[
  {
    "path": ".github/CONTRIBUTING.md",
    "content": "We only accept bug reports and pull requests in GitHub.\nIf you have a support question about how to use thinreports, please [ask on GitHub Discussions](https://github.com/thinreports/thinreports/discussions).\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# To get started with Dependabot version updates, you'll need to specify which\n# package ecosystems to update and where the package manifests are located.\n# Please see the documentation for all configuration options:\n# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\n\nversion: 2\nupdates:\n  - package-ecosystem: github-actions\n    directory: /\n    schedule:\n      interval: daily\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\n\non:\n  push:\n    branches:\n      - main\n      - \"dev**\"\n  pull_request:\n\njobs:\n  setup:\n    name: Ruby ${{ matrix.ruby }} with prawn ${{ matrix.prawn }}\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        ruby:\n          - \"3.0\"\n          - \"3.1\"\n          - \"3.2\"\n          - \"3.3\"\n        prawn:\n          - \"2.4\"\n          - \"2.5\"\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: hidakatsuya/action-setup-diff-pdf@v1\n        with:\n          diff-pdf-version: \"0.5\"\n\n      - name: Set up Ruby ${{ matrix.ruby }}\n        uses: ruby/setup-ruby@v1\n        with:\n          ruby-version: ${{ matrix.ruby }}\n          bundler-cache: true\n\n      - name: Install dependencies\n        run: bundle install --gemfile gemfiles/prawn-${{ matrix.prawn }}.gemfile --jobs 4 --retry 3\n\n      - name: Run tests for main\n        run: bundle exec rake test:main\n\n      - name: Run tests for basic report\n        run: xvfb-run -a bundle exec rake test:basic_report\n\n      - name: Run tests for section report\n        run: xvfb-run -a bundle exec rake test:section_report\n"
  },
  {
    "path": ".gitignore",
    "content": "Gemfile.lock\n*.gem\n*.pdf\n.bundle\n.yardoc\ndoc\n!/test/**/*/expect.pdf\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## main (Unreleased)\n\n## 0.14.2\n\nChanges:\n\n* Add base64 and bigdecimal to the gemspec #133\n* Remove matrix gem version constraint\n\n## 0.14.1\n\nEnhancements:\n\n* Add overflow-wrap option #129\n\n## 0.14.0\n\nBreaking Changes:\n\n* Drop Ruby 2.7 support\n\nBug Fixes:\n\n* Fix LoadError: cannot load such file -- matrix #131\n\n## 0.13.1\n\nBug Fixes:\n\n * allow title argument to be specified in Report.generate method #127\n\n## 0.13.0\n\nBreaking Changes:\n\n * Drop Ruby 2.5,2.6,JRuby support\n * Drop Prawn 2.2, 2.3 support\n * Moved Basic Format implementation to `Thinreports::BasicReport` namespace\n   * `Thinreports::Report` and `Thinreports::Layout` are defined as aliases for `Thinreports::BasicReport::Report` and `Thinreports::BasicReport::Layout` respectively, but other than those can be a destructive change if you rely on internal implementations\n\nEnhancements:\n\n * Allow any string to be set to the title attribute of the PDF document metadata #125\n * Add Ruby 3.1, 3.2 support\n\nNotes:\n\n * thinreports gem has opted in to the [\"MFA required to publish\" setting](https://guides.rubygems.org/mfa-requirement-opt-in/) on Rubygems.org\n\n## 0.12.1\n\nBug Fixes:\n\n * Fix argument of Thinreports::Report.generate in Ruby 3.0 #116 [@sada]\n\n## 0.12.0\n\nBreaking Changes:\n\n * Drop Ruby 2.4 support #108, #109\n\nEnhancements:\n\n * Ruby 3.0 support #108, #109\n * Prawn 2.4 support #108, #109\n\n## 0.11.0\n\nBreaking Changes:\n\n * Dropped Ruby 2.1 support\n * Dropped Ruby 2.2 support\n * Dropped Ruby 2.3 support\n * Formatter of a text-block works even with multiple-line (#95)\n\nEnhancements:\n\n * Ruby 2.7.0 support\n * Support Pathname layout option on `Thinreports::Report` #99 [@meganemura]\n\nBug Fixes:\n\n * Fixed: thousands separation is applied to decimal part #95\n\n## 0.10.3\n\nBug Fixes:\n\n * Fixed: corner-radius of Rect is not applied correctly #93\n\n## 0.10.2\n\nBug Fixes:\n\n * Fixed: Prawn::Errors::UnknownFont error occured: \"is not a known font\" #89\n\n## 0.10.1\n\nBug Fixes:\n\n * Fixed a bug that an error occurred on page break in other list when there is a list with page-break disabled #87 [@meganemura]\n\n## 0.10.0\n\n * Thinreports requires Prawn 2.2\n * Dropped Ruby 1.9.3 and 2.0.0 support\n * Fixed a bug line-height of a text line-wrapped is broken #36 [@tkobayashi0330]\n * Remove deprecated top-module `ThinReports`\n * Remove `config.convert_palleted_transparency_png` option\n * Remove `config.generator.default` option\n * Deprecate `:report` and `:generator` argument of `Thinreports::Report.generate`\n\n### Remove config.convert_palleted_transparency_png option\n\nPNG image with indexed transparency has been supported since Prawn version 2.0. And now, thinreports requires Prawn 2.2+, so the unique support in thinreports is no longer needed.\n\n### Remove deprecated top-module ThinReports\n\nPlease use `Thinreports` instead.\n\n## 0.9.1\n\n * Fixed bug that line-height of text-block is always set to 0 #68\n * Fixed a referenced text-block not rendered #68\n * Fixed #66 an error occurred when render list #68\n\n## 0.9.0\n\n * Drop support for layout file saved with Editor v0.7 or lower #62\n * New format for layout file and deprecate old format #35\n * Fixed fail in rendering a static image #61\n * Make possible to set an image-data to image-block item #65\n * Remove old way to define callback of list #54\n * Remove `config.eudc_fonts=` option #53\n * Deprecate `config.convert_palleted_transparency_png` option #49\n\n### Drop support for layout file saved with Editor v0.7 or lower\n\nGenerator v0.9 or higher can't load the layout file saved with Editor v0.7 or lower.\n\n### New format for layout file and deprecate old format\n\nThis is a BIG internal change.\n\nThinreports has two format types for layout file now:\n\n  1. Old format generated by Thinreports Editor 0.8.x or lower\n  2. New format generated by Thinreports Editor 0.9.x or higher\n\nthinreports-generator will supports as below:\n\n| Generator  | Format type(1) | Format type(2) |\n| ---------- | :------------: | :------------: |\n| =< 0.8     |        o       |        x       |\n| 0.9, 1.0   |        o       |        o       |\n| >= 1.1     |        x       |        o       |\n\nSee https://github.com/thinreports/thinreports/issues/4 for further details.\n\n### Make possible to set an image-data to image-block item\n\nThe following code works fine now.\n\n```ruby\npng_image = StringIO.new(png_data)\npage.item(:image_block).src(png_image)\n\nrequire 'open-uri'\nopen('http://example.com/image.png') do |image_data|\n  page.item(:image_block).src(image_data)\nend\n```\n\n### Remove old way to define callback of list\n\nThe block of `Report::Base#use_layout` never performed:\n\n```ruby\nreport.use_layout 'foo.tlf' do |config|\n  config.events.on(:page_create) { ... }\n  config.list.events.on(:footer_insert) { ... }\nend\n```\n\n`List#store` and `List#events` has been removed:\n\n```ruby\nreport.list.store.foo += 1 # => NoMethodError\nreport.list.events.on(:footer_insert) { ... } # => NoMethodError\n```\n\n`Layout::Base#config` has been removed:\n\n```ruby\nreport.default_layout.config { ... } # => NoMethodError\n```\n\nYou can use the following method instead:\n\n * `Report::Base#on_page_create`\n * `List#on_page_finalize`\n * `List#on_footer_insert`\n * `List#on_page_footer_insert`\n\nSee https://github.com/thinreports/thinreports-generator/tree/master/examples/list_events.\n\n### Remove config.eudc_fonts= option\n\n```ruby\nThinreports.config.eudc_fonts = true # => NoMethodError\n```\n\nYou can use `config.fallback_fonts` instead.\n\n### Deprecate config.convert_palleted_transparency_png option\n\n```ruby\nThinreports.config.convert_palleted_transparency_png = true # => warn \"[DEPRECATION]\"\n```\n\nThis is option to enable palette-based transparency PNG support.\nThe option will be removed in version 1.0, but thinreports will support the feature by default.\nPlease see [PR#32](https://github.com/thinreports/thinreports-generator/pull/32) for detailed the feature.\n\n## 0.8.2\n\n  * Fixed: some Ruby warnings (#40, #41, #43) [Akira Matsuda, Katsuya Hidaka]\n  * Some code improvements\n\n## 0.8.1\n\n### Add OPTIONAL feature for converting a palette-based PNG w. transparency\n\nThis feature is **DISABLED** by default. Please see [PR#32](https://github.com/thinreports/thinreports-generator/pull/32) for further details.\n\n## 0.8.0\n\nThis release is a stepping stone to next major version 1.0.0 release.\n\n  * Upgrade to Prawn 1.3 and drop support for Ruby 1.8.7 (#11)\n  * Change name of root module to Thinreports from ThinReports (#15)\n  * Implement `Item#value=` method (#20)\n  * Implement new list callbacks (#17)\n  * Implement `page[:item_id]=` as alias for `page.item(:item_id).value=` (#22)\n  * Support font-size style for Text and TextBlock (#23)\n  * Support for setting the default fallback font (#7)\n  * Remove `Report#generate_file` method (#13)\n  * Deprecate `Report#events`, and implement new callbacks (#18)\n  * Deprecate `List#events`, recommend to use `List#on_page_finalize` callback or create manually (#9)\n\n### Upgrade to Prawn 1.3 and drop support for Ruby 1.8.7\n\nWe have dropped support for MRI 1.8.7 and 1.8 mode JRuby by upgrading to Prawn 1.3.\nCurrently supported versions are MRI 1.9.3 and 2.0.0 or higher, JRuby(1.9 mode) 1.7 or higher.\n\n### Change name of root module to Thinreports from ThinReports\n\nWe have changed name of root module to `Thinreports` from `ThinReports`.\nOld name `ThinReports` has been enabling as alias, but it will be removed\nin the next major release.\n\n### Deprecate `List#events` and `List#store`\n\n`List#events` and `List#store` have been deprecated.\n\n```ruby\nreport.layout.config.list do |list|\n  list.events.on :page_footer_insert do |e|\n    # ...\n  end\n  # => warn: \"[DEPRECATION] ...\"\n\n  list.events.on :footer_insert do |e|\n    # ...\n  end\n  # => warn: \"[DEPRECATION] ...\"\n\n  list.events.on :page_finalize do |e|\n    # ...\n  end\n  # => warn: \"[DEPRECATION] ...\"\nend\n\nlist.store.price += 0 # => warn: \"[DEPRECATION] ...\"\n```\n\nPlease use new callbacks instead:\n\n```ruby\nreport.list do |list|\n  price = 0\n\n  list.on_page_footer_insert do |footer|\n    footer.item(:price).value = price\n  end\n\n  list.on_footer_insert do |footer|\n    # ...\n  end\n\n  list.on_page_finalize do\n    # ...\n  end\nend\n```\n\nSee [Issue #17](https://github.com/thinreports/thinreports-generator/issues/17), [Issue #9](https://github.com/thinreports/thinreports-generator/issues/9) and [examples/list_events](https://github.com/thinreports/thinreports-generator/tree/master/examples/list_events) for further details.\n\n### Deprecate `Report#events`, and implement new callbacks\n\n`Report#events` has been deprecated:\n\n```ruby\nreport.events.on :page_create do |e|\n  e.page.item(:text1).value('Text1')\nend\n# => warn: \"[DEPRECATION] ...\"\n\nreport.events.on :generate do |e|\n  e.pages.each do |page|\n    page.item(:text2).value('Text2')\n  end\nend\n# => warn: \"[DEPRECATION] ...\"\n```\n\nPlease use `Report#on_page_create` callback instead.\nHowever `Report#on_generate` callback has not been implemented,\nbut you can do the same things using `Report#pages` method.\n\n```ruby\nreport.on_page_create do |page|\n  page.item(:text1).value('Text1')\nend\n\nreport.pages.each do |page|\n  page.item(:text2).value('Text2')\nend\n\nreport.generate filename: 'foo.pdf'\n```\n\nSee [Issue #18](https://github.com/thinreports/thinreports-generator/issues/18) for further details.\n\n### Implement `page[:item_id]=` as alias for `page.item(:item_id).value=` (#22)\n\n```ruby\n# New setter, same as `page.item(:text_block).value = 'tblock value'`\npage[:text_block] = 'tblock value'\n# New getter, same as `page.item(:text_block).value`\npage[:text_block] # => <Tblock>\npage[:text_block].value # => \"tblock value\"\npage.item(:text_block).value # => \"tblock value\"\n\npage[:image_block] = '/path/to/image.png'\npage[:image_block].src # => \"/path/to/image.png\"\npage.item(:image_block).src # => \"/path/to/image.png\"\n```\n\nSee [Issue #22](https://github.com/thinreports/thinreports-generator/issues/22) for further details.\n\n### Implement `Item#value=` method\n\n```ruby\npage.item(:text_block).value('value')\npage.item(:text_block).value = 'value'\npage.item(:image_block).src('/path/to/image.tlf')\npage.item(:image_block).src = '/path/to/image.tlf'\n```\n\nSee [Issue #20](https://github.com/thinreports/thinreports-generator/issues/20) for further details.\n\n### Support font-size style for Text and TextBlock\n\n```ruby\npage.item(:text).style(:font_size, 20)\npage.item(:text_block).style(:font_size, 20)\npage.item(:text_block).style(:font_size) # => 20\n```\n\nSee [Issue #23](https://github.com/thinreports/thinreports-generator/issues/23) for further details.\n\n### Support for setting the default fallback font\n\nPlease see [Issue #7](https://github.com/thinreports/thinreports-generator/issues/7) for further details.\n\n## 0.7.7.1\n\n  * No release for generator\n\n## 0.7.7\n\n### Features\n\n  * ページ番号ツール [Katsuya Hidaka]\n  * New \"Word-wrap\" property of TextBlock [Katsuya Hidaka]\n  * B4/B5 の ISO サイズを追加 [Takumi FUJISE / Minoru Maeda / Katsuya Hidaka]\n  * generate filename: 'foo.pdf' を実装、#generate_file を非推奨へ [Katsuya Hidaka]\n  * start_new_page layout: 'file.tlf' でもデフォルトレイアウトが設定されるよう改善 [Eito Katagiri / Katsuya Hidaka]\n\n### Bug fixes\n\n  * Report#use_layout で list の設定を行うとエラーが発生する [Katsuya Hidaka]\n  * Layout::Format#page_margin_right が不正な値を返す [Katsuya Hidaka]\n  * セキュリティを設定した PDF を印刷すると \"このページにはエラーがあります...\" メッセージが表示される [Katsuya Hidaka]\n  * B4 サイズで出力した PDF の用紙サイズが正しくない [Takumi FUJISE / Katsuya Hidaka]\n\n## 0.7.6\n\n### Features\n\n  * デフォルトレイアウトを書き換え可能へ変更 [Katsuya Hidaka]\n\n### Bug fixes\n\n  * Fix raise NoMethodError when has no default layout [Katsuya Hidaka]\n\n## 0.7.5\n\n### Features\n\n  * テキストブロックのオーバフロープロパティ [Katsuya Hidaka]\n  * list メソッドのデフォルト id と Report#list の追加 [Katsuya Hidaka]\n\n### Bug fixes\n\n  * gem install 時にRDoc生成時のエラーが表示される場合がある [Katsuya Hidaka]\n  * エディターにて一覧表ツールのヘッダーを使わない場合の動作について [吉田 和弘 / Katsuya Hidaka]\n\n## 0.7.0\n\n### Features\n\n  * Listに :page_finalize イベントを追加\n  * ダイナミックスタイルの拡充\n  * イメージブロックの実装\n  * Tblockで行間、横位置、縦位置、文字間隔の指定を可能に\n  * Prawn 0.12.0 を採用\n  * メタ情報のタイトルに反映\n  * Example Test環境の構築\n  * 外字の埋め込みサポート\n  * clean taskの削除\n  * YARD Docのテンプレート追加\n  * ロードするprawnのバージョンを固定\n  * .generate, .generate_fileメソッドのオプション指定をフラット化\n  * 単行モードテキストブロックがレイアウトで定義した「高さ」の影響を受けないように\n  * PXD形式の出力フォーマット廃止とデフォルトタイプの導入\n  * $KCODEによる文字カウント処理の改善\n  * List#headerの挙動を改善\n  * Errors::UnknownItemId 時のエラーメッセージを分かりやすく\n  * テスト漏れに対するテストコード作成とテスト\n\n### Bug fixes\n\n  * フッターが挿入時、リスト領域をオーバフローしない場合でも改ページされる場合がある\n  * Tblockで基本書式のみ設定されている場合、その書式が反映されない\n  * Tblockがフォントサイズに対して小さすぎる場合にエラー\n"
  },
  {
    "path": "Gemfile",
    "content": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\ngemspec\n\ngem 'rake'\ngem 'minitest'\ngem 'mocha'\ngem 'pdf-inspector'\ngem 'pdf_matcher-testing'\n\n# suppress warning: assigned but unused variable - y1\n# https://github.com/yob/pdf-reader/pull/502\ngem 'pdf-reader', github: 'yob/pdf-reader', ref: 'dc7e6e46e1d842486bd34288df087b590e8a7b38'\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Matsukei Co.,Ltd.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Thinreports Generator\n\n[![Gem Version](https://badge.fury.io/rb/thinreports.svg)](http://badge.fury.io/rb/thinreports)\n[![Test](https://github.com/thinreports/thinreports-generator/workflows/Test/badge.svg)](https://github.com/thinreports/thinreports-generator/actions)\n\nA Ruby library for [Thinreports](https://github.com/thinreports/thinreports).\n\n## Prerequisites\n\n### Supported Versions\n\n- Ruby 3.0, 3.1, 3.2, 3.3\n- Prawn 2.4+\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'thinreports'\n```\n\nAnd then execute:\n\n    $ bundle install\n\nOr install it yourself as:\n\n    $ gem install thinreports\n\n\n## Getting Started\n\nFirst of all, check out [the README](https://github.com/thinreports/thinreports#getting-started) for an overview of Thinreports, its features, the two template formats available, and a complete example with template files and Ruby code.\n\n## Usage\n\nSee [the README](https://github.com/thinreports/thinreports) for usage of the Section Format.\n\n### Basic Format\n\nThe template file (`.tlf`) must be created in the [Thinreports Basic Editor](https://github.com/thinreports/thinreports-basic-editor/).\n\n```ruby\nrequire 'thinreports'\n\nreport = Thinreports::Report.new layout: 'report.tlf'\n\nreport.start_new_page do\n  item(:title).value('Thinreports')\nend\n\nreport.start_new_page do |page|\n  # Item Finder\n  page.item(:item_id) # => Item object\n  page[:item_id]      # => Item object\n\n  # Text block\n  page.item(:text_block).value('Pure Ruby')\n  page.item(:text_block).value = 'Pure Ruby'\n  page[:text_block] = 'Pure Ruby'\n  page.item('text_block').set('value', color: '#0000ff')\n  page.item(:text_block).format_enabled(false)\n\n  # Image block\n  page.item(:image_block).src('/path/to/image.png')\n  page.item(:image_block).src = '/path/to/image.png'\n  page[:image_block] = '/path/to/image.png'\n  require 'open-uri'\n  page.item(:image_block).src(open('http://www.thinreports.org/assets/logos/thinreports-logo.png'))\n\n  # Attributes\n  page.item(:any).hide\n  page.item(:any).show\n  page.item(:any).visible(true)\n  page.item(:any).visible? # => true\n  page.item(:any).id # => \"any\"\n\n  # Styles\n  page.item(:text).style(:color, 'red')\n  page.item(:text).style(:bold, true)\n  page.item(:text).style(:italic, true)\n  page.item(:text).style(:linethrough, true)\n  page.item(:text).style(:underline, true)\n  page.item(:text).style(:font_size, 20)\n\n  page.item(:text).style(:align, :left or :center or :right)\n  page.item(:text).style(:valign, :top or :center or :bottom)\n\n  page.item(:rectangle).style(:border_color, '#ff0000')\n                       .style(:border_width, 1)\n                       .style(:fill_color, '#ffffff')\n\n  # Bulk setting of styles\n  page.item(:text).styles(color: '#00000', align: :right)\n\n  # Bulk setting of values\n  page.values text_block_a: 'value', text_block_b: 'value'\n\n  # Helpers\n  page.item_exists?(:existing_id)  # => true\n  page.item_exists?('existing_id') # => true\n  page.item_exists?(:unknown_id)   # => false\nend\n\nreport.generate(filename: 'report.pdf')\n```\n\n```ruby\nThinreports::Report.generate(filename: 'report.pdf', layout: 'report.tlf') do |report|\n  report.start_new_page do |page|\n    # :\n  end\nend\n```\n\n#### Report and Page\n\n```ruby\nreport = Thinreports::Report.new layout: 'foo.tlf'\n\n3.times { report.start_new_page }\n\n# Returns all pages\nreport.pages # => [<Report::Page>, <Report::Page>, <Report::Page>]\n# Returns number of pages\nreport.page_count # => 3\n\n# Add a blank page\nreport.add_blank_page\n\nreport.pages.last # => Report::BlankPage\n```\n\n#### Using multiple layouts\n\n```ruby\nreport = Thinreports::Report.new\n\nreport.use_layout '/path/to/default.tlf', default: true\nreport.use_layout '/path/to/other1.tlf', id: :other\n\nreport.start_new_page do |page|\n  # use '/path/to/default.tlf' layout\nend\n\nreport.start_new_page layout: :other do |page|\n  # use '/path/to/other1.tlf' layout\nend\n\nreport.start_new_page layout: '/path/to/other2.tlf' do |page|\n  # use '/path/to/other2.tlf' layout\nend\n```\n\n#### Callbacks\n\n```ruby\nreport = Thinreports::Report.new layout: 'foo.tlf'\n\n# It will be called before finalizing each page\nreport.on_page_create do |page|\n  page.item(:text).value('Text for all pages')\nend\n```\n\nSee also [basic_report/features/report_callbacks](https://github.com/thinreports/thinreports-generator/tree/main/test/basic_report/features/report_callbacks).\n\n#### List\n\n```ruby\nreport = Thinreports::Report.new layout: 'list.tlf'\n\nreport.list.header do |header|\n  header.item(:text_block).value('Title')\nend\n\n10.times do |n|\n  report.list.add_row do |row|\n    row.item(:text_block).value(n)\n  end\nend\n\nreport.generate(filename: 'list.pdf')\n```\n\n```ruby\nreport = Thinreports::Report.new layout: 'list_with_footer.tlf'\n\nreport.list do |list|\n  total_price = 0\n  price_per_page = 0\n\n  list.on_page_finalize do\n    total_price += price_per_page\n    price_per_page = 0\n  end\n\n  list.on_page_footer_insert do |footer|\n    footer.values price: price_per_page\n  end\n\n  list.on_footer_insert do |footer|\n    footer.item(:price).value(total_price)\n  end\n\n  [100, 200, 300].each do |price|\n    list.add_row do |row|\n      row[:price] = price\n    end\n    price_per_page += price\n  end\nend\n```\n\nSee also  [basic_report/features/list_events](https://github.com/thinreports/thinreports-generator/tree/main/test/basic_report/features/list_events).\n\n#### Page Number\n\n```ruby\n# Setting starting number of page\nreport.start_page_number_from 5\n\n# Setting whether to count new page\nreport.start_new_page count: true # default\nreport.start_new_page count: false\n\n# Change styles\nreport.start_new_page do |page|\n  page.item(:pageno).hide\n  page.item(:pageno).show\n  page.item(:pageno).visible(false)\n  page.item(:pageno).styles(color: 'red', bold: true)\nend\n```\n\nSee also [basic_report/features/page_number](https://github.com/thinreports/thinreports-generator/blob/main/test/basic_report/features/page_number) and [basic_report/features/page_number_with_list](https://github.com/thinreports/thinreports-generator/blob/main/test/basic_report/features/page_number_with_list).\n\n#### Configuring fallback fonts\n\n```ruby\nThinreports.configure do |config|\n  config.fallback_fonts = '/path/to/fallback.ttf'\nend\n\nThinreports.config.fallback_fonts = ['/path/to/font_a.ttf', '/path/to/font_b.ttf']\n```\n\nSee also [basic_report/features/eudc](https://github.com/thinreports/thinreports-generator/blob/main/test/basic_report/features/eudc).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/thinreports/thinreports-generator. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/thinreports/thinreports/blob/main/CODE_OF_CONDUCT.md).\n\n## Development\n\n### Feature test requires diff-pdf command\n\nIn order to run feature test, you need to install [diff-pdf](https://github.com/vslavik/diff-pdf) in your environment, or you can run test in the docker container as below.\n\n### How to develop in Docker container\n\nYou can use the Docker container for development. This container contains the libraries required for testing, such as diff-pdf.\n\n```\n$ docker pull ghcr.io/hidakatsuya/ruby-with-diff-pdf:latest\n$ docker run -v $PWD:/src:cached -it ghcr.io/hidakatsuya/ruby-with-diff-pdf bash\n\n> /src#\n```\n\nYou can run test:\n\n```\n> /src# bundle install\n> /src# bundle exec rake test\n```\n\n## Releasing Generator\n\n1. Update the version number in `version.rb`\n2. Update `CHANGELOG.md` and `README.md` (if needed)\n3. Create the Release PR like #105\n4. Merge the PR\n5. Is the main CI green? If not, make it green\n6. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to rubygems.org\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Copyright\n\n(c) 2021 [Matsukei Co.,Ltd](http://www.matsukei.co.jp).\n"
  },
  {
    "path": "Rakefile",
    "content": "require 'bundler/gem_tasks'\nrequire 'rake/testtask'\n\ntask default: :test\n\nRake::TestTask.new do |t|\n  t.name = 'test:main'\n  t.description = 'Run tests for main'\n  t.libs << 'test/main'\n  t.test_files = Dir['test/main/**/test_*.rb']\nend\n\nRake::TestTask.new do |t|\n  t.name = 'test:basic_report'\n  t.description = 'Run tests for basic report'\n  t.libs << 'test' << 'test/basic_report'\n  t.test_files = Dir['test/basic_report/**/test_*.rb']\nend\n\nRake::TestTask.new do |t|\n  t.name = 'test:section_report'\n  t.description = 'Run tests for section report'\n  t.libs << 'test' << 'test/section_report'\n  t.test_files = Dir['test/section_report/**/test_*.rb']\nend\n\ndesc 'Run all tests'\ntask test: %i(test:main test:basic_report test:section_report)\n"
  },
  {
    "path": "fonts/IPA_Font_License_Agreement_v1.0.txt",
    "content": "﻿--------------------------------------------------\r\nIPA Font License Agreement v1.0 <Japanese/English>\r\n--------------------------------------------------\r\n\r\nIPAフォントライセンスv1.0\r\n\r\n許諾者は、この使用許諾（以下「本契約」といいます。）に定める条件の下で、許諾プログラム（1条に定義するところによります。）を提供します。受領者（1条に定義するところによります。）が、許諾プログラムを使用し、複製し、または頒布する行為、その他、本契約に定める権利の利用を行った場合、受領者は本契約に同意したものと見なします。\r\n\r\n\r\n第1条　用語の定義\r\n\r\n本契約において、次の各号に掲げる用語は、当該各号に定めるところによります。\r\n\r\n1.「デジタル･フォント･プログラム」とは、フォントを含み、レンダリングしまたは表示するために用いられるコンピュータ・プログラムをいいます。\r\n2.「許諾プログラム」とは、許諾者が本契約の下で許諾するデジタル･フォント･プログラムをいいます。\r\n3.「派生プログラム」とは、許諾プログラムの一部または全部を、改変し、加除修正等し、入れ替え、その他翻案したデジタル･フォント･プログラムをいい、許諾プログラムの一部もしくは全部から文字情報を取り出し、またはデジタル･ドキュメント･ファイルからエンベッドされたフォントを取り出し、取り出された文字情報をそのまま、または改変をなして新たなデジタル・フォント・プログラムとして製作されたものを含みます。\r\n4.「デジタル・コンテンツ」とは、デジタル・データ形式によってエンド・ユーザに提供される制作物のことをいい、動画・静止画等の映像コンテンツおよびテレビ番組等の放送コンテンツ、ならびに文字テキスト、画像、図形等を含んで構成された制作物を含みます。\r\n5.「デジタル・ドキュメント・ファイル」とは、PDFファイルその他、各種ソフトウェア･プログラムによって製作されたデジタル・コンテンツであって、その中にフォントを表示するために許諾プログラムの全部または一部が埋め込まれた（エンベッドされた）ものをいいます。フォントが「エンベッドされた」とは、当該フォントが埋め込まれた特定の「デジタル・ドキュメント・ファイル」においてのみ表示されるために使用されている状態を指し、その特定の「デジタル・ドキュメント・ファイル」以外でフォントを表示するために使用できるデジタル・フォント・プログラムに含まれている場合と区別されます。\r\n6.「コンピュータ｣とは、本契約においては、サーバを含みます。\r\n7.「複製その他の利用」とは、複製、譲渡、頒布、貸与、公衆送信、上映、展示、翻案その他の利用をいいます。\r\n8.「受領者」とは、許諾プログラムを本契約の下で受領した人をいい、受領者から許諾プログラムを受領した人を含みます。\r\n\r\n第２条 使用許諾の付与\r\n\r\n許諾者は受領者に対し、本契約の条項に従い、すべての国で、許諾プログラムを使用することを許諾します。ただし、許諾プログラムに存在する一切の権利はすべて許諾者が保有しています。本契約は、本契約で明示的に定められている場合を除き、いかなる意味においても、許諾者が保有する許諾プログラムに関する一切の権利および、いかなる商標、商号、もしくはサービス・マークに関する権利をも受領者に移転するものではありません。\r\n\r\n1.受領者は本契約に定める条件に従い、許諾プログラムを任意の数のコンピュータにインストールし、当該コンピュータで使用することができます。\r\n2.受領者はコンピュータにインストールされた許諾プログラムをそのまま、または改変を行ったうえで、印刷物およびデジタル・コンテンツにおいて、文字テキスト表現等として使用することができます。\r\n3.受領者は前項の定めに従い作成した印刷物およびデジタル・コンテンツにつき、その商用・非商用の別、および放送、通信、各種記録メディアなどの媒体の形式を問わず、複製その他の利用をすることができます。\r\n4.受領者がデジタル・ドキュメント・ファイルからエンベッドされたフォントを取り出して派生プログラムを作成した場合には、かかる派生プログラムは本契約に定める条件に従う必要があります。\r\n5.許諾プログラムのエンベッドされたフォントがデジタル・ドキュメント・ファイル内のデジタル・コンテンツをレンダリングするためにのみ使用される場合において、受領者が当該デジタル・ドキュメント・ファイルを複製その他の利用をする場合には、受領者はかかる行為に関しては本契約の下ではいかなる義務をも負いません。\r\n6.受領者は、3条2項の定めに従い、商用・非商用を問わず、許諾プログラムをそのままの状態で改変することなく複製して第三者への譲渡し、公衆送信し、その他の方法で再配布することができます(以下、「再配布」といいます。)。\r\n7.受領者は、上記の許諾プログラムについて定められた条件と同様の条件に従って、派生プログラムを作成し、使用し、複製し、再配布することができます。ただし、受領者が派生プログラムを再配布する場合には、3条1項の定めに従うものとします。\r\n\r\n第３条　制限\r\n\r\n前条により付与された使用許諾は、以下の制限に服します。\r\n\r\n1.派生プログラムが前条4項及び7項に基づき再配布される場合には、以下の全ての条件を満たさなければなりません。\r\n　(1)派生プログラムを再配布する際には、下記もまた、当該派生プログラムと一緒に再配布され、オンラインで提供され、または、郵送費・媒体及び取扱手数料の合計を超えない実費と引き換えに媒体を郵送する方法により提供されなければなりません。\r\n　　(a)派生プログラムの写し; および\r\n　　(b)派生プログラムを作成する過程でフォント開発プログラムによって作成された追加のファイルであって派生プログラムをさらに加工するにあたって利用できるファイルが存在すれば、当該ファイル\r\n　(2)派生プログラムの受領者が、派生プログラムを、このライセンスの下で最初にリリースされた許諾プログラム（以下、「オリジナル・プログラム」といいます。）に置き換えることができる方法を再配布するものとします。かかる方法は、オリジナル・ファイルからの差分ファイルの提供、または、派生プログラムをオリジナル・プログラムに置き換える方法を示す指示の提供などが考えられます。\r\n　(3)派生プログラムを、本契約書に定められた条件の下でライセンスしなければなりません。\r\n　(4)派生プログラムのプログラム名、フォント名またはファイル名として、許諾プログラムが用いているのと同一の名称、またはこれを含む名称を使用してはなりません。\r\n　(5)本項の要件を満たすためにオンラインで提供し、または媒体を郵送する方法で提供されるものは、その提供を希望するいかなる者によっても提供が可能です。\r\n2.受領者が前条6項に基づき許諾プログラムを再配布する場合には、以下の全ての条件を満たさなければなりません。\r\n　(1)許諾プログラムの名称を変更してはなりません。\r\n　(2)許諾プログラムに加工その他の改変を加えてはなりません。\r\n　(3)本契約の写しを許諾プログラムに添付しなければなりません。\r\n3.許諾プログラムは、現状有姿で提供されており、許諾プログラムまたは派生プログラムについて、許諾者は一切の明示または黙示の保証（権利の所在、非侵害、商品性、特定目的への適合性を含むがこれに限られません）を行いません。いかなる場合にも、その原因を問わず、契約上の責任か厳格責任か過失その他の不法行為責任かにかかわらず、また事前に通知されたか否かにかかわらず、許諾者は、許諾プログラムまたは派生プログラムのインストール、使用、複製その他の利用または本契約上の権利の行使によって生じた一切の損害（直接・間接・付随的・特別・拡大・懲罰的または結果的損害）（商品またはサービスの代替品の調達、システム障害から生じた損害、現存するデータまたはプログラムの紛失または破損、逸失利益を含むがこれに限られません）について責任を負いません。\r\n4.許諾プログラムまたは派生プログラムのインストール、使用、複製その他の利用に関して、許諾者は技術的な質問や問い合わせ等に対する対応その他、いかなるユーザ・サポートをも行う義務を負いません。\r\n\r\n第４条　契約の終了\r\n\r\n1.本契約の有効期間は、受領者が許諾プログラムを受領した時に開始し、受領者が許諾プログラムを何らかの方法で保持する限り続くものとします。\r\n2.前項の定めにかかわらず、受領者が本契約に定める各条項に違反したときは、本契約は、何らの催告を要することなく、自動的に終了し、当該受領者はそれ以後、許諾プログラムおよび派生プログラムを一切使用しまたは複製その他の利用をすることができないものとします。ただし、かかる契約の終了は、当該違反した受領者から許諾プログラムまたは派生プログラムの配布を受けた受領者の権利に影響を及ぼすものではありません。\r\n\r\n第５条　準拠法\r\n\r\n1.IPAは、本契約の変更バージョンまたは新しいバージョンを公表することができます。その場合には、受領者は、許諾プログラムまたは派生プログラムの使用、複製その他の利用または再配布にあたり、本契約または変更後の契約のいずれかを選択することができます。その他、上記に記載されていない条項に関しては日本の著作権法および関連法規に従うものとします。\r\n2.本契約は、日本法に基づき解釈されます。\r\n\r\n\r\n----------\r\n\r\nIPA Font License Agreement v1.0\r\n\r\nThe Licensor provides the Licensed Program (as defined in Article 1 below) under the terms of this license agreement (“Agreement”).  Any use, reproduction or distribution of the Licensed Program, or any exercise of rights under this Agreement by a Recipient (as defined in Article 1 below) constitutes the Recipient's acceptance of this Agreement. \r\n\r\nArticle 1 (Definitions)\r\n1.“Digital Font Program” shall mean a computer program containing, or used to render or display fonts.\r\n2.“Licensed Program” shall mean a Digital Font Program licensed by the Licensor under this Agreement.\r\n3.“Derived Program” shall mean a Digital Font Program created as a result of a modification, addition, deletion, replacement or any other adaptation to or of a part or all of the Licensed Program, and includes a case where a Digital Font Program newly created by retrieving font information from a part or all of the Licensed Program or Embedded Fonts from a Digital Document File with or without modification of the retrieved font information. \r\n4.“Digital Content” shall mean products provided to end users in the form of digital data, including video content, motion and/or still pictures, TV programs or other broadcasting content and products consisting of character text, pictures, photographic images, graphic symbols and/or the like.\r\n5.“Digital Document File” shall mean a PDF file or other Digital Content created by various software programs in which a part or all of the Licensed Program becomes embedded or contained in the file for the display of the font (“Embedded Fonts”).  Embedded Fonts are used only in the display of characters in the particular Digital Document File within which they are embedded, and shall be distinguished from those in any Digital Font Program, which may be used for display of characters outside that particular Digital Document File.\r\n6.“Computer” shall include a server in this Agreement.\r\n7.“Reproduction and Other Exploitation” shall mean reproduction, transfer, distribution, lease, public transmission, presentation, exhibition, adaptation and any other exploitation.\r\n8.“Recipient” shall mean anyone who receives the Licensed Program under this Agreement, including one that receives the Licensed Program from a Recipient.\r\n\r\nArticle 2 (Grant of License)\r\nThe Licensor grants to the Recipient a license to use the Licensed Program in any and all countries in accordance with each of the provisions set forth in this Agreement. However, any and all rights underlying in the Licensed Program shall be held by the Licensor. In no sense is this Agreement intended to transfer any right relating to the Licensed Program held by the Licensor except as specifically set forth herein or any right relating to any trademark, trade name, or service mark to the Recipient.\r\n\r\n1.The Recipient may install the Licensed Program on any number of Computers and use the same in accordance with the provisions set forth in this Agreement.\r\n2.The Recipient may use the Licensed Program, with or without modification in printed materials or in Digital Content as an expression of character texts or the like.\r\n3.The Recipient may conduct Reproduction and Other Exploitation of the printed materials and Digital Content created in accordance with the preceding Paragraph, for commercial or non-commercial purposes and in any form of media including but not limited to broadcasting, communication and various recording media.\r\n4.If any Recipient extracts Embedded Fonts from a Digital Document File to create a Derived Program, such Derived Program shall be subject to the terms of this agreement.\r\n5.If any Recipient performs Reproduction or Other Exploitation of a Digital Document File in which Embedded Fonts of the Licensed Program are used only for rendering the Digital Content within such Digital Document File then such Recipient shall have no further obligations under this Agreement in relation to such actions.\r\n6.The Recipient may reproduce the Licensed Program as is without modification and transfer such copies, publicly transmit or otherwise redistribute the Licensed Program to a third party for commercial or non-commercial purposes (“Redistribute”), in accordance with the provisions set forth in Article 3 Paragraph 2.\r\n7.The Recipient may create, use, reproduce and/or Redistribute a Derived Program under the terms stated above for the Licensed Program: provided, that the Recipient shall follow the provisions set forth in Article 3 Paragraph 1 when Redistributing the Derived Program. \r\n\r\nArticle 3 (Restriction)\r\nThe license granted in the preceding Article shall be subject to the following restrictions:\r\n\r\n1.If a Derived Program is Redistributed pursuant to Paragraph 4 and 7 of the preceding Article, the following conditions must be met :\r\n　(1)The following must be also Redistributed together with the Derived Program, or be made available online or by means of mailing mechanisms in exchange for a cost which does not exceed the total costs of postage, storage medium and handling fees:\r\n　　(a)a copy of the Derived Program; and\r\n　　(b)any additional file created by the font developing program in the course of creating the Derived Program that can be used for further modification of the Derived Program, if any. \r\n　(2)It is required to also Redistribute means to enable recipients of the Derived Program to replace the Derived Program with the Licensed Program first released under this License (the “Original Program”).  Such means may be to provide a difference file from the Original Program, or instructions setting out a method to replace the Derived Program with the Original Program. \r\n　(3)The Recipient must license the Derived Program under the terms and conditions of this Agreement.\r\n　(4)No one may use or include the name of the Licensed Program as a program name, font name or file name of the Derived Program. \r\n　(5)Any material to be made available online or by means of mailing a medium to satisfy the requirements of this paragraph may be provided, verbatim, by any party wishing to do so.\r\n2.If the Recipient Redistributes the Licensed Program pursuant to Paragraph 6 of the preceding Article, the Recipient shall meet all of the following conditions:\r\n　(1)The Recipient may not change the name of the Licensed Program.\r\n　(2)The Recipient may not alter or otherwise modify the Licensed Program.\r\n　(3)The Recipient must attach a copy of this Agreement to the Licensed Program.\r\n3.THIS LICENSED PROGRAM IS PROVIDED BY THE LICENSOR “AS IS” AND ANY EXPRESSED OR IMPLIED WARRANTY AS TO THE LICENSED PROGRAM OR ANY DERIVED PROGRAM, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE LICENSOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXTENDED, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO; PROCUREMENT OF SUBSTITUTED GOODS OR SERVICE; DAMAGES ARISING FROM SYSTEM FAILURE; LOSS OR CORRUPTION OF EXISTING DATA OR PROGRAM; LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE INSTALLATION, USE, THE REPRODUCTION OR OTHER EXPLOITATION OF THE LICENSED PROGRAM OR ANY DERIVED PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\r\n4.The Licensor is under no obligation to respond to any technical questions or inquiries, or provide any other user support in connection with the installation, use or the Reproduction and Other Exploitation of the Licensed Program or Derived Programs thereof.\r\n\r\nArticle 4 (Termination of Agreement)\r\n1.The term of this Agreement shall begin from the time of receipt of the Licensed Program by the Recipient and shall continue as long as the Recipient retains any such Licensed Program in any way.\r\n2.Notwithstanding the provision set forth in the preceding Paragraph, in the event of the breach of any of the provisions set forth in this Agreement by the Recipient, this Agreement shall automatically terminate without any notice. In the case of such termination, the Recipient may not use or conduct Reproduction and Other Exploitation of the Licensed Program or a Derived Program: provided that such termination shall not affect any rights of any other Recipient receiving the Licensed Program or the Derived Program from such Recipient who breached this Agreement.\r\n\r\nArticle 5 (Governing Law)\r\n1.IPA may publish revised and/or new versions of this License.  In such an event, the Recipient may select either this Agreement or any subsequent version of the Agreement in using, conducting the Reproduction and Other Exploitation of, or Redistributing the Licensed Program or a Derived Program. Other matters not specified above shall be subject to the Copyright Law of Japan and other related laws and regulations of Japan.\r\n2.This Agreement shall be construed under the laws of Japan.\r\n\r\n"
  },
  {
    "path": "gemfiles/prawn-2.4.gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'prawn', '~> 2.4.0'\n\ngemspec path: '../'\n"
  },
  {
    "path": "gemfiles/prawn-2.5.gemfile",
    "content": "source 'https://rubygems.org'\n\ngem 'prawn', '~> 2.5.0'\n\ngemspec path: '../'\n\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/errors.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Errors\n      class Basic < ::StandardError\n      end\n\n      class UnknownShapeStyleName < Basic\n        def initialize(style, availables)\n          super(\"The specified style name, '#{style}', cannot be used. \" \\\n                \"The available styles are #{availables.map { |s| \":#{s}\" }.join(', ')}.\")\n        end\n      end\n\n      class UnknownShapeType < Basic\n      end\n\n      class UnknownFormatterType < Basic\n      end\n\n      class LayoutFileNotFound < Basic\n      end\n\n      class FontFileNotFound < Basic\n      end\n\n      class NoRegisteredLayoutFound < Basic\n      end\n\n      class UnknownItemId < Basic\n        def initialize(id, item_type = 'Basic')\n          super(\"The layout does not have a #{item_type} Item with id '#{id}'.\")\n        end\n      end\n\n      class DisabledListSection < Basic\n        def initialize(section)\n          super(\"The #{section} section is disabled.\")\n        end\n      end\n\n      class UnknownLayoutId < Basic\n      end\n\n      class UnsupportedColorName < Basic\n      end\n\n      class InvalidLayoutFormat < Basic\n      end\n\n      class IncompatibleLayoutFormat < Basic\n        def initialize(filename, fileversion, required_rules)\n          super(\"Generator #{Thinreports::VERSION} can not be built this file, \" \\\n                \"'#{File.basename(filename)}'. \" \\\n                \"This file is updated in the Editor of version '#{fileversion}', \" \\\n                \"but Generator requires version #{required_rules}.\")\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/format/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Format\n        # @abstract\n        class Base\n          class << self\n            def config_reader(*configs, &block)\n              each_configs(*configs) do |m, location|\n                define_read_method(m, location, &block)\n              end\n            end\n\n            def config_checker(check, *configs)\n              checker = ->(val) { val == check }\n              each_configs(*configs) do |m, location|\n                define_read_method(:\"#{m}?\", location, &checker)\n              end\n            end\n\n            def config_writer(*configs)\n              each_configs(*configs) do |m, location|\n                define_write_method(m, location)\n              end\n            end\n\n            def config_accessor(*configs, &block)\n              config_reader(*configs, &block)\n              config_writer(*configs)\n            end\n\n            private\n\n            def define_read_method(m, location = nil, &block)\n              define_method(m) do\n                read(*location, &block)\n              end\n            end\n\n            def define_write_method(m, location = nil)\n              define_method(:\"#{m}=\") do |value|\n                write(value, *location)\n              end\n            end\n\n            def each_configs(*configs, &block)\n              c = configs.first.is_a?(::Hash) ? configs.first : (configs || [])\n              c.each do |m, location|\n                block.call(m, location || [m.to_s])\n              end\n            end\n          end\n\n          def initialize(config, &block)\n            @config = config\n            block.call(self) if ::Kernel.block_given?\n          end\n\n          def attributes\n            @config\n          end\n\n          private\n\n          def find(*keys)\n            if keys.empty?\n              @config\n            else\n              keys.inject(@config) do |c, k|\n                c.is_a?(::Hash) ? c[k] : (break c)\n              end\n            end\n          end\n\n          def write(value, *keys)\n            key = keys.pop\n            owner = find(*keys)\n            owner[key] = value\n          end\n\n          def read(*keys, &block)\n            value = find(*keys)\n            ::Kernel.block_given? ? block.call(value) : value\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/base/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Base\n          # @abstract\n          class Interface\n            include Utils\n            extend  Forwardable\n\n            def self.internal_delegators(*args)\n              def_delegators :internal, *args\n            end\n            private_class_method :internal_delegators\n\n            attr_reader :internal\n\n            def initialize(parent, format, internal = nil)\n              @internal = internal || init_internal(parent, format)\n            end\n\n            def copy(parent)\n              self.class.new(parent, internal.format, internal.copy(parent))\n            end\n\n            private\n\n            # @param [Thinreports::BasicReport::Report::Page, Thinreports::BasicReport::Core::Shape::List::SectionInterface] parent\n            # @param [Thinreports::BasicReport::Core::Shape::Basic::Format] format\n            # @return [Thinreports::BasicReport::Core::Shape::Basic::Internal]\n            # @abstract\n            def init_internal(parent, format)\n              raise NotImplementedError\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/base/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Base\n          # @abstract\n          class Internal\n            include Utils\n            extend  Forwardable\n\n            def self.format_delegators(*args)\n              def_delegators :format, *args\n            end\n            private_class_method :format_delegators\n\n            attr_reader :parent\n            attr_reader :format\n            attr_writer :style\n            attr_accessor :states\n\n            def initialize(parent, format)\n              @parent = parent\n              @format = format\n              @states = {}\n              @style = nil\n\n              @finalized_attributes = nil\n            end\n\n            def style\n              raise NotImplementedError\n            end\n\n            def copy(new_parent, &block)\n              new_internal = self.class.new(new_parent, format)\n              new_internal.style = style.copy\n              new_internal.states = deep_copy(states)\n\n              block.call(new_internal) if block_given?\n              new_internal\n            end\n\n            def type_of?\n              raise NotImplementedError\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/base.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'forwardable'\n\nrequire_relative 'base/internal'\nrequire_relative 'base/interface'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic/block_format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          class BlockFormat < Basic::Format\n            config_reader :value\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic/block_interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          class BlockInterface < Basic::Interface\n            # @overload value(val)\n            #   Set a val\n            #   @param [Object] val\n            #   @return [self]\n            # @overload value\n            #   Return the value\n            #   @return [Object]\n            def value(*args)\n              if args.empty?\n                internal.read_value\n              else\n                internal.write_value(args.first)\n                self\n              end\n            end\n\n            # @param [Object] val\n            def value=(val)\n              value(val)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic/block_internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          class BlockInternal < Basic::Internal\n            format_delegators :box\n\n            def style\n              @style ||= Style::Basic.new(format)\n            end\n\n            def read_value\n              states.key?(:value) ? states[:value] : format.value.dup\n            end\n            alias value read_value\n\n            def write_value(val)\n              states[:value] = val\n            end\n\n            def real_value\n              read_value\n            end\n\n            def type_of?(type_name)\n              type_name == :block\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          class Format < Core::Format::Base\n            include Utils\n\n            config_reader :type, :id\n            config_reader :style\n            config_checker true, :display\n            config_reader follow_stretch: %w[follow-stretch]\n\n            def affect_bottom_margin?\n              attributes.fetch('affect-bottom-margin', true)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          class Interface < Base::Interface\n            internal_delegators :type\n\n            # @return [String]\n            def id\n              internal.id.dup\n            end\n\n            # @param [Boolean] visibility\n            # @return [self]\n            def visible(visibility)\n              internal.style.visible = visibility\n              self\n            end\n\n            # @return [Boolean]\n            def visible?\n              internal.style.visible\n            end\n\n            # @overload style(style_name)\n            #   @param [Symbol] style_name\n            #   @return [Object]\n            # @overload style(style_name, value)\n            #   @param [Symbol] style_name\n            #   @param [String, Symbol, Number, Array] value\n            #   @return [self]\n            # @overload style(style_name, value1, value2)\n            #   @param [Symbol] style_name\n            #   @param [String, Number] value1\n            #   @param [String, Number] value2\n            #   @return [self]\n            def style(*args)\n              case args.length\n              when 1\n                internal.style[args.first]\n              when 2\n                internal.style[args.first] = args.last\n                self\n              when 3\n                internal.style[args.shift] = args\n                self\n              else\n                raise ArgumentError, '#style requires 1 or 2, 3 arguments'\n              end\n            end\n\n            # @param [Hash] settings style_name: value\n            # @return [self]\n            def styles(settings)\n              settings.each { |args| style(*args) }\n              self\n            end\n\n            # @see #visible\n            # @return [self]\n            def hide\n              visible(false)\n              self\n            end\n\n            # @see #visible\n            # @return [self]\n            def show\n              visible(true)\n              self\n            end\n\n            private\n\n            # @see Thinreports::BasicReport::Core::Shape::Base::Interface#init_internal\n            def init_internal(parent, format)\n              Basic::Internal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          class Internal < Base::Internal\n            # Delegate to Format's methods\n            format_delegators :id, :type\n\n            def style\n              @style ||= Style::Graphic.new(format)\n            end\n\n            def type_of?(type_name)\n              [:basic, type].include?(type_name)\n            end\n\n            def identifier\n              \"#{id}#{style.identifier}\"\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/basic.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Basic\n          TYPE_NAMES = %w[line rect ellipse image].freeze\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'basic/format'\nrequire_relative 'basic/internal'\nrequire_relative 'basic/interface'\nrequire_relative 'basic/block_format'\nrequire_relative 'basic/block_internal'\nrequire_relative 'basic/block_interface'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/image_block/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module ImageBlock\n          class Format < Basic::BlockFormat\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/image_block/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module ImageBlock\n          class Interface < Basic::BlockInterface\n            # @see #value\n            alias src value\n            # @see #value=\n            alias src= value=\n\n            private\n\n            # @see Thinreports::BasicReport::Core::Shape::Base::Interface#init_internal\n            def init_internal(parent, format)\n              ImageBlock::Internal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/image_block/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module ImageBlock\n          class Internal < Basic::BlockInternal\n            alias src read_value\n\n            def type_of?(type_name)\n              type_name == ImageBlock::TYPE_NAME || super\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/image_block.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module ImageBlock\n          TYPE_NAME = 'image-block'\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'image_block/format'\nrequire_relative 'image_block/internal'\nrequire_relative 'image_block/interface'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class Format < Basic::Format\n            config_reader height: %w[content-height]\n            config_checker true, auto_page_break: %w[auto-page-break]\n\n            # @deprecated\n            config_reader :header,\n                          :detail,\n                          :footer\n            # @deprecated\n            config_reader page_footer: %w[page-footer]\n\n            config_checker true, has_header: %w[header enabled]\n            config_checker true, has_footer: %w[footer enabled]\n            config_checker true, has_page_footer: %w[page-footer enabled]\n\n            config_reader page_footer_height: %w[page-footer height]\n            config_reader footer_height: %w[footer height]\n            config_reader header_height: %w[header height]\n            config_reader detail_height: %w[detail height]\n\n            attr_reader :sections\n\n            def initialize(*)\n              super\n              initialize_sections\n            end\n\n            # @param [Symbol] section_name\n            # @return [Hash]\n            # @deprecated\n            def section(section_name)\n              __send__(section_name)\n            end\n\n            # @param [Symbol] section_name\n            # @return [Boolean]\n            def has_section?(section_name)\n              section_name == :detail ? true : __send__(:\"has_#{section_name}?\")\n            end\n\n            # @param [Symbol] section_name\n            # @return [Numeric]\n            def section_height(section_name)\n              has_section?(section_name) ? __send__(:\"#{section_name}_height\") : 0\n            end\n\n            # @param [:detai, :header, :page_footer, :footer] section_name\n            # @return [Numeric]\n            def section_base_position_top(section_name)\n              section = @sections[section_name]\n              return 0 unless has_section?(section_name)\n\n              top = section.relative_top\n\n              case section_name\n              when :page_footer\n                top - section_height(:detail)\n              when :footer\n                top - section_height(:detail) - section_height(:page_footer)\n              else\n                top\n              end\n            end\n\n            private\n\n            def initialize_sections\n              @sections = {\n                detail: List::SectionFormat.new(attributes['detail'])\n              }\n\n              @sections[:header] = section_format('header') if has_section?(:header)\n              @sections[:page_footer] = section_format('page-footer') if has_section?(:page_footer)\n              @sections[:footer] = section_format('footer') if has_section?(:footer)\n            end\n\n            def section_format(section_name)\n              List::SectionFormat.new(attributes[section_name])\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/manager.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class Manager\n            include Utils\n\n            # @return [Thinreports::BasicReport::Core::Shape:::List::Page]\n            attr_reader :current_page\n\n            # @return [Thinreports::BasicReport::Core::Shape::List::PageState]\n            attr_reader :current_page_state\n\n            # @return [Integer]\n            attr_accessor :page_count\n\n            # @return [Proc]\n            attr_accessor :page_finalize_handler\n\n            # @return [Proc]\n            attr_accessor :page_footer_handler\n\n            # @return [Proc]\n            attr_accessor :footer_handler\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::Page] page\n            def initialize(page)\n              switch_current!(page)\n\n              @finalized = false\n              @page_count = 0\n\n              @page_finalize_handler = nil\n              @page_footer_handler = nil\n              @footer_handler = nil\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::Page] page\n            # @return [Thinreports::BasicReport::Core::Shape::List::Manager]\n            def switch_current!(page)\n              @current_page = page\n              @current_page_state = page.internal\n              self\n            end\n\n            # @yield [new_list]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::Page] new_list\n            def change_new_page(&block)\n              finalize_page\n              new_page = report.internal.copy_page\n\n              block.call(new_page.list(current_page.id)) if block_given?\n            end\n\n            # @param [Hash] values ({})\n            # @yield [header]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::SectionInterface] header\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            # @raise [Thinreports::BasicReport::Errors::DisabledListSection]\n            def build_header(values = {}, &block)\n              raise Thinreports::BasicReport::Errors::DisabledListSection, 'header' unless format.has_header?\n\n              current_page_state.header ||= init_section(:header)\n              build_section(header_section, values, &block)\n            end\n\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def header_section\n              current_page_state.header\n            end\n\n            # @param (see #build_section)\n            # @return [Boolean]\n            def add_detail(values = {}, &block)\n              return false if current_page_state.finalized?\n\n              successful = true\n\n              if overflow_with?(:detail)\n                if auto_page_break?\n                  change_new_page do |new_list|\n                    new_list.manager.insert_detail(values, &block)\n                  end\n                else\n                  finalize\n                  successful = false\n                end\n              else\n                insert_detail(values, &block)\n              end\n              successful\n            end\n\n            # @param values (see Thinreports::BasicReport::Core::Shape::Manager::Target#values)\n            # @yield [section,]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::SectionInterface] section\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def insert_detail(values = {}, &block)\n              detail = build_section(init_section(:detail), values, &block)\n              insert_row(detail)\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::SectionInterface] row\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def insert_row(row)\n              row.internal.move_top_to(current_page_state.height)\n\n              current_page_state.rows << row\n              current_page_state.height += row.height\n              row\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::SectionInterface] section\n            # @param values (see Thinreports::BasicReport::Core::Shape::Manager::Target#values)\n            # @yield [section,]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::SectionInterface] section\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def build_section(section, values = {}, &block)\n              section.values(values)\n              call_block_in(section, &block)\n            end\n\n            # @param [Symbol] section_name\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def init_section(section_name)\n              List::SectionInterface.new(current_page,\n                                         format.sections[section_name],\n                                         section_name)\n            end\n\n            # @param [Symbol] section_name\n            # @return [Boolean]\n            def overflow_with?(section_name = :detail)\n              max_height = page_max_height\n\n              max_height += format.section_height(:page_footer) if section_name == :footer && format.has_page_footer?\n\n              height = format.section_height(section_name)\n              (current_page_state.height + height) > max_height\n            end\n\n            # @return [Numeric]\n            def page_max_height\n              @page_max_height ||= begin\n                h = format.height\n                h -= format.section_height(:page_footer)\n                h -= format.section_height(:footer) unless auto_page_break?\n                h\n              end\n            end\n\n            # @return [Boolean]\n            def auto_page_break?\n              format.auto_page_break?\n            end\n\n            # @param [Hash] options\n            # @option options [Boolean] :ignore_page_footer (false)\n            #   When the switch of the page is generated by #finalize, it is used.\n            def finalize_page(options = {})\n              return if current_page_state.finalized?\n\n              build_header if format.has_header?\n\n              finalize_page_footer unless options[:ignore_page_footer]\n\n              current_page_state.finalized!\n              @page_finalize_handler.call if @page_finalize_handler\n\n              @page_count += 1\n              current_page_state.no = @page_count\n            end\n\n            def finalize_page_footer\n              return unless format.has_page_footer?\n\n              page_footer = init_section(:page_footer)\n              insert_row(page_footer)\n\n              @page_footer_handler.call(page_footer) if @page_footer_handler\n            end\n\n            def finalize\n              return if finalized?\n              finalize_page\n\n              if format.has_footer?\n                footer = init_section(:footer)\n\n                @footer_handler.call(footer) if @footer_handler\n\n                if auto_page_break? && overflow_with?(:footer)\n                  change_new_page do |new_list|\n                    new_list.manager.insert_row(footer)\n                    new_list.manager.finalize_page(ignore_page_footer: true)\n                  end\n                else\n                  insert_row(footer)\n                end\n              end\n              @finalized = true\n            end\n\n            # @return [Boolean]\n            def finalized?\n              @finalized\n            end\n\n            # @return [Thinreports::BasicReport::Report::Base]\n            def report\n              current_page_state.parent.report\n            end\n\n            # @return [Thinreports::BasicReport::Layout::Base]\n            def layout\n              current_page_state.parent.layout\n            end\n\n            # @return [Thinreports::BasicReport::Core::Shape::List::Format]\n            def format\n              current_page_state.format\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/page.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class Page < Basic::Interface\n            extend Forwardable\n\n            attr_reader :manager\n\n            # @param [Thinreports::BasicReport::Report::Page] parent\n            # @param [Thinreports::BasicReport::Core::Shape::Basic::Format] format\n            # @param [Thinreports::BasicReport::Core::Shape::List::PageState] internal (nil)\n            # @param [Thinreports::BasicReport::Core::Shape::List::Manager] manager (nil)\n            def initialize(parent, format, internal = nil, manager = nil)\n              super(parent, format, internal)\n\n              @manager =\n                if manager\n                  manager.switch_current!(self)\n                else\n                  List::Manager.new(self)\n                end\n\n              # Set a reference to List::PageState List::Manager\n              self.internal.manager = self.manager\n            end\n\n            # @see Thinreports::BasicReport::Core::Shape::List::Manager#build_header\n            def_delegator :manager, :build_header, :header\n\n            def on_page_finalize(&block)\n              manager.page_finalize_handler = block\n            end\n\n            # @yield [page_footer]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::SectionInterface] page_footer\n            def on_page_footer_insert(&block)\n              manager.page_footer_handler = block\n            end\n\n            # @yield [footer]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::SectionInterface] footer\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def on_footer_insert(&block)\n              manager.footer_handler = block\n            end\n\n            # @param [Hash] values ({})\n            # @yield [row,]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::List::SectionInterface] row\n            # @return [Boolean]\n            def add_row(values = {}, &block)\n              manager.add_detail(values, &block)\n            end\n\n            # If enabled, the auto-page-break of the list will force a page break\n            # at the time this method is called. Otherwise, this list will be finalized.\n            def page_break\n              if manager.auto_page_break?\n                manager.change_new_page\n              else\n                manager.finalize_page\n              end\n            end\n            alias finalize page_break\n\n            # @return [Boolean] Returns true if list has overflowed\n            #   when `list#add_row` is called at the next time.\n            def overflow?\n              manager.overflow_with?(:detail)\n            end\n\n            # @param [Thinreports::BasicReport::Report::Page] new_parent\n            # @return [Thinreports::BasicReport::Core::Shape::List::Page]\n            def copy(new_parent)\n              if manager.auto_page_break?\n                new_list = self.class.new(new_parent, internal.format,\n                                          nil, manager)\n              else\n                manager.finalize\n\n                new_list = self.class.new(new_parent, internal.format,\n                                          internal.copy(new_parent), manager)\n                internal.rows.each do |row|\n                  new_list.internal.rows << row.copy(new_list)\n                end\n                new_list.internal.finalized!\n              end\n\n              new_list.internal.header = internal.header.copy(new_list) if internal.format.has_header?\n              new_list\n            end\n\n            private\n\n            # @see Thinreports::BasicReport::Core::Shape::Base::Interface#init_internal\n            def init_internal(parent, format)\n              List::PageState.new(parent, format)\n            end\n          end\n\n          # Alias to List::Page.\n          # @see Thinreports::BasicReport::Core::Shape::List::Page\n          List::Interface = List::Page\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/page_state.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class PageState < Basic::Internal\n            attr_reader :rows\n\n            attr_accessor :height\n            attr_accessor :header\n            attr_accessor :no\n            attr_accessor :manager\n\n            def initialize(*args)\n              super(*args)\n\n              @rows = []\n              @height = 0\n              @finalized = false\n\n              @header = nil\n            end\n\n            def style\n              @style ||= Style::Basic.new(format)\n            end\n\n            def finalized?\n              @finalized\n            end\n\n            def finalized!\n              @finalized = true\n            end\n\n            def type_of?(type_name)\n              type_name == List::TYPE_NAME\n            end\n          end\n\n          # Alias to List::PageState.\n          # @see Thinreports::BasicReport::Core::Shape::List::PageState\n          List::Internal = List::PageState\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/section_format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class SectionFormat < Shape::Manager::Format\n            config_reader :height\n            config_reader relative_left: %w[translate x],\n                          relative_top: %w[translate y]\n            config_reader :style\n\n            # For compatible 0.8.x format API\n            config_checker true, display: %w[enabled]\n\n            def initialize(*)\n              super\n              initialize_items(attributes['items'])\n            end\n\n            private\n\n            def initialize_items(item_schemas)\n              item_schemas.each do |item_schema|\n                id, type = item_schema.values_at 'id', 'type'\n                next if id.empty?\n\n                shapes[id.to_sym] = Core::Shape::Format(type).new(item_schema)\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/section_interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class SectionInterface < Base::Interface\n            include Core::Shape::Manager::Target\n\n            undef_method :list\n            internal_delegators :height\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::Page] parent\n            # @param [Thinreports::BasicReport::Core::Shape::List::SectionFormat] format\n            # @param [Symbol] section_name\n            def initialize(parent, format, section_name)\n              super(parent, format)\n              internal.section_name = section_name\n\n              initialize_manager(format) do |f|\n                Core::Shape::Interface(self, f)\n              end\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::Page] parent\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInterface]\n            def copy(parent)\n              new_sec = super\n              new_sec.internal.section_name = internal.section_name\n\n              manager.shapes.each do |id, shape|\n                new_sec.manager.shapes[id] = shape.copy(new_sec)\n              end\n              new_sec\n            end\n\n            private\n\n            # @param parent (see #initialize)\n            # @param format (see #initialize)\n            # @return [Thinreports::BasicReport::Core::Shape::List::SectionInternal]\n            def init_internal(parent, format)\n              List::SectionInternal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list/section_internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          class SectionInternal < Base::Internal\n            format_delegators :height,\n                              :relative_left\n\n            # @return [Symbol]\n            attr_accessor :section_name\n\n            def style\n              @style ||= Style::Base.new(format)\n            end\n\n            # @param [Numeric] ry\n            def move_top_to(ry)\n              states[:relative_top] = ry\n            end\n\n            # @return [Float]\n            def relative_top\n              states[:relative_top] || 0\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/list.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module List\n          TYPE_NAME = 'list'\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'list/format'\nrequire_relative 'list/manager'\n\nrequire_relative 'list/page'\nrequire_relative 'list/page_state'\n\nrequire_relative 'list/section_format'\nrequire_relative 'list/section_interface'\nrequire_relative 'list/section_internal'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/manager/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Manager\n          class Format < Core::Format::Base\n            # @return [Symbol, Integer]\n            attr_reader :identifier\n\n            def initialize(config, id = nil, &block)\n              super(config, &block)\n              @identifier = id || object_id\n            end\n\n            def find_shape(id)\n              shapes[id]\n            end\n\n            def has_shape?(id)\n              shapes.key?(id)\n            end\n\n            def shapes\n              @shapes ||= {}\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/manager/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Manager\n          class Internal\n            include Utils\n\n            attr_reader :format\n            attr_reader :shapes\n            attr_reader :lists\n\n            # @param [Thinreports::BasicReport::Core::Manager::Format] format\n            # @param [Proc] init_item_handler\n            def initialize(format, init_item_handler)\n              @format = format\n              @shapes = {}\n              @lists = {}\n              @init_item_handler = init_item_handler\n            end\n\n            # @param [String, Symbol] id\n            # @return [Thinreports::BasicReport::Core::Shape::Basic::Format]\n            def find_format(id)\n              format.find_shape(id.to_sym)\n            end\n\n            # @param [String, Symbol] id\n            # @param limit (see #valid_type?)\n            def find_item(id, limit = {})\n              id = id.to_sym\n\n              if shapes.key?(id)\n                shape = shapes[id]\n                valid_type?(shape.type, limit) ? shape : nil\n              elsif find_format(id)\n                shape_format = find_format(id)\n                return nil unless valid_type?(shape_format.type, limit)\n\n                shape = init_item(shape_format)\n                shapes[id] = shape\n\n                shape\n              end\n            end\n\n            # @param [String, Symbol] id\n            # @return [Thinreports::BasicReport::Core::Shape::Base::Interface, nil]\n            def final_shape(id)\n              shape = shapes[id]\n\n              # When shape was found in registry.\n              if shape\n                return nil unless shape.visible?\n\n                # In the case of TextBlock or ImageBlock.\n                if shape.internal.type_of?(:block)\n                  blank_value?(shape.internal.real_value) ? nil : shape\n                else\n                  shape\n                end\n              # When shape was not found in registry.\n              elsif format.has_shape?(id)\n                shape_format = find_format(id)\n                return nil unless shape_format.display?\n\n                case shape_format.type\n                # In the case of TextBlock.\n                when TextBlock::TYPE_NAME\n                  return nil if !shape_format.has_reference? && blank_value?(shape_format.value)\n                  init_item(shape_format)\n                # In the case of ImageBlock, Return the nil constantly.\n                when ImageBlock::TYPE_NAME\n                  nil\n                else\n                  init_item(shape_format)\n                end\n              end\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::Basic::Format] format\n            def init_item(format)\n              @init_item_handler.call(format)\n            end\n\n            # @param [String] type\n            # @param [Hash] limit\n            # @option limit [String] :only\n            # @option limit [String] :except\n            # @return [Booldan]\n            def valid_type?(type, limit = {})\n              return true if limit.empty?\n\n              if limit[:only]\n                type == limit[:only]\n              elsif limit[:except]\n                type != limit[:except]\n              else\n                raise ArgumentError\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/manager/target.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Manager\n          module Target\n            include Utils\n\n            attr_reader :manager\n\n            # @example\n            #   item(:title).value('Title').style(:fill, 'red')\n            #\n            #   item(:title) do\n            #     value('Title')\n            #     style(:fill, 'red')\n            #   end\n            #\n            #   item(:title) do |t|\n            #     t.value('Title')\n            #     t.style(:fill, 'red')\n            #   end\n            #   item(:list)       # => Error: UnknownItemId\n            #   item(:unknown_id) # => Error: UnknownItemId\n            # @param [String, Symbol] id\n            # @yield [item,]\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::Base::Interface] item\n            # @raise [Thinreports::BasicReport::Errors::UnknownItemId]\n            # @return [Thinreports::BasicReport::Core::Shape::Base::Interface]\n            def item(id, &block)\n              shape = find_item(id, except: Core::Shape::List::TYPE_NAME)\n\n              raise Thinreports::BasicReport::Errors::UnknownItemId, id unless shape\n\n              call_block_in(shape, &block)\n            end\n\n            # @example\n            #   page[:text_block].style(:bold, true)\n            #   page[:rect].style(:border_color, 'red')\n            #\n            #   page[:list]       # => Error: UnknownItemId\n            #   page[:unknown_id] # => Error: UnknownItemId\n            # @param [String, Symbol] id\n            # @return [Thinreports::BasicReport::Core::Shape::Base::Interface]\n            def [](id)\n              item(id)\n            end\n\n            # @example\n            #   page[:text_block]  = 'Title'\n            #   page[:image_block] = '/path/to/image.png'\n            #   page[:list]        = 'value' # => Error: UnknownItemId\n            #   page[:ellipse]     = 'value' # => Error: NoMethodError #value\n            #   page[:unknown_id]  = 'value' # => Error: UnknownItemId\n            # @param [String, Symbol] id\n            # @param [Object] value\n            def []=(id, value)\n              item(id).value = value\n            end\n\n            # @example\n            #   page.values text_block: 'value',\n            #               image_block: '/path/to/image.png'\n            # @param [Hash] item_values\n            def values(item_values)\n              item_values.each { |id, val| item(id).value(val) }\n            end\n\n            # @param [Symbol, String] id\n            # @return [Boolean]\n            def item_exists?(id)\n              !manager.find_format(id).nil?\n            end\n            alias exists? item_exists?\n\n            # @example\n            #   report.list.add_row do |row|\n            #     row.item(:price).value(1000)\n            #   end\n            #\n            #   report.list(:list_id) # => List\n            #   report.list(:text_block_id) # => raises UnknownItemId\n            # @see #item\n            def list(id = nil, &block)\n              shape = find_item(id ||= :default, only: Core::Shape::List::TYPE_NAME)\n\n              raise Thinreports::BasicReport::Errors::UnknownItemId.new(id, 'List') unless shape\n\n              manager.lists[id.to_sym] ||= shape\n              call_block_in(shape, &block)\n            end\n\n            private\n\n            # @param format (see Thinreports::BasicReport::Core::Shape::Manager::Internal#initialize)\n            # @yield [format] Handler for initialize item.\n            # @yieldparam [Thinreports::BasicReport::Core::Shape::Basic::Format] format\n            def initialize_manager(format, &block)\n              @manager = Manager::Internal.new(format, block)\n            end\n\n            # @see Thinreports::BasicReport::Core::Shape::Manager::Internal#find_item\n            def find_item(id, limit = {})\n              manager.find_item(id, limit)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/manager.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'manager/format'\nrequire_relative 'manager/target'\nrequire_relative 'manager/internal'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/page_number/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module PageNumber\n          class Format < Basic::Format\n            config_reader :target\n            config_reader default_format: %w[format]\n\n            # For saving compatible 0.8.x format API\n            config_reader overflow: %w[style overflow]\n\n            def id\n              @id ||= blank_value?(read('id')) ? self.class.next_default_id : read('id')\n            end\n\n            def for_report?\n              blank_value?(target)\n            end\n\n            def self.next_default_id\n              @id_counter ||= 0\n              \"__pageno#{@id_counter += 1}\"\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/page_number/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module PageNumber\n          class Interface < Basic::Interface\n            internal_delegators :reset_format\n\n            def format(*args)\n              if args.empty?\n                internal.read_format\n              else\n                internal.write_format(args.first)\n                self\n              end\n            end\n\n            private\n\n            # @see Thinreports::BasicReport::Core::Shape::Base::Interface#init_internal\n            def init_internal(parent, format)\n              PageNumber::Internal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/page_number/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module PageNumber\n          class Internal < Basic::Internal\n            format_delegators :box, :for_report?\n\n            def read_format\n              states.key?(:format) ? states[:format] : format.default_format.dup\n            end\n\n            def reset_format\n              states.delete(:format)\n            end\n\n            def write_format(format)\n              states[:format] = format.to_s\n            end\n\n            def build_format(page_no, page_count)\n              return '' if blank_value?(read_format)\n\n              if start_page_number > 1\n                page_no += start_page_number - 1\n                page_count += start_page_number - 1\n              end\n\n              read_format.dup.tap do |f|\n                f.gsub! '{page}', page_no.to_s\n                f.gsub! '{total}', page_count.to_s\n              end\n            end\n\n            def style\n              @style ||= PageNumber::Style.new(format)\n            end\n\n            def type_of?(type_name)\n              type_name == PageNumber::TYPE_NAME\n            end\n\n            def start_page_number\n              for_report? ? parent.report.start_page_number : 1\n            end\n          end\n\n          class Style < Style::Text\n            accessible_styles.delete :valign\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/page_number.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module PageNumber\n          TYPE_NAME = 'page-number'\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'page_number/format'\nrequire_relative 'page_number/internal'\nrequire_relative 'page_number/interface'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/stack_view/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module StackView\n          class Format < Basic::Format\n            attr_reader :rows\n\n            def initialize(*)\n              super\n              initialize_rows\n            end\n\n            private\n\n            def initialize_rows\n              @rows = []\n              attributes['rows'].each do |row|\n                @rows << StackView::RowFormat.new(row)\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/stack_view/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module StackView\n          class Interface < Basic::Interface\n            private\n\n            def init_internal(parent, format)\n              StackView::Internal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/stack_view/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module StackView\n          class Internal < Basic::Internal\n            def initialize(parent, format)\n              super\n              @rows = []\n            end\n\n            attr_accessor :rows\n\n            def type_of?(type_name)\n              type_name == StackView::TYPE_NAME\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/stack_view/row_format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module StackView\n          class RowFormat < Core::Format::Base\n            config_reader :id\n            config_reader :height\n            config_checker true, :display\n            config_checker true, auto_stretch: 'auto-stretch'\n\n            attr_reader :items\n\n            def initialize(*)\n              super\n              @items = []\n              @item_with_ids = {}\n              initialize_items(attributes['items'])\n            end\n\n            def find_item(id)\n              @item_with_ids[id.to_sym]\n            end\n\n            private\n\n            def initialize_items(item_schemas)\n              item_schemas.each do |item_schema|\n                item = Core::Shape::Format(item_schema['type']).new(item_schema)\n                @items << item\n                @item_with_ids[item.id.to_sym] = item unless item.id.empty?\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/stack_view.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module StackView\n          TYPE_NAME = 'stack-view'.freeze\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'stack_view/format'\nrequire_relative 'stack_view/interface'\nrequire_relative 'stack_view/internal'\n\nrequire_relative 'stack_view/row_format'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/style/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Style\n          class Base\n            include Utils\n\n            class << self\n              # @param [Symbol] style_method\n              # @param [String] style\n              # @return [void]\n              def style_accessor(style_method, style)\n                style_reader(style_method, style)\n                style_writer(style_method, style)\n              end\n\n              # @see .style_accessor\n              def style_reader(style_method, style)\n                define_method(style_method) do\n                  read_internal_style(style)\n                end\n              end\n\n              # @see .style_accessor\n              def style_writer(style_method, style)\n                define_method(:\"#{style_method}=\") do |value|\n                  write_internal_style(style, value)\n                end\n              end\n\n              # @param [Array<Symbol>] style_methods\n              def style_accessible(*style_methods)\n                accessible_styles.concat(style_methods)\n              end\n\n              # @return [Array<Symbol>]\n              def accessible_styles\n                @accessible_styles ||= []\n              end\n\n              def inherited(s)\n                s.accessible_styles.concat(accessible_styles.dup)\n              end\n            end\n\n            # @return [Hash]\n            attr_accessor :styles\n            # @see .accessible_styles\n            attr_reader :accessible_styles\n\n            # @param [Thinreports::BasicReport::Core::Format::Base] format\n            # @param [Hash] default_styles ({})\n            def initialize(format, default_styles = {})\n              @format = format\n              @styles = default_styles\n              @base_styles = format.style || {}\n\n              @accessible_styles = self.class.accessible_styles.dup\n            end\n\n            # @param [Symbol] style_method\n            # @return [Object]\n            def [](style_method)\n              verify_style_method(style_method)\n              send(style_method.to_sym)\n            end\n\n            # @param [Symbol] style_method\n            # @param [String, Number, Array<String, Number>] value\n            def []=(style_method, value)\n              verify_style_method(style_method)\n              send(:\"#{style_method}=\", value)\n            end\n\n            # @return [String]\n            def identifier\n              create_identifier(@styles)\n            end\n\n            # @return [self]\n            def copy\n              self.class.new(@format, @styles.empty? ? {} : deep_copy(@styles))\n            end\n\n            # @param [String, Symbol] style\n            # @return [Object]\n            def read_internal_style(style)\n              style = style.to_s\n              @styles.key?(style) ? @styles[style] : @base_styles[style]\n            end\n\n            # @param [String, Symbol] style\n            # @param [Object] value\n            def write_internal_style(style, value)\n              @styles[style.to_s] = value\n            end\n\n            # @param [Symbol] style_method\n            # @return [Boolean]\n            def has_style?(style_method)\n              accessible_styles.include?(style_method)\n            end\n\n            # @return [Hash]\n            def finalized_styles\n              @finalized_styles ||=\n                if @styles.empty?\n                  @base_styles.dup\n                else\n                  @base_styles.merge(@styles)\n                end\n            end\n\n            private\n\n            # @param [Hash] s\n            # @return [String]\n            def create_identifier(s)\n              s.empty? ? '' : s.hash.to_s\n            end\n\n            # @param [Symbol] style_method\n            # @raise Thinreports::BasicReport::Errors::UnknownShapeStyleName\n            def verify_style_method(style_method)\n              return if has_style?(style_method)\n\n              raise Thinreports::BasicReport::Errors::UnknownShapeStyleName.new(\n                style_method,\n                accessible_styles\n              )\n            end\n\n            # @param [Object] value\n            # @param [Array<Object>] allows\n            # @param [String] msg (nil)\n            # @raise ArgumentError\n            def verify_style_value(value, allows, msg = nil)\n              raise ArgumentError, msg unless allows.include?(value)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/style/basic.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Style\n          class Basic < Style::Base\n            style_accessible :visible, :offset_x, :offset_y\n            attr_accessor :visible\n\n            style_accessor :offset_x, 'offset-x'\n            style_accessor :offset_y, 'offset-y'\n\n            def initialize(*args)\n              super\n              @visible = @format.display?\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/style/graphic.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Style\n          class Graphic < Style::Basic\n            style_accessible :border_color, :border_width, :fill_color, :border\n\n            # @method border_color\n            #   @return [String]\n            # @method border_color=(color)\n            #   @param [String] color\n            style_accessor :border_color, 'border-color'\n\n            # @method border_width\n            #   @return [Number]\n            style_accessor :border_width, 'border-width'\n\n            # @method fill_color\n            #   @return [String]\n            # @method fill_color=(color)\n            #   @param [String] color\n            style_accessor :fill_color, 'fill-color'\n\n            # @return [Array<String, Number>]\n            def border\n              [border_width, border_color]\n            end\n\n            # @param [Array<String, Number>] width_and_color\n            def border=(width_and_color)\n              w, c = width_and_color\n              self.border_width = w\n              self.border_color = c\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/style/text.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Style\n          class Text < Style::Basic\n            style_accessible :bold, :italic, :underline, :linethrough,\n                             :align, :valign, :color, :font_size\n\n            # @method color\n            #   @return [String]\n            # @method color=(v)\n            #   @param [String] v\n            style_accessor :color, 'color'\n\n            # @method font_size\n            #   @return [Numeric, String]\n            # @method font_size=(v)\n            #   @param [Numeric, String] v\n            style_accessor :font_size, 'font-size'\n\n            def initialize(*)\n              super\n              initialize_font_style\n            end\n\n            # @return [Boolean]\n            def bold\n              read_internal_style('font-style').include?('bold')\n            end\n\n            # @param [Boolean] enable\n            def bold=(enable)\n              write_font_style('bold', enable)\n            end\n\n            # @return [Boolean]\n            def italic\n              read_internal_style('font-style').include?('italic')\n            end\n\n            # @param [Boolean] enable\n            def italic=(enable)\n              write_font_style('italic', enable)\n            end\n\n            # @return [Boolean]\n            def underline\n              read_internal_style('font-style').include?('underline')\n            end\n\n            # @param [Boolean] enable\n            def underline=(enable)\n              write_font_style('underline', enable)\n            end\n\n            # @return [Boolean]\n            def linethrough\n              read_internal_style('font-style').include?('linethrough')\n            end\n\n            # @param [Boolean] enable\n            def linethrough=(enable)\n              write_font_style('linethrough', enable)\n            end\n\n            # @return [:left, :center, :right]\n            def align\n              read_internal_style('text-align').to_sym\n            end\n\n            # @param [:left, :center, :right] align_name\n            def align=(align_name)\n              verify_style_value(align_name, %i[left center right],\n                                 'Only :left or :center, :right can be specified as align.')\n              write_internal_style('text-align', align_name.to_s)\n            end\n\n            # @return [:top, :middle, :bottom]\n            def valign\n              vertical_align = read_internal_style('vertical-align')\n              blank_value?(vertical_align) ? :top : vertical_align.to_sym\n            end\n\n            # @param [:top, :center, :middle, :bottom] valign_name\n            def valign=(valign_name)\n              if valign_name == :center\n                warn '[DEPRECATION] :center value for valign style is deprecated' \\\n                     ' and will be removed in thinreports-generator 1.0.' \\\n                     ' Please use :middle instead of :center.'\n                valign_name = :middle\n              end\n\n              verify_style_value(\n                valign_name,\n                %i[top middle bottom],\n                'Only :top or :middle (:center), :bottom can be specified as valign.'\n              )\n              write_internal_style('vertical-align', valign_name.to_s)\n            end\n\n            private\n\n            def initialize_font_style\n              styles['font-style'] ||= (@base_styles['font-style'] || []).dup\n            end\n\n            def write_font_style(style_name, enable)\n              if enable\n                styles['font-style'].push(style_name).uniq!\n              else\n                styles['font-style'].delete(style_name)\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/style.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'style/base'\nrequire_relative 'style/basic'\nrequire_relative 'style/graphic'\nrequire_relative 'style/text'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Text\n          class Format < Basic::Format\n            config_reader :texts\n            config_reader valign: %w[style vertical-align]\n            config_reader line_height: %w[style line-height]\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Text\n          class Interface < Basic::Interface\n            private\n\n            # @see Thinreports::BasicReport::Core::Shape::Base::Interface#init_internal\n            def init_internal(parent, format)\n              Text::Internal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Text\n          class Internal < Basic::Internal\n            # Delegate to Format's methods\n            format_delegators :texts, :box\n\n            def style\n              @style ||= Style::Text.new(format)\n            end\n\n            def type_of?(type_name)\n              type_name == Text::TYPE_NAME\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module Text\n          TYPE_NAME = 'text'\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'text/format'\nrequire_relative 'text/internal'\nrequire_relative 'text/interface'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/format.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          class Format < Basic::BlockFormat\n            # For saving compatible 0.8.x format API\n            config_reader ref_id: %w[reference-id]\n            config_reader valign: %w[style vertical-align]\n            config_reader overflow: %w[style overflow]\n            config_reader line_height: %w[style line-height]\n\n            config_reader format_base: %w[format base],\n                          format_type: %w[format type],\n                          format_datetime_format: %w[format datetime format],\n                          format_number_delimiter: %w[format number delimiter],\n                          format_number_precision: %w[format number precision],\n                          format_padding_char: %w[format padding char],\n                          format_padding_dir: %w[format padding direction]\n\n            config_checker true, multiple: %w[multiple-line]\n            config_checker 'R', format_padding_rdir: %w[format padding direction]\n\n            config_reader format_padding_length: %w[format padding length] do |len|\n              blank_value?(len) ? 0 : len.to_i\n            end\n\n            config_reader has_format?: %w[format type] do |type|\n              %w[datetime number padding].include?(type)\n            end\n\n            # For saving compatible 0.8.x format API\n            def has_reference?\n              !blank_value?(ref_id)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/formatter/basic.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          module Formatter\n            class Basic\n              include Utils\n\n              attr_reader :format\n\n              def initialize(format)\n                @format = format\n              end\n\n              def apply(value)\n                value = apply_format_to(value) if applicable?(value)\n\n                return value if blank_value?(format.format_base)\n\n                format.format_base.gsub(/\\{value\\}/, value.to_s)\n              end\n\n              private\n\n              def apply_format_to(value)\n                value\n              end\n\n              def applicable?(_value)\n                true\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/formatter/datetime.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          module Formatter\n            class Datetime < Formatter::Basic\n              private\n\n              def apply_format_to(value)\n                value.strftime(format.format_datetime_format)\n              end\n\n              def applicable?(value)\n                !blank_value?(format.format_datetime_format) && value.respond_to?(:strftime)\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/formatter/number.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'bigdecimal'\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          module Formatter\n            class Number < Formatter::Basic\n              private\n\n              def apply_format_to(value)\n                precision = format.format_number_precision\n                delimiter = format.format_number_delimiter\n\n                if_applicable value do |val|\n                  val = number_with_precision(val, precision) unless blank_value?(precision)\n                  val = number_with_delimiter(val, delimiter) unless blank_value?(delimiter)\n                  val\n                end\n              end\n\n              def if_applicable(value, &block)\n                normalized_value = normalize(value)\n                normalized_value.nil? ? value : block.call(normalized_value)\n              end\n\n              def normalize(value)\n                if value.is_a?(String)\n                  convert_to_integer(value) || convert_to_float(value)\n                else\n                  value\n                end\n              end\n\n              def number_with_delimiter(value, delimiter = ',')\n                value_int, value_float = value.to_s.split('.')\n\n                [\n                  value_int.gsub(/(\\d)(?=(\\d{3})+(?!\\d))/) { \"#{$1}#{delimiter}\" },\n                  value_float\n                ].compact.join('.')\n              end\n\n              def number_with_precision(value, precision = 3)\n                value = BigDecimal(value.to_s).round(precision)\n                sprintf(\"%.#{precision}f\", value)\n              end\n\n              def convert_to_integer(value)\n                Integer(value)\n              rescue ArgumentError\n                nil\n              end\n\n              def convert_to_float(value)\n                Float(value)\n              rescue ArgumentError\n                nil\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/formatter/padding.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          module Formatter\n            class Padding < Formatter::Basic\n              private\n\n              def apply_format_to(value)\n                value.to_s.send(format.format_padding_rdir? ? :ljust : :rjust,\n                                format.format_padding_length,\n                                format.format_padding_char)\n              end\n\n              def applicable?(_value)\n                !blank_value?(format.format_padding_char) && format.format_padding_length > 0\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/formatter.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          module Formatter\n            include Utils\n\n            # @param [Thinreports::BasicReport::Core::Shape::TextBlock::Format] format\n            # @return [Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::Base]\n            def self.setup(format)\n              klass =\n                if blank_value?(format.format_type)\n                  Basic\n                else\n                  case format.format_type\n                  when 'number'   then Number\n                  when 'datetime' then Datetime\n                  when 'padding'  then Padding\n                  else\n                    raise Thinreports::BasicReport::Errors::UnknownFormatterType\n                  end\n                end\n              klass.new(format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'formatter/basic'\nrequire_relative 'formatter/datetime'\nrequire_relative 'formatter/padding'\nrequire_relative 'formatter/number'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/interface.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          class Interface < Basic::BlockInterface\n            internal_delegators :format_enabled?\n\n            # @param [Boolean] enabled\n            # @return [self]\n            def format_enabled(enabled)\n              internal.format_enabled(enabled)\n              self\n            end\n\n            # @param [Object] val\n            # @param [Hash<Symbol, Object>] style_settings\n            # @return [self]\n            def set(val, style_settings = {})\n              value(val)\n              styles(style_settings) #=> self\n            end\n\n            private\n\n            # @see Thinreports::BasicReport::Core::Shape::Base::Interface#init_internal\n            def init_internal(parent, format)\n              TextBlock::Internal.new(parent, format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          class Internal < Basic::BlockInternal\n            format_delegators :multiple?\n\n            attr_reader :style\n\n            def initialize(*args)\n              super(*args)\n\n              @reference = nil\n              @formatter = nil\n\n              @style = Style::Text.new(format)\n              @style.accessible_styles.delete(:valign) unless multiple?\n            end\n\n            def read_value\n              if format.has_reference?\n                @reference ||= parent.item(format.ref_id)\n                @reference.value\n              else\n                super\n              end\n            end\n\n            def write_value(val)\n              if format.has_reference?\n                warn 'The set value was not saved, ' \\\n                     \"Because '#{format.id}' has reference to '#{format.ref_id}'.\"\n              else\n                super\n              end\n            end\n\n            def real_value\n              if format_enabled?\n                formatter.apply(read_value)\n              else\n                super\n              end\n            end\n\n            def format_enabled(enabled)\n              states[:format_enabled] = enabled\n            end\n\n            def format_enabled?\n              if states.key?(:format_enabled)\n                states[:format_enabled]\n              else\n                !blank_value?(format.format_base) || format.has_format?\n              end\n            end\n\n            def type_of?(type_name)\n              type_name == TextBlock::TYPE_NAME || super\n            end\n\n            private\n\n            def formatter\n              @formatter ||= TextBlock::Formatter.setup(format)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape/text_block.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        module TextBlock\n          TYPE_NAME = 'text-block'\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'text_block/format'\nrequire_relative 'text_block/internal'\nrequire_relative 'text_block/interface'\nrequire_relative 'text_block/formatter'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/shape.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Core\n      module Shape\n        def Interface(parent, format)\n          find_by_type(format.type)::Interface.new(parent, format)\n        end\n\n        def Format(type)\n          find_by_type(type)::Format\n        end\n\n        module_function :Interface, :Format\n\n        def self.find_by_type(type)\n          case type\n          when TextBlock::TYPE_NAME  then TextBlock\n          when ImageBlock::TYPE_NAME then ImageBlock\n          when List::TYPE_NAME       then List\n          when StackView::TYPE_NAME  then StackView\n          when Text::TYPE_NAME       then Text\n          when PageNumber::TYPE_NAME then PageNumber\n          when *Basic::TYPE_NAMES    then Basic\n          else\n            raise Thinreports::BasicReport::Errors::UnknownShapeType\n          end\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'shape/style'\nrequire_relative 'shape/manager'\nrequire_relative 'shape/base'\nrequire_relative 'shape/basic'\nrequire_relative 'shape/text'\nrequire_relative 'shape/text_block'\nrequire_relative 'shape/image_block'\nrequire_relative 'shape/list'\nrequire_relative 'shape/stack_view'\nrequire_relative 'shape/page_number'\n"
  },
  {
    "path": "lib/thinreports/basic_report/core/utils.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Utils\n      def self.included(klass)\n        klass.extend self\n      end\n\n      def deep_copy(src)\n        case src\n        when Hash\n          src.each_with_object({}) do |(k, v), h|\n            h[k] = v.dup rescue v\n          end\n        when Array\n          src.map do |a|\n            a.dup rescue a\n          end\n        else\n          raise ArgumentError\n        end\n      end\n\n      def blank_value?(value)\n        case value\n        when String   then value.empty?\n        when NilClass then true\n        else false\n        end\n      end\n\n      def call_block_in(scope, &block)\n        return scope unless block_given?\n\n        if block.arity == 1\n          block.call(scope)\n        else\n          scope.instance_eval(&block)\n        end\n        scope\n      end\n    end\n\n    extend Utils\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/draw_shape.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module DrawShape\n          # @param [Thinreports::BasicReport::Core::Shape::TextBlock::Internal] shape\n          # @param [Numeric] height (nil) It will be used as rendering height if present.\n          #   Otherwise, the rendering height is the height of schema.\n          # @param [:truncate, :shrink_to_fit, :expand] overflow (nil) It will be set the overflow attribute if present.\n          def draw_shape_tblock(shape, height: nil, overflow: nil, &block)\n            x, y, w = shape.format.attributes.values_at('x', 'y', 'width')\n\n            h = height || shape.format.attributes['height']\n\n            content = shape.real_value.to_s\n            return if content.empty?\n\n            attrs = build_text_attributes(shape.style.finalized_styles)\n            attrs[:overflow] = overflow if overflow\n\n            unless shape.multiple?\n              content = content.tr(\"\\n\", ' ')\n              attrs[:single] = true\n            end\n\n            text_box(content, x, y, w, h, attrs, &block)\n          end\n\n          def draw_shape_pageno(shape, page_no, page_count)\n            x, y, w, h = shape.format.attributes.values_at('x', 'y', 'width', 'height')\n\n            attrs = build_text_attributes(shape.style.finalized_styles)\n            text_box(shape.build_format(page_no, page_count), x, y, w, h, attrs)\n          end\n\n          # @param [Thinreports::BasicReport::Core::Shape::Basic::Internal] shape\n          def draw_shape_image(shape)\n            x, y, w, h = shape.format.attributes.values_at('x', 'y', 'width', 'height')\n\n            image_data = shape.format.attributes['data']\n            base64image(image_data['base64'], x, y, w, h)\n          end\n\n          # @param [Thinreports::BasicReport::Core::Shape::ImageBlock::Internal] shape\n          def draw_shape_iblock(shape)\n            return if blank_value?(shape.src)\n\n            x, y, w, h = shape.format.attributes.values_at('x', 'y', 'width', 'height')\n            style = shape.style.finalized_styles\n\n            image_box(\n              shape.src, x, y, w, h,\n              position_x: image_position_x(style['position-x']),\n              position_y: image_position_y(style['position-y']),\n              offset_x: style['offset-x'],\n              offset_y: style['offset-y']\n            )\n          end\n\n          def shape_iblock_dimenions(shape)\n            return nil if blank_value?(shape.src)\n\n            x, y, w, h = shape.format.attributes.values_at('x', 'y', 'width', 'height')\n            style = shape.style.finalized_styles\n\n            image_dimensions(\n              shape.src, x, y, w, h,\n              position_x: image_position_x(style['position-x']),\n              position_y: image_position_y(style['position-y'])\n            )\n          end\n\n          # @param [Thinreports::BasicReport::Core::Shape::Text::Internal] shape\n          def draw_shape_text(shape, dheight = 0)\n            x, y, w, h = shape.format.attributes.values_at('x', 'y', 'width', 'height')\n            text(\n              shape.texts.join(\"\\n\"), x, y, w, h + dheight,\n              build_text_attributes(shape.style.finalized_styles)\n            )\n          end\n\n          # @param [Thinreports::BasicReport::Core::Shape::Basic::Internal] shape\n          def draw_shape_ellipse(shape)\n            cx, cy, rx, ry = shape.format.attributes.values_at('cx', 'cy', 'rx', 'ry')\n            ellipse(cx, cy, rx, ry, build_graphic_attributes(shape.style.finalized_styles))\n          end\n\n          # @param [Thinreports::BasicReport::Core::Shape::Basic::Internal] shape\n          def draw_shape_line(shape, dy1 = 0, dy2 = 0)\n            x1, y1, x2, y2 = shape.format.attributes.values_at('x1', 'y1', 'x2', 'y2')\n            line(x1, y1 + dy1, x2, y2 + dy2, build_graphic_attributes(shape.style.finalized_styles))\n          end\n\n          # @param [Thinreports::BasicReport::Core::Shape::Basic::Internal] shape\n          def draw_shape_rect(shape, dheight = 0)\n            x, y, w, h = shape.format.attributes.values_at('x', 'y', 'width', 'height')\n            rect_attributes = build_graphic_attributes(shape.style.finalized_styles) do |attrs|\n              attrs[:radius] = shape.format.attributes['border-radius']\n            end\n            rect(x, y, w, h + dheight, rect_attributes)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/draw_template_items.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module DrawTemplateItems\n          # @param [Array<Hash>] items\n          def draw_template_items(items)\n            items.each do |item_attributes|\n              next unless drawable?(item_attributes)\n\n              case item_attributes['type']\n              when 'text' then draw_text(item_attributes)\n              when 'image' then draw_image(item_attributes)\n              when 'rect' then draw_rect(item_attributes)\n              when 'ellipse' then draw_ellipse(item_attributes)\n              when 'line' then draw_line(item_attributes)\n              end\n            end\n          end\n\n          private\n\n          # @param [Hash] item_attributes\n          def draw_rect(item_attributes)\n            x, y, w, h = item_attributes.values_at('x', 'y', 'width', 'height')\n            graphic_attributes = build_graphic_attributes(item_attributes['style']) do |attrs|\n              attrs[:radius] = item_attributes['border-radius']\n            end\n\n            rect(x, y, w, h, graphic_attributes)\n          end\n\n          # @see #draw_rect\n          def draw_ellipse(item_attributes)\n            x, y, rx, ry = item_attributes.values_at('cx', 'cy', 'rx', 'ry')\n            ellipse(x, y, rx, ry, build_graphic_attributes(item_attributes['style']))\n          end\n\n          # @see #draw_rect\n          def draw_line(item_attributes)\n            x1, y1, x2, y2 = item_attributes.values_at('x1', 'y1', 'x2', 'y2')\n            line(x1, y1, x2, y2, build_graphic_attributes(item_attributes['style']))\n          end\n\n          # @see #draw_rect\n          def draw_text(item_attributes)\n            x, y, w, h = item_attributes.values_at('x', 'y', 'width', 'height')\n            text(\n              item_attributes['texts'].join(\"\\n\"), x, y, w, h,\n              build_text_attributes(item_attributes['style'])\n            )\n          end\n\n          # @see #draw_rect\n          def draw_image(item_attributes)\n            x, y, w, h = item_attributes.values_at('x', 'y', 'width', 'height')\n            image_data = item_attributes['data']\n\n            base64image(image_data['base64'], x, y, w, h)\n          end\n\n          def drawable?(item_attributes)\n            item_attributes['id'].empty? && item_attributes['display']\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/font.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Font\n          FONT_STORE = Thinreports.root.join('fonts')\n\n          BUILTIN_FONTS = {\n            'IPAMincho'  => FONT_STORE.join('ipam.ttf').to_s,\n            'IPAPMincho' => FONT_STORE.join('ipamp.ttf').to_s,\n            'IPAGothic'  => FONT_STORE.join('ipag.ttf').to_s,\n            'IPAPGothic' => FONT_STORE.join('ipagp.ttf').to_s\n          }.freeze\n\n          DEFAULT_FALLBACK_FONTS = %w[IPAMincho].freeze\n\n          PRAWN_BUINTIN_FONT_ALIASES = {\n            'Courier New' => 'Courier',\n            'Times New Roman' => 'Times-Roman'\n          }.freeze\n\n          def setup_fonts\n            # Install built-in fonts.\n            BUILTIN_FONTS.each do |font_name, font_path|\n              install_font(font_name, font_path)\n            end\n\n            # Create aliases from the font list provided by Prawn.\n            PRAWN_BUINTIN_FONT_ALIASES.each do |alias_name, name|\n              pdf.font_families[alias_name] = pdf.font_families[name]\n            end\n\n            # Setup custom fallback fonts\n            fallback_fonts = Thinreports.config.fallback_fonts.uniq\n            fallback_fonts.map!.with_index do |font, i|\n              if pdf.font_families.key?(font)\n                font\n              else\n                install_font \"Custom-fallback-font#{i}\", font\n              end\n            end\n\n            # Set fallback fonts\n            pdf.fallback_fonts(fallback_fonts + DEFAULT_FALLBACK_FONTS)\n          end\n\n          # @param [String] name\n          # @param [String] file\n          # @return [String] installed font name\n          def install_font(name, file)\n            raise Errors::FontFileNotFound unless File.exist?(file)\n\n            pdf.font_families[name] = {\n              normal: file,\n              bold: file,\n              italic: file,\n              bold_italic: file\n            }\n            name\n          end\n\n          # @return [String]\n          def default_family\n            'Helvetica'\n          end\n\n          # @param [String] family\n          # @return [String]\n          def default_family_if_missing(family)\n            pdf.font_families.key?(family) ? family : default_family\n          end\n\n          # @param [String] font_name\n          # @param [:bold, :italic] font_style\n          # @return [Boolean]\n          def font_has_style?(font_name, font_style)\n            font = pdf.font_families[font_name]\n\n            return false unless font\n            return false unless font.key?(font_style)\n\n            font[font_style] != font[:normal]\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/graphics/attributes.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Graphics\n          # @param [Hash] style\n          # @yield [attrs]\n          # @yieldparam [Hash] attrs\n          # @return [Hash]\n          def build_graphic_attributes(style, &block)\n            graphic_attributes = {\n              stroke: style['border-color'],\n              stroke_width: style['border-width'],\n              stroke_type: style['border-style'],\n              fill: style['fill-color']\n            }\n            block.call(graphic_attributes) if block_given?\n            graphic_attributes\n          end\n\n          # @param [Hash] style\n          # @yield [attrs]\n          # @yieldparam [Hash] attrs\n          # @return [Hash]\n          def build_text_attributes(style, &block)\n            word_wrap = word_wrap(style['word-wrap'])\n\n            text_attributes = {\n              font: font_family(style['font-family']),\n              size: style['font-size'],\n              color: style['color'],\n              align: text_align(style['text-align']),\n              valign: text_valign(style['vertical-align']),\n              styles: font_styles(style['font-style']),\n              letter_spacing: letter_spacing(style['letter-spacing']),\n              line_height: line_height(style['line-height']),\n              overflow: text_overflow(style['overflow']),\n              word_wrap: word_wrap,\n              # Deprecated: Use overflow_wrap instead of word_wrap\n              overflow_wrap: overflow_wrap(style['overflow-wrap'], word_wrap)\n            }\n            block.call(text_attributes) if block_given?\n            text_attributes\n          end\n\n          def overflow_wrap(style, computed_word_wrap)\n            case style || migrate_overflow_wrap_from_word_wrap(computed_word_wrap)\n            when 'normal', nil then :normal\n            when 'anywhere' then :anywhere\n            # Deprecated: This is a temporary value for migrating from word_wrap.\n            when 'disable-break-word-by-space' then :disable_break_word_by_space\n            else :normal\n            end\n          end\n\n          def migrate_overflow_wrap_from_word_wrap(computed_word_wrap)\n            case computed_word_wrap\n            when :none then 'disable-break-word-by-space'\n            when :break_word then 'normal'\n            else raise ArgumentError, 'Invalid computed word_wrap value'\n            end\n          end\n\n          # @param [Array<String>] font_names\n          # @return [String]\n          def font_family(font_names)\n            font_name = font_names.first\n            default_family_if_missing(font_name)\n          end\n\n          # @param [Array<String>] styles\n          # @return [Array<Symbol>]\n          def font_styles(styles)\n            styles.map do |font_style|\n              case font_style\n              when 'bold' then :bold\n              when 'italic' then :italic\n              when 'underline' then :underline\n              when 'linethrough' then :strikethrough\n              end\n            end\n          end\n\n          # @param [Float, \"\", nil] spacing\n          # @return [Float, nil]\n          def letter_spacing(spacing)\n            blank_value?(spacing) ? nil : spacing\n          end\n\n          # @param [\"left\", \"center\", \"right\", \"\"] align\n          # @return [:left, :center, :right]\n          def text_align(align)\n            case align\n            when 'left' then :left\n            when 'center' then :center\n            when 'right' then :right\n            when '' then :left\n            else :left\n            end\n          end\n\n          # @param [\"top\", \"middle\", \"bottom\", \"\", nil] valign\n          # @return [:top, :center, :bottom]\n          def text_valign(valign)\n            case valign\n            when 'top' then :top\n            when 'middle' then :center\n            when 'bottom' then :bottom\n            when '' then :top\n            else :top\n            end\n          end\n\n          # @param [\"truncate\", \"fit\", \"expand\", \"\", nil] overflow\n          # @return [:truncate, :shrink_to_fit, :expand]\n          def text_overflow(overflow)\n            case overflow\n            when 'truncate' then :truncate\n            when 'fit' then :shrink_to_fit\n            when 'expand' then :expand\n            when '' then :truncate\n            else :truncate\n            end\n          end\n\n          # @param [\"break-word\", \"none\", \"\", nil] word_wrap\n          # @return [:break_word, :none]\n          def word_wrap(word_wrap)\n            case word_wrap\n            when 'break-word' then :break_word\n            when 'none' then :none\n            else :none\n            end\n          end\n\n          # @param [Float, \"\", nil] height\n          # @return [Float, nil]\n          def line_height(height)\n            blank_value?(height) ? nil : height\n          end\n\n          # @param [\"left\", \"center\", \"right\", \"\"] position\n          # @return [:left, :center, :right]\n          def image_position_x(position)\n            case position\n            when 'left' then :left\n            when 'center' then :center\n            when 'right' then :right\n            when '' then :left\n            else :left\n            end\n          end\n\n          # @param [\"top\", \"middle\", \"bottom\", \"\"] position\n          # @return [:left, :center, :right]\n          def image_position_y(position)\n            case position\n            when 'top' then :top\n            when 'middle' then :center\n            when 'bottom' then :bottom\n            when '' then :top\n            else :top\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/graphics/basic.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Graphics\n          STROKE_DASH = {\n            dashed: [2, 2],\n            dotted: [1, 2]\n          }.freeze\n\n          # @param [Numeric, String] x1\n          # @param [Numeric, String] y1\n          # @param [Numeric, String] x2\n          # @param [Numeric, String] y2\n          # @param [Hash] attrs ({})\n          # @option attrs [String] :stroke\n          # @option attrs [Numeric, String] :stroke_width\n          # @option attrs [\"solid\", \"dashed\", \"dotted\"] :stroke_type\n          def line(x1, y1, x2, y2, attrs = {})\n            with_graphic_styles(attrs) do\n              pdf.line(pos(x1, y1), pos(x2, y2))\n            end\n          end\n\n          # @param [Numeric, String] x\n          # @param [Numeric, String] y\n          # @param [Numeric, String] w width\n          # @param [Numeric, String] h height\n          # @param [Hash] attrs ({})\n          # @option attrs [Integer, String] :radius\n          # @option attrs [String] :stroke\n          # @option attrs [Numeric, String] :stroke_width\n          # @option attrs [\"solid\", \"dashed\", \"dotted\"] :stroke_type\n          # @option attrs [String] :fill\n          def rect(x, y, w, h, attrs = {})\n            w, h = s2f(w, h)\n            radius = s2f(attrs[:radius])\n\n            with_graphic_styles(attrs) do\n              if radius && !radius.zero?\n                pdf.rounded_rectangle(pos(x, y), w, h, radius)\n              else\n                pdf.rectangle(pos(x, y), w, h)\n              end\n            end\n          end\n\n          # @param [Numeric, String] x center-x\n          # @param [Numeric, String] y center-y\n          # @param [Numeric, String] rx\n          # @param [Numeric, String] ry\n          # @param [Hash] attrs ({})\n          # @option attrs [String] :stroke\n          # @option attrs [Numeric, String] :stroke_width\n          # @option attrs [Array<Integer, String>] :stroke_dash\n          # @option attrs [\"solid\", \"dashed\", \"dotted\"] :stroke_type\n          # @option attrs [String] :fill\n          def ellipse(x, y, rx, ry, attrs = {})\n            rx, ry = s2f(rx, ry)\n\n            with_graphic_styles(attrs) do\n              pdf.ellipse(pos(x, y), rx, ry)\n            end\n          end\n\n          # @param [Hash] attrs\n          def with_graphic_styles(attrs, &block)\n            stroke = build_stroke_styles(attrs)\n            fill = build_fill_styles(attrs)\n\n            # Do not draw if no colors given.\n            return unless fill || stroke\n\n            save_graphics_state\n\n            # Apply stroke-dashed.\n            if stroke && stroke[:dash]\n              length, space = stroke[:dash]\n              pdf.dash(length, space: space)\n            end\n\n            # Draw with fill and stroke.\n            if fill && stroke\n              pdf.fill_and_stroke do\n                line_width(stroke[:width])\n                pdf.fill_color(fill[:color])\n                pdf.stroke_color(stroke[:color])\n                block.call\n              end\n            # Draw only with fill.\n            elsif fill\n              pdf.fill do\n                pdf.fill_color(fill[:color])\n                block.call\n              end\n            # Draw only with stroke.\n            elsif stroke\n              pdf.stroke do\n                line_width(stroke[:width])\n                pdf.stroke_color(stroke[:color])\n                block.call\n              end\n            end\n\n            restore_graphics_state\n          end\n\n          # @param [Hash] styles\n          # @return [Hash, nil]\n          def build_stroke_styles(styles)\n            color = styles[:stroke]\n            width = styles[:stroke_width]\n            return nil unless color && color != 'none'\n            return nil unless width && width != 0\n\n            {\n              color: parse_color(color),\n              width: s2f(width),\n              dash: STROKE_DASH[styles[:stroke_type].to_sym]\n            }\n          end\n\n          # @param [Hash] styles\n          # @return [Hash, nil]\n          def build_fill_styles(styles)\n            color = styles[:fill]\n            return nil unless color && color != 'none'\n\n            { color: parse_color(color) }\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/graphics/image.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'tempfile'\nrequire 'base64'\nrequire 'digest/md5'\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Graphics\n          # @param [String, IO] filename_or_io\n          # @param [Numeric, Strng] x\n          # @param [Numeric, Strng] y\n          # @param [Numeric, Strng] w\n          # @param [Numeric, Strng] h\n          def image(filename_or_io, x, y, w, h)\n            w, h = s2f(w, h)\n            pdf.image(filename_or_io, at: pos(x, y), width: w, height: h)\n          end\n\n          # @param [String] base64_data\n          # @param [Numeric, Strng] x\n          # @param [Numeric, Strng] y\n          # @param [Numeric, Strng] w\n          # @param [Numeric, Strng] h\n          def base64image(base64_data, x, y, w, h)\n            image_data = Base64.decode64(base64_data)\n            image_id = Digest::MD5.hexdigest(base64_data)\n            image_path = create_temp_imagefile(image_id, image_data)\n\n            image(image_path, x, y, w, h)\n          end\n\n          # @param [String, IO] filename_or_io\n          # @param [Numeric, Strng] x\n          # @param [Numeric, Strng] y\n          # @param [Numeric, Strng] w\n          # @param [Numeric, Strng] h\n          # @param [Hash] options\n          # @option options [:left, :center, :right] :position_x (:left)\n          # @option options [:top, :center, :bottom] :position_y (:top)\n          # @option options [Numeric] :offset_x\n          # @option options [Numeric] :offset_y\n          def image_box(filename_or_io, x, y, w, h, options = {})\n            w, h = s2f(w, h)\n\n            computed_position = pos(\n              x + (options[:offset_x] || 0),\n              y + (options[:offset_y] || 0)\n            )\n            pdf.bounding_box(computed_position, width: w, height: h) do\n              pdf.image(\n                filename_or_io,\n                position: options[:position_x] || :left,\n                vposition: options[:position_y] || :top,\n                auto_fit: [w, h]\n              )\n            end\n          end\n\n          def image_dimensions(filename_or_io, x, y, w, h, options = {})\n            w, h = s2f(w, h)\n            # XXX: Calling @private method\n            _pdf_obj, info = pdf.build_image_object(filename_or_io)\n            info.calc_image_dimensions(\n              position: options[:position_x] || :left,\n              vposition: options[:position_y] || :top,\n              auto_fit: [w, h]\n            )\n          end\n\n          def clean_temp_images\n            temp_image_registry.each_value(&:close!)\n            temp_image_registry.clear\n          end\n\n          def temp_image_registry\n            @temp_image_registry ||= {}\n          end\n\n          # @param [String] image_id\n          # @param [String] image_data\n          # @return [String] Path to imagefile\n          def create_temp_imagefile(image_id, image_data)\n            temp_image_registry[image_id] ||= begin\n              file = Tempfile.new('temp-image')\n              file.binmode\n              file.write(image_data)\n              file.open\n              file\n            end\n            temp_image_registry[image_id].path\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/graphics/text.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Graphics\n          # @param [String] content\n          # @param [Numeric, String] x\n          # @param [Numeric, String] y\n          # @param [Numeric, String] w\n          # @param [Numeric, String] h\n          # @param [Hash] attrs ({})\n          # @option attrs [String] :font\n          # @option attrs [Numeric, String] :size\n          # @option attrs [String] :color\n          # @option attrs [Array<:bold, :italic, :underline, :strikethrough>]\n          #   :styles (nil)\n          # @option attrs [:left, :center, :right] :align (:left)\n          # @option attrs [:top, :center, :bottom] :valign (:top)\n          # @option attrs [Numeric, String] :line_height The total height of an text line.\n          # @option attrs [Numeric, String] :letter_spacing\n          # @option attrs [Boolean] :single (false)\n          # @option attrs [:trancate, :shrink_to_fit, :expand] :overflow (:trancate)\n          # @option attrs [:none, :break_word] :word_wrap (:none)\n          # @option attrs [:normal, :anywhere, :disable_break_word_by_space] :overflow_wrap (:normal)\n          def text_box(content, x, y, w, h, attrs = {}, &block)\n            w, h = s2f(w, h)\n\n            box_attrs = text_box_attrs(\n              x, y, w, h,\n              single: attrs.delete(:single),\n              overflow: attrs[:overflow]\n            )\n\n            content = replace_space_to_nbsp(content) if attrs[:overflow_wrap] == :disable_break_word_by_space\n\n            with_text_styles(attrs) do |built_attrs, font_styles|\n              if block\n                block.call [{ text: content, styles: font_styles }],\n                  built_attrs.merge(box_attrs)\n              else\n                pdf.formatted_text_box(\n                  [{ text: content, styles: font_styles }],\n                  built_attrs.merge(box_attrs)\n                )\n              end\n            end\n          rescue Prawn::Errors::CannotFit\n            # Nothing to do.\n            #\n            # When the area is too small compared\n            # with the content and the style of the text.\n            #   (See prawn/core/text/formatted/line_wrap.rb#L185)\n          end\n\n          # @see #text_box\n          def text(content, x, y, w, h, attrs = {})\n            # Set the :overflow property to :shirink_to_fit.\n            text_box(content, x, y, w, h, { overflow: :shirink_to_fit }.merge(attrs))\n          end\n\n          private\n\n          # @param x (see #text_box)\n          # @param y (see #text_box)\n          # @param w (see #text_box)\n          # @param h (see #text_box)\n          # @param [Hash] states\n          # @option states [Boolean] :single\n          # @option states [Symbold] :overflow\n          # @return [Hash]\n          def text_box_attrs(x, y, w, h, states = {})\n            attrs = {\n              at: pos(x, y),\n              width: s2f(w)\n            }\n            if states[:single]\n              states[:overflow] != :expand ? attrs.merge(single_line: true) : attrs\n            else\n              attrs.merge(height: s2f(h))\n            end\n          end\n\n          # @param attrs (see #text)\n          # @yield [built_attrs, font_styles]\n          # @yieldparam [Hash] built_attrs The finalized attributes.\n          # @yieldparam [Array] font_styles The finalized styles.\n          def with_text_styles(attrs, &block)\n            # When no color is given, do not draw.\n            return unless attrs.key?(:color) && attrs[:color] != 'none'\n\n            save_graphics_state\n\n            fontinfo = {\n              name: attrs.delete(:font).to_s,\n              color: parse_color(attrs.delete(:color)),\n              size: s2f(attrs.delete(:size))\n            }\n\n            # Add the specified value to :leading option.\n            line_height = attrs.delete(:line_height)\n            if line_height\n              attrs[:leading] = text_line_leading(\n                s2f(line_height),\n                name: fontinfo[:name],\n                size: fontinfo[:size]\n              )\n            end\n\n            # Set the :character_spacing option.\n            spacing = attrs.delete(:letter_spacing)\n            attrs[:character_spacing] = s2f(spacing) if spacing\n\n            # Disable line breaking on chars such as spaces and hyphens\n            attrs[:disable_word_break] = true if attrs.delete(:overflow_wrap) == :anywhere\n\n            # Delete unnecessary attributes\n            attrs.delete(:word_wrap)\n\n            # Or... with_font_styles(attrs, fontinfo, &block)\n            with_font_styles(attrs, fontinfo) do |modified_attrs, styles|\n              block.call(modified_attrs, styles)\n            end\n\n            restore_graphics_state\n          end\n\n          # @param [Numeric] line_height\n          # @param [Hash] font\n          # @option font [String] :name Name of font.\n          # @option font [Numeric] :size Size of font.\n          # @return [Numeric]\n          def text_line_leading(line_height, font)\n            line_height - pdf.font(font[:name], size: font[:size]).height\n          end\n\n          # @param [String] content\n          # @return [String]\n          def replace_space_to_nbsp(content)\n            content.gsub(/ /, Prawn::Text::NBSP)\n          end\n\n          # @param [Hash] attrs\n          # @param [Hash] font\n          # @option font [String] :color\n          # @option font [Numeric] :size\n          # @option font [String] :name\n          # @yield [attributes, styles]\n          # @yieldparam [Hash] modified_attrs\n          # @yieldparam [Array] styles\n          def with_font_styles(attrs, font, &block)\n            # Building font styles.\n            styles = attrs.delete(:styles)\n\n            if styles\n              manual, styles = styles.partition do |style|\n                %i[bold italic].include?(style) && !font_has_style?(font[:name], style)\n              end\n            end\n\n            # Emulate bold style.\n            if manual && manual.include?(:bold)\n              pdf.stroke_color(font[:color])\n              pdf.line_width(font[:size] * 0.025)\n\n              # Change rendering mode to :fill_stroke.\n              attrs[:mode] = :fill_stroke\n            end\n\n            # Emulate italic style.\n            if manual && manual.include?(:italic)\n              # FIXME\n              # pdf.transformation_matrix(1, 0, 0.26, 1, 0, 0)\n            end\n\n            pdf.font(font[:name], size: font[:size]) do\n              pdf.fill_color(font[:color])\n              block.call(attrs, styles || [])\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/graphics.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Graphics\n          BASE_LINE_WIDTH = 0.9\n\n          private\n\n          # Change the default graphic states defined by Prawn.\n          def setup_custom_graphic_states\n            pdf.line_width(BASE_LINE_WIDTH)\n          end\n\n          # @param [Numeric] width\n          def line_width(width)\n            pdf.line_width(width * BASE_LINE_WIDTH)\n          end\n\n          # Delegate to Prawn::Document#save_graphic_state\n          # @see Prawn::Document#save_graphics_state\n          def save_graphics_state\n            pdf.save_graphics_state\n          end\n\n          # Delegate to Prawn::Document#restore_graphic_state\n          # @see Prawn::Document#restore_graphics_state\n          def restore_graphics_state\n            pdf.restore_graphics_state\n          end\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'graphics/attributes'\nrequire_relative 'graphics/basic'\nrequire_relative 'graphics/image'\nrequire_relative 'graphics/text'\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/page.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Page\n          JIS_SIZES = {\n            'B4' => [728.5, 1031.8],\n            'B5' => [515.9, 728.5]\n          }.freeze\n\n          # @param [Thinreports::BasicReport::Layout::Format] format\n          def start_new_page(format)\n            format_id =\n              if change_page_format?(format)\n                pdf.start_new_page(new_basic_page_options(format))\n                @current_page_format = format\n\n                create_format_stamp(format) unless format_stamp_registry.include?(format.identifier)\n                format.identifier\n              else\n                pdf.start_new_page(new_basic_page_options(current_page_format))\n                current_page_format.identifier\n              end\n\n            stamp(format_id.to_s)\n          end\n\n          def start_new_page_for_section_report(format)\n            @current_page_format = format\n            pdf.start_new_page(new_basic_page_options(current_page_format).merge(\n              top_margin: current_page_format.page_margin[0],\n              bottom_margin: current_page_format.page_margin[2]\n            ))\n          end\n\n          def max_content_height\n            pdf.margin_box.height\n          end\n\n          def add_blank_page\n            pdf.start_new_page(pdf.page_count.zero? ? { size: 'A4' } : {})\n          end\n\n          private\n\n          # @return [Thinreports::BasicReport::Layout::Format]\n          attr_reader :current_page_format\n\n          # @param [Thinreports::BasicReport::Layout::Format] new_format\n          # @return [Boolean]\n          def change_page_format?(new_format)\n            !current_page_format ||\n              current_page_format.identifier != new_format.identifier\n          end\n\n          # @param [Thinreports::BasicReport::Layout::Format] format\n          def create_format_stamp(format)\n            create_stamp(format.identifier.to_s) do\n              draw_template_items(format.attributes['items'])\n            end\n            format_stamp_registry << format.identifier\n          end\n\n          # @return [Array]\n          def format_stamp_registry\n            @format_stamp_registry ||= []\n          end\n\n          # @param [Thinreports::BasicReport::Layout::Format] format\n          # @return [Hash]\n          def new_basic_page_options(format)\n            options = { layout: format.page_orientation.to_sym }\n\n            options[:size] =\n              if format.user_paper_type?\n                [format.page_width.to_f, format.page_height.to_f]\n              else\n                case format.page_paper_type\n                # Convert B4(5)_ISO to B4(5)\n                when 'B4_ISO', 'B5_ISO'\n                  format.page_paper_type.delete('_ISO')\n                when 'B4', 'B5'\n                  JIS_SIZES[format.page_paper_type]\n                else\n                  format.page_paper_type\n                end\n              end\n            options\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document/parse_color.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module ParseColor\n          # @param [String] color\n          # @return [String]\n          def parse_color(color)\n            color = color.downcase\n\n            if color =~ /^#?[\\da-f]{6}$/\n              color.delete('#')\n            else\n              find_color_from_name(color)\n            end\n          end\n\n          private\n\n          # Supported only SAFE COLORS.\n          SUPPORTED_COLOR_NAMES = {\n            'red'     => 'ff0000',\n            'yellow'  => 'fff000',\n            'lime'    => '00ff00',\n            'aqua'    => '00ffff',\n            'blue'    => '0000ff',\n            'fuchsia' => 'ff00ff',\n            'maroon'  => '800000',\n            'olive'   => '808000',\n            'green'   => '008800',\n            'teal'    => '008080',\n            'navy'    => '000080',\n            'purple'  => '800080',\n            'black'   => '000000',\n            'gray'    => '808080',\n            'silver'  => 'c0c0c0',\n            'white'   => 'ffffff'\n          }.freeze\n\n          def find_color_from_name(name)\n            color = SUPPORTED_COLOR_NAMES[name]\n            raise Thinreports::BasicReport::Errors::UnsupportedColorName, name unless color\n            color\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/document.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'document/font'\nrequire_relative 'document/parse_color'\nrequire_relative 'document/graphics'\nrequire_relative 'document/draw_shape'\nrequire_relative 'document/draw_template_items'\nrequire_relative 'document/page'\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        class Document\n          include Utils\n\n          include PDF::Font\n          include PDF::ParseColor\n          include PDF::Graphics\n          include PDF::DrawShape\n          include PDF::DrawTemplateItems\n          include PDF::Page\n\n          # @return [Prawn::Document]\n          attr_reader :pdf\n\n          # @param [String] title (nil)\n          # @param [Hash] security (nil)\n          def initialize(title: nil, security: nil)\n            @pdf = Prawn::Document.new(\n              skip_page_creation: true,\n              margin: [0, 0],\n              info: {\n                CreationDate: Time.now,\n                Creator: 'Thinreports Generator for Ruby ' + Thinreports::VERSION,\n                Title: title\n              }\n            )\n            # Setup to Prawn::Document.\n            setup_fonts\n            setup_custom_graphic_states\n\n            # Encrypts the document.\n            @pdf.encrypt_document(security) if security\n          end\n\n          # Delegate to Prawn::Document#render\n          # @see Prawn::Document#render\n          def render\n            result = pdf.render\n            finalize\n            result\n          end\n\n          # Delegate to Prawn::Document#render_file\n          # @see Prawn::Document#render_file\n          def render_file(*args)\n            finalize\n            pdf.render_file(*args)\n          end\n\n          # @param [Numeric, String] x\n          # @param [Numeric, String] y\n          def translate(x, y, &block)\n            x, y = rpos(x, y)\n            pdf.translate(x, y, &block)\n          end\n\n          # @param [String] stamp_id\n          # @param [Array<Numeric>] at (nil)\n          def stamp(stamp_id, at = nil)\n            if at.nil?\n              pdf.stamp(stamp_id)\n            else\n              pdf.stamp_at(stamp_id, rpos(*at))\n            end\n          end\n\n          # Delegate to Prawn::Document#create_stamp\n          # @param [String] id\n          # @see Prawn::Document#create_stamp\n          def create_stamp(id, &block)\n            pdf.create_stamp(id, &block)\n          end\n\n          # @see #pdf\n          def internal\n            @pdf\n          end\n\n          private\n\n          def finalize\n            clean_temp_images\n          end\n\n          # @param [Array<String, Numeric>] values\n          # @return [Numeric, Array<Numeric>, nil]\n          def s2f(*values)\n            return nil if values.empty?\n\n            if values.size == 1\n              value = values.first\n              return nil unless value\n              value.is_a?(::Numeric) ? value : value.to_f\n            else\n              values.map { |v| s2f(v) }\n            end\n          end\n\n          # @param [Numeric, String] x\n          # @param [Numeric, String] y\n          # @return [Array<Float>]\n          def map_to_upper_left_relative_position(x, y)\n            x, y = s2f(x, y)\n            [x, -y]\n          end\n          alias rpos map_to_upper_left_relative_position\n\n          # @param [Numeric, String] x\n          # @param [Numeric, String] y\n          # @return [Array<Float>]\n          def map_to_upper_left_position(x, y)\n            x, y = s2f(x, y)\n            [x, pdf.bounds.height - y]\n          end\n          alias pos map_to_upper_left_position\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/drawer/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Drawer\n          # @abstract\n          class Base\n            # @param [Thinreports::BasicReport::Generator::PDF::Document] pdf\n            # @param [Thinreports::BasicReport::Core::Shape::Manager::Format] format\n            def initialize(pdf, format)\n              @pdf = pdf\n              @format = format\n              @stamps = []\n              @draw_at = nil\n            end\n\n            # @abstract\n            def draw\n              raise NotImplementedError\n            end\n\n            private\n\n            # @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape\n            # @return [String]\n            def pdf_stamp_id(shape)\n              \"#{@format.identifier}#{shape.identifier}\"\n            end\n\n            # @overload pdf_stamp(shape_id)\n            #   @param [String] shape_id\n            # @overload pdf_stamp(shape)\n            #   @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape\n            def pdf_stamp(shape)\n              shape = pdf_stamp_id(shape) unless shape.is_a?(::String)\n              @pdf.stamp(shape, @draw_at)\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape\n            def create_pdf_stamp(shape, &block)\n              @pdf.create_stamp(pdf_stamp_id(shape), &block)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/drawer/list.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Drawer\n          class List < Base\n            # @param (see PDF::Drawer::Base#initialize)\n            def initialize(pdf, format)\n              super\n              @sections = {}\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::PageState] list_page\n            def draw(list_page)\n              draw_section(list_page.header) if list_page.header\n              list_page.rows.each do |row|\n                draw_section(row)\n              end\n\n              # Returns Thinreports::BasicReport::Report::Page object\n              manager = list_page.parent.manager\n\n              list_id = list_page.id.to_s\n              manager.format.shapes.each do |id, shape|\n                next unless list_pageno?(list_id, shape)\n\n                shape = manager.final_shape(id)\n                @pdf.draw_shape_pageno(shape.internal,\n                                       list_page.no, list_page.manager.page_count)\n              end\n            end\n\n            private\n\n            # @param [String] list_id\n            # @param [Thinreports::BasicReport::Core::Shape::Base::Format] shape\n            # @return [Boolean]\n            def list_pageno?(list_id, shape)\n              shape.type == Thinreports::BasicReport::Core::Shape::PageNumber::TYPE_NAME &&\n                shape.target == list_id\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::SectionInterface] section\n            def draw_section(section)\n              internal = section.internal\n\n              base_top = @format.section_base_position_top(internal.section_name)\n              position = [internal.relative_left, base_top + internal.relative_top]\n\n              drawer(internal).draw(section, position)\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::SectionInternal] section\n            # @return [Thinreports::BasicReport::Generator::PDF::Drawer::ListSection]\n            def drawer(section)\n              @sections[section.section_name] ||= ListSection.new(@pdf, section)\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/drawer/list_section.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Drawer\n          class ListSection < Page\n            # @param pdf (see PDF::Drawer::Page#initialize)\n            # @param section [Thinreports::BasicReport::Core::Shape::List::SectionInternal] section\n            def initialize(pdf, section)\n              super(pdf, section.format)\n              @section = section\n              @stamp_created = false\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::List::SectionInternal] section\n            # @param [Array<Numeric>] at\n            def draw(section, at)\n              @draw_at = at\n              draw_section\n              super(section)\n            end\n\n            private\n\n            def draw_section\n              id = @format.identifier.to_s\n\n              unless @stamp_created\n                @pdf.create_stamp(id) { @pdf.draw_template_items(@format.attributes['items']) }\n                @stamp_created = true\n              end\n              pdf_stamp(id)\n            end\n\n            # @see Thinreports::BasicReport::Generator::PDF::Drawer::Page#draw_tblock_shape\n            def draw_tblock_shape(shape)\n              @pdf.translate(*@draw_at) { super }\n            end\n\n            # @see Thinreports::BasicReport::Generator::PDF::Drawer::Page#draw_iblock_shape\n            def draw_iblock_shape(shape)\n              @pdf.translate(*@draw_at) { super }\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/drawer/page.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        module Drawer\n          class Page < Base\n            # @param (see PDF::Drawer::Base#initialize)\n            def initialize(pdf, format)\n              super\n              @lists = {}\n            end\n\n            # @param [Thinreports::BasicReport::Report::Page] page\n            def draw(page)\n              manager = page.manager\n\n              manager.format.shapes.each_key do |id|\n                shape = manager.final_shape(id)\n                next unless shape\n\n                shape = shape.internal\n\n                if shape.type_of?(Core::Shape::PageNumber::TYPE_NAME)\n                  # Do not draw pageno if is not for Report\n                  draw_pageno_shape(shape, page) if page.count? && shape.for_report?\n                else\n                  draw_shape(shape)\n                end\n              end\n            end\n\n            private\n\n            def draw_shape(shape)\n              if shape.type_of?(Core::Shape::TextBlock::TYPE_NAME)\n                draw_tblock_shape(shape)\n              elsif shape.type_of?(Core::Shape::List::TYPE_NAME)\n                draw_list_shape(shape)\n              elsif shape.type_of?(Core::Shape::ImageBlock::TYPE_NAME)\n                draw_iblock_shape(shape)\n              else\n                id = shape.identifier\n                unless @stamps.include?(id)\n                  create_basic_shape_stamp(shape)\n                  @stamps << id\n                end\n                pdf_stamp(shape)\n              end\n            end\n\n            def draw_pageno_shape(shape, page)\n              @pdf.draw_shape_pageno(shape, page.no, page.report.page_count)\n            end\n\n            # @see #draw_shape\n            def draw_list_shape(shape)\n              drawer = @lists[shape.id] ||= List.new(@pdf, shape.format)\n              drawer.draw(shape)\n            end\n\n            # @see #draw_shape\n            def draw_tblock_shape(shape)\n              @pdf.draw_shape_tblock(shape)\n            end\n\n            # @see #draw_shape\n            def draw_iblock_shape(shape)\n              @pdf.draw_shape_iblock(shape)\n            end\n\n            # @param [Thinreports::BasicReport::Core::Shape::Base::Internal] shape\n            def create_basic_shape_stamp(shape)\n              if shape.type_of?('text')\n                create_text_stamp(shape)\n              elsif shape.type_of?('image')\n                create_image_stamp(shape)\n              elsif shape.type_of?('ellipse')\n                create_ellipse_stamp(shape)\n              elsif shape.type_of?('rect')\n                create_rect_stamp(shape)\n              elsif shape.type_of?('line')\n                create_line_stamp(shape)\n              end\n            end\n\n            # @see #create_basic_shape_stamp\n            def create_image_stamp(shape)\n              create_pdf_stamp(shape) do\n                @pdf.draw_shape_image(shape)\n              end\n            end\n\n            # @see #create_basic_shape_stamp\n            def create_rect_stamp(shape)\n              create_pdf_stamp(shape) do\n                @pdf.draw_shape_rect(shape)\n              end\n            end\n\n            # @see #create_basic_shape_stamp\n            def create_ellipse_stamp(shape)\n              create_pdf_stamp(shape) do\n                @pdf.draw_shape_ellipse(shape)\n              end\n            end\n\n            # @see #create_basic_shape_stamp\n            def create_line_stamp(shape)\n              create_pdf_stamp(shape) do\n                @pdf.draw_shape_line(shape)\n              end\n            end\n\n            # @see #create_basic_shape_stamp\n            def create_text_stamp(shape)\n              create_pdf_stamp(shape) do\n                @pdf.draw_shape_text(shape)\n              end\n            end\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/prawn_ext/calc_image_dimensions.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      module PrawnExt\n        module CalcImageDimensions\n          # Implement :auto_fit option for image size calculation.\n          #\n          # When the image is larger than the box, the original: fit option does not change\n          # the image size. The :auto_fit option changes the image size to fit in the box\n          # while maintaining the aspect ratio.\n          #\n          # Usage:\n          #   image '/path/to/image.png', at: [100, 100], auto_fit: [100, 100]\n          #\n          def calc_image_dimensions(options)\n            if options[:auto_fit]\n              image_width = options[:width] || width\n              image_height = options[:height] || height\n\n              box_width, box_height = options.delete(:auto_fit)\n\n              options[:fit] = [box_width, box_height] if image_width > box_width || image_height > box_height\n            end\n            super(options)\n          end\n        end\n      end\n    end\n  end\nend\n\nPrawn::Images::Image.prepend Thinreports::BasicReport::Generator::PrawnExt::CalcImageDimensions\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/prawn_ext/width_of.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      module PrawnExt\n        module WidthOf\n          # This patch fixes the character_spacing effect on text width calculation.\n          #\n          # The original #width_of:\n          #\n          #   width_of('abcd') #=> 4 + 4 = 8\n          #\n          # The #width_of in this patch:\n          #\n          #   width_of('abcd') #=> 4 + 3 = 7\n          #\n          def width_of(*)\n            width = super - character_spacing\n            width > 0 ? width : 0\n          end\n        end\n      end\n    end\n  end\nend\n\n# Prawn v2.3 and later includes this patch by https://github.com/prawnpdf/prawn/pull/1117.\nif Prawn::VERSION < '2.3.0'\n  Prawn::Document.prepend Thinreports::BasicReport::Generator::PrawnExt::WidthOf\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf/prawn_ext.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'prawn_ext/width_of'\nrequire_relative 'prawn_ext/calc_image_dimensions'\n\nPrawn::Font::AFM.hide_m17n_warning = true\n"
  },
  {
    "path": "lib/thinreports/basic_report/generator/pdf.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'prawn'\nrequire 'prawn/disable_word_break'\n\nPrawn::DisableWordBreak.config.default = false\n\nmodule Thinreports\n  module BasicReport\n    module Generator\n      class PDF\n        # @return [Thinreports::BasicReport::Report::Base]\n        attr_reader :report\n\n        # @param [Thinreports::BasicReport::Report::Base] report\n        # @param [Hash] security (nil)\n        # @param [String] title (nil)\n        def initialize(report, security: nil, title: nil)\n          report.finalize\n\n          @report = report.internal\n          title ||= default_layout ? default_layout.format.report_title : nil\n\n          @document = Document.new(title: title, security: security)\n          @drawers = {}\n        end\n\n        # @param [String, nil] filename\n        # @return [String, nil]\n        def generate(filename = nil)\n          draw_report\n          filename ? @document.render_file(filename) : @document.render\n        end\n\n        def default_layout\n          report.default_layout\n        end\n\n        private\n\n        def draw_report\n          report.pages.each do |page|\n            draw_page(page)\n          end\n        end\n\n        def draw_page(page)\n          return @document.add_blank_page if page.blank?\n\n          format = page.layout.format\n          @document.start_new_page(format)\n\n          drawer(format).draw(page)\n        end\n\n        def drawer(format)\n          @drawers[format.identifier] ||= Drawer::Page.new(@document, format)\n        end\n      end\n    end\n  end\nend\n\nrequire_relative 'pdf/prawn_ext'\nrequire_relative 'pdf/document'\nrequire_relative 'pdf/drawer/base'\nrequire_relative 'pdf/drawer/page'\nrequire_relative 'pdf/drawer/list'\nrequire_relative 'pdf/drawer/list_section'\n"
  },
  {
    "path": "lib/thinreports/basic_report/layout/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Layout\n      class Base\n        EXT_NAME = 'tlf'\n        include Utils\n\n        class << self\n          # @param [String] filename\n          # @return [Thinreports::BasicReport::Layout::Format]\n          # @raise [Thinreports::BasicReport::Errors::InvalidLayoutFormat]\n          # @raise [Thinreports::BasicReport::Errors::IncompatibleLayoutFormat]\n          def load_format(filename)\n            filename += \".#{EXT_NAME}\" unless filename =~ /\\.#{EXT_NAME}$/\n\n            raise Thinreports::BasicReport::Errors::LayoutFileNotFound unless File.exist?(filename)\n            # Build format.\n            Thinreports::BasicReport::Layout::Format.build(filename)\n          end\n        end\n\n        attr_reader :format\n\n        # @return [String]\n        attr_reader :filename\n\n        # @return [Symbol]\n        attr_reader :id\n\n        # @param [String] filename\n        # @param [Hash] options\n        # @option options [Symbol] :id (nil)\n        def initialize(filename, options = {})\n          @filename = filename\n          @format = self.class.load_format(filename)\n          @id = options[:id]\n        end\n\n        # @return [Boolean] Return the true if is default layout.\n        def default?\n          @id.nil?\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/layout/format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'json'\n\nmodule Thinreports\n  module BasicReport\n    module Layout\n      class Format < Core::Shape::Manager::Format\n        config_reader last_version: %w[version]\n        config_reader report_title: %w[title]\n        config_reader page_paper_type: %w[report paper-type],\n                      page_width: %w[report width],\n                      page_height: %w[report height],\n                      page_orientation: %w[report orientation]\n\n        class << self\n          def build(filename)\n            schema = JSON.parse(read_file(filename))\n            schema_version = Layout::Version.new(schema['version'])\n\n            unless schema_version.compatible?\n              raise Errors::IncompatibleLayoutFormat.new(\n                filename, schema['version'],\n                Layout::Version.compatible_rules.join(' and ')\n              )\n            end\n\n            if schema_version.legacy?\n              warn '[DEPRECATION] Support for the layout file with old format' \\\n                   ' that generated with Editor 0.8 or lower will be dropped in Thinreports 1.1.' \\\n                   ' Please convert to new layout format using Thinreports Editor 0.9 or 1.0.'\n              schema = Layout::LegacySchema.new(schema).upgrade\n            end\n\n            new schema\n          end\n\n          def read_file(filename)\n            File.read(filename, encoding: 'UTF-8')\n          end\n        end\n\n        def initialize(*)\n          super\n          initialize_items(attributes['items'])\n        end\n\n        def user_paper_type?\n          page_paper_type == 'user'\n        end\n\n        private\n\n        def initialize_items(item_schemas)\n          item_schemas.each do |item_schema|\n            id, type = item_schema.values_at 'id', 'type'\n\n            next if id.empty? && type != 'page-number'\n\n            item = Core::Shape::Format(type).new(item_schema)\n            shapes[item.id.to_sym] = item\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/layout/legacy_schema.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'json'\nrequire 'rexml/document'\n\nmodule Thinreports\n  module BasicReport\n    module Layout\n      class LegacySchema\n        include Utils\n\n        def initialize(legacy_schema)\n          @legacy_schema = legacy_schema\n          @legacy_svg = legacy_schema['svg'].dup\n          @legacy_item_schemas = extract_legacy_item_schemas(legacy_svg)\n\n          @legacy_svg = cleanup_svg(@legacy_svg)\n        end\n\n        def upgrade\n          config = legacy_schema['config']\n          page_config = config['page']\n\n          {\n            'version' => legacy_schema['version'],\n            'title' => legacy_schema['config']['title'],\n            'report' => {\n              'paper-type' => page_config['paper-type'],\n              'width' => page_config['width'].to_f,\n              'height' => page_config['height'].to_f,\n              'orientation' => page_config['orientation'],\n              'margin' => page_config.values_at(\n                'margin-top',\n                'margin-right',\n                'margin-bottom',\n                'margin-left'\n              ).map(&:to_f)\n            },\n            'items' => item_schemas\n          }\n        end\n\n        attr_reader :legacy_schema, :legacy_svg, :legacy_item_schemas\n\n        def item_schemas\n          svg = REXML::Document.new(legacy_svg)\n          build_item_schemas_from_svg(svg.elements['/svg/g'])\n        end\n\n        def build_item_schemas_from_svg(svg_elements)\n          return [] unless svg_elements\n\n          items = []\n\n          svg_elements.each do |item_element|\n            item_attributes = item_element.attributes\n\n            items <<\n              case item_element.attributes['class']\n              when 's-text' then text_item_schema(item_attributes, extract_texts_from(item_element))\n              when 's-image' then image_item_schema(item_attributes)\n              when 's-rect' then rect_item_schema(item_attributes)\n              when 's-ellipse' then ellipse_item_schema(item_attributes)\n              when 's-line' then line_item_schema(item_attributes)\n              when 's-tblock' then text_block_item_schema(item_attributes)\n              when 's-iblock' then image_block_item_schema(item_attributes)\n              when 's-pageno' then page_number_item_schema(item_attributes)\n              when 's-list' then list_item_schema(item_element)\n              else raise 'Unknown item type'\n              end\n          end\n\n          items\n        end\n\n        def text_item_schema(attributes, texts)\n          {\n            'id' => attributes['x-id'],\n            'type' => Core::Shape::Text::TYPE_NAME,\n            'x' => attributes['x-left'].to_f,\n            'y' => attributes['x-top'].to_f,\n            'width' => attributes['x-width'].to_f,\n            'height' => attributes['x-height'].to_f,\n            'display' => display(attributes['x-display']),\n            'texts' => texts,\n            'style' => {\n              'font-family' => [attributes['font-family']],\n              'font-size' => attributes['font-size'].to_f,\n              'color' => attributes['fill'],\n              'font-style' => font_style(attributes),\n              'text-align' => text_align(attributes['text-anchor']),\n              'vertical-align' => vertical_align(attributes['x-valign']),\n              'line-height' => line_height(attributes['x-line-height']),\n              'letter-spacing' => letter_spacing(attributes['kerning'])\n            }\n          }\n        end\n\n        def rect_item_schema(attributes)\n          {\n            'id' => attributes['x-id'],\n            'type' => 'rect',\n            'x' => attributes['x'].to_f,\n            'y' => attributes['y'].to_f,\n            'width' => attributes['width'].to_f,\n            'height' => attributes['height'].to_f,\n            'display' => display(attributes['x-display']),\n            'border-radius' => attributes['rx'].to_i,\n            'style' => {\n              'border-width' => attributes['stroke-width'].to_f,\n              'border-color' => attributes['stroke'],\n              'border-style' => attributes['x-stroke-type'],\n              'fill-color' => attributes['fill']\n            }\n          }\n        end\n\n        def line_item_schema(attributes)\n          {\n            'id' => attributes['x-id'],\n            'type' => 'line',\n            'x1' => attributes['x1'].to_f,\n            'y1' => attributes['y1'].to_f,\n            'x2' => attributes['x2'].to_f,\n            'y2' => attributes['y2'].to_f,\n            'display' => display(attributes['x-display']),\n            'style' => {\n              'border-width' => attributes['stroke-width'].to_f,\n              'border-color' => attributes['stroke'],\n              'border-style' => attributes['x-stroke-type']\n            }\n          }\n        end\n\n        def ellipse_item_schema(attributes)\n          {\n            'id' => attributes['x-id'],\n            'type' => 'ellipse',\n            'cx' => attributes['cx'].to_f,\n            'cy' => attributes['cy'].to_f,\n            'rx' => attributes['rx'].to_f,\n            'ry' => attributes['ry'].to_f,\n            'display' => display(attributes['x-display']),\n            'style' => {\n              'border-width' => attributes['stroke-width'].to_f,\n              'border-color' => attributes['stroke'],\n              'border-style' => attributes['x-stroke-type'],\n              'fill-color' => attributes['fill']\n            }\n          }\n        end\n\n        def image_item_schema(attributes)\n          _, image_type, image_data = attributes['xlink:href'].match(%r{^data:(image/[a-z]+?);base64,(.+)}).to_a\n\n          {\n            'id' => attributes['x-id'],\n            'type' => 'image',\n            'x' => attributes['x'].to_f,\n            'y' => attributes['y'].to_f,\n            'width' => attributes['width'].to_f,\n            'height' => attributes['height'].to_f,\n            'display' => display(attributes['x-display']),\n            'data' => {\n              'mime-type' => image_type,\n              'base64' => image_data\n            }\n          }\n        end\n\n        def page_number_item_schema(attributes)\n          {\n            'id' => attributes['x-id'],\n            'type' => Core::Shape::PageNumber::TYPE_NAME,\n            'x' => attributes['x-left'].to_f,\n            'y' => attributes['x-top'].to_f,\n            'width' => attributes['x-width'].to_f,\n            'height' => attributes['x-height'].to_f,\n            'format' => attributes['x-format'],\n            'target' => attributes['x-target'],\n            'display' => display(attributes['x-display']),\n            'style' => {\n              'font-family' => [attributes['font-family']],\n              'font-size' => attributes['font-size'].to_f,\n              'color' => attributes['fill'],\n              'font-style' => font_style(attributes),\n              'text-align' => text_align(attributes['text-anchor']),\n              'overflow' => attributes['x-overflow']\n            }\n          }\n        end\n\n        def image_block_item_schema(attributes)\n          {\n            'id' => attributes['x-id'],\n            'type' => Core::Shape::ImageBlock::TYPE_NAME,\n            'x' => attributes['x-left'].to_f,\n            'y' => attributes['x-top'].to_f,\n            'width' => attributes['x-width'].to_f,\n            'height' => attributes['x-height'].to_f,\n            'display' => display(attributes['x-display']),\n            'style' => {\n              'position-x' => attributes['x-position-x'],\n              'position-y' => image_position_y(attributes['x-position-y'])\n            }\n          }\n        end\n\n        def text_block_item_schema(attributes)\n          text_format = {\n            'base' => attributes['x-format-base'],\n            'type' => attributes['x-format-type']\n          }\n          case text_format['type']\n          when 'datetime'\n            text_format['datetime'] = {\n              'format' => attributes['x-format-datetime-format']\n            }\n          when 'number'\n            text_format['number'] = {\n              'delimiter' => attributes['x-format-number-delimiter'],\n              'precision' => attributes['x-format-number-precision'].to_i\n            }\n          when 'padding'\n            text_format['padding'] = {\n              'length' => attributes['x-format-padding-length'].to_i,\n              'char' => attributes['x-format-padding-char'],\n              'direction' => attributes['x-format-padding-direction']\n            }\n          end\n\n          {\n            'id' => attributes['x-id'],\n            'type' => Core::Shape::TextBlock::TYPE_NAME,\n            'x' => attributes['x-left'].to_f,\n            'y' => attributes['x-top'].to_f,\n            'width' => attributes['x-width'].to_f,\n            'height' => attributes['x-height'].to_f,\n            'display' => display(attributes['x-display']),\n            'value' => attributes['x-value'],\n            'multiple-line' => attributes['x-multiple'] == 'true',\n            'format' => text_format,\n            'reference-id' => attributes['x-ref-id'],\n            'style' => {\n              'font-family' => [attributes['font-family']],\n              'font-size' => attributes['font-size'].to_f,\n              'color' => attributes['fill'],\n              'font-style' => font_style(attributes),\n              'text-align' => text_align(attributes['text-anchor']),\n              'vertical-align' => vertical_align(attributes['x-valign']),\n              'line-height' => line_height(attributes['x-line-height']),\n              'letter-spacing' => letter_spacing(attributes['kerning']),\n              'overflow' => attributes['x-overflow'],\n              'word-wrap' => attributes['x-word-wrap'] || ''\n            }\n          }\n        end\n\n        def list_item_schema(legacy_element)\n          legacy_schema = legacy_item_schemas[legacy_element.attributes['x-id']]\n\n          header = list_section_schema('header', legacy_element, legacy_schema)\n          detail = list_section_schema('detail', legacy_element, legacy_schema)\n          page_footer = list_section_schema('page-footer', legacy_element, legacy_schema)\n          footer = list_section_schema('footer', legacy_element, legacy_schema)\n\n          schema = {\n            'id' => legacy_schema['id'],\n            'type' => Core::Shape::List::TYPE_NAME,\n            'content-height' => legacy_schema['content-height'].to_f,\n            'auto-page-break' => legacy_schema['page-break'] == 'true',\n            'display' => display(legacy_schema['display']),\n            'header' => header,\n            'detail' => detail,\n            'page-footer' => page_footer,\n            'footer' => footer\n          }\n\n          page_footer['translate']['y'] += detail['height'] if page_footer['enabled']\n\n          if footer['enabled']\n            footer['translate']['y'] += detail['height']\n            footer['translate']['y'] += page_footer['height'] if page_footer['enabled']\n          end\n          schema\n        end\n\n        def list_section_schema(section_name, legacy_list_element, legacy_list_schema)\n          legacy_section_schema = legacy_list_schema[section_name]\n          return {} if legacy_section_schema.empty?\n\n          section_item_elements = legacy_list_element.elements[\"g[@class='s-list-#{section_name}']\"]\n\n          section_schema = {\n            'height' => legacy_section_schema['height'].to_f,\n            'translate' => {\n              'x' => legacy_section_schema['translate']['x'].to_f,\n              'y' => legacy_section_schema['translate']['y'].to_f\n            },\n            'items' => build_item_schemas_from_svg(section_item_elements)\n          }\n\n          unless section_name == 'detail'\n            section_schema['enabled'] = legacy_list_schema[\"#{section_name}-enabled\"] == 'true'\n          end\n          section_schema\n        end\n\n        def extract_texts_from(text_item_element)\n          [].tap do |texts|\n            text_item_element.each_element('text') { |e| texts << e.text }\n          end\n        end\n\n        def image_position_y(legacy_position_y)\n          case legacy_position_y\n          when 'top' then 'top'\n          when 'center' then 'middle'\n          when 'bottom' then 'bottom'\n          end\n        end\n\n        def display(legacy_display)\n          legacy_display == 'true'\n        end\n\n        def font_style(attributes)\n          style = []\n          style << 'bold' if attributes['font-weight'] == 'bold'\n          style << 'italic' if attributes['font-style'] == 'italic'\n          style << 'underline' if attributes['text-decoration'].include?('underline')\n          style << 'linethrough' if attributes['text-decoration'].include?('line-through')\n          style\n        end\n\n        def text_align(legacy_text_align)\n          case legacy_text_align\n          when 'start' then 'left'\n          when 'middle' then 'center'\n          when 'end' then 'right'\n          else 'left'\n          end\n        end\n\n        def vertical_align(legacy_vertical_align)\n          return '' unless legacy_vertical_align\n\n          case legacy_vertical_align\n          when 'top' then 'top'\n          when 'center' then 'middle'\n          when 'bottom' then 'bottom'\n          else 'top'\n          end\n        end\n\n        def line_height(legacy_line_height)\n          blank_value?(legacy_line_height) ? '' : legacy_line_height.to_f\n        end\n\n        def letter_spacing(legacy_letter_spacing)\n          case legacy_letter_spacing\n          when 'auto', '' then ''\n          else legacy_letter_spacing.to_f\n          end\n        end\n\n        def extract_legacy_item_schemas(svg)\n          items = {}\n          svg.scan(/<!--SHAPE(.*?)SHAPE-->/) do |(item_schema_json)|\n            item_schema = JSON.parse(item_schema_json)\n            items[item_schema['id']] = item_schema\n          end\n          items\n        end\n\n        def cleanup_svg(svg)\n          cleaned_svg = svg.gsub(/<!--SHAPE.*?SHAPE-->/, '')\n          cleaned_svg.gsub(/<!--LAYOUT(.*?)LAYOUT-->/) { $1 }\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/layout/version.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Layout\n      class Version\n        COMPATIBLE_RULES = ['>= 0.8.0', '< 1.0.0'].freeze\n        NEW_SCHEMA_FROM = '0.9.0'\n\n        class << self\n          def compatible_rules\n            COMPATIBLE_RULES\n          end\n        end\n\n        def initialize(schema_version)\n          @schema_version = normalize_version(schema_version)\n        end\n\n        def compatible?\n          self.class.compatible_rules.all? do |rule|\n            op, ver = rule.split(' ')\n            schema_version.send(op.to_sym, normalize_version(ver))\n          end\n        end\n\n        def legacy?\n          @schema_version < normalize_version(NEW_SCHEMA_FROM)\n        end\n\n        private\n\n        attr_reader :schema_version\n\n        def normalize_version(version)\n          Gem::Version.create(version)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/layout.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Layout\n      # @see Thinreports::BasicReport::Layout::Base#initialize\n      def self.new(filename, options = {})\n        Base.new(filename, options)\n      end\n    end\n  end\nend\n\nrequire_relative 'layout/version'\nrequire_relative 'layout/base'\nrequire_relative 'layout/format'\nrequire_relative 'layout/legacy_schema'\n"
  },
  {
    "path": "lib/thinreports/basic_report/report/base.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Report\n      class Base\n        extend  Forwardable\n        include Utils\n\n        class << self\n          # @param options (see #initialize)\n          # @option options (see #initialize)\n          # @yield [report]\n          # @yieldparam [Thinreports::BasicReport::Report::Base] report\n          # @return [Thinreports::BasicReport::Report::Base]\n          def create(options = {}, &block)\n            raise ArgumentError, '#create requires a block' unless block_given?\n\n            report = new(options)\n            call_block_in(report, &block)\n            report.finalize\n\n            report\n          end\n\n          # @param layout (see #initialize)\n          # @param filename (see #generate)\n          # @param security (see #generate)\n          # @param title (see #generate)\n          # @param [Hash] report ({}) DEPRECATED. Options for Report.\n          # @param [Hash] generator ({}) DEPRECATED. Options for Generator.\n          # @yield (see .create)\n          # @yieldparam (see .create)\n          # @return [String]\n          def generate(layout: nil, filename: nil, security: nil, title: nil, report: {}, generator: {}, &block)\n            raise ArgumentError, '#generate requires a block' unless block_given?\n\n            if report.any? || generator.any?\n              warn '[DEPRECATION] :report and :generator argument has been deprecated. ' \\\n                   'Use :layout and :filename, :security argument instead.'\n            end\n\n            layout ||= report[:layout]\n            filename ||= generator[:filename]\n            security ||= generator[:security]\n\n            report = create(layout: layout, &block)\n            report.generate(filename: filename, security: security, title: title)\n          end\n        end\n\n        # @return [Thinreports::BasicReport::Report::Internal]\n        attr_reader :internal\n\n        # @return [Integer]\n        attr_reader :start_page_number\n\n        # @return [Thinreports::BasicReport::Report::Page]\n        def_delegator :internal, :page\n\n        # @return [Integer]\n        def_delegator :internal, :page_count\n\n        # @return [Array<Thinreports::BasicReport::Report::Page>]\n        def_delegator :internal, :pages\n\n        # @return [Thinreports::BasicReport::Layout::Base]\n        def_delegator :internal, :default_layout\n\n        # @param [Hash] options\n        # @option options [String, nil] :layout (nil)\n        def initialize(options = {})\n          @internal = Report::Internal.new(self, options)\n          @start_page_number = 1\n        end\n\n        # @yield [page]\n        # @yieldparam [Thinreports::BasicReport::Report::Page] page\n        # @example\n        #   report.on_page_create do |page|\n        #     page.item(:header_title).value = 'Title'\n        #   end\n        def on_page_create(&block)\n          internal.page_create_handler = block\n        end\n\n        # @param [Integer] page_number\n        def start_page_number_from(page_number)\n          @start_page_number = page_number\n        end\n\n        # @param [String] layout filename of layout file\n        # @param [Hash] options\n        # @option options [Boolean] :default (true)\n        # @option options [Symbol] :id (nil)\n        # @example\n        #   report.use_layout '/path/to/default_layout.tlf' # Default layout\n        #   report.use_layout '/path/to/default_layout.tlf', default: true\n        #   report.use_layout '/path/to/other_layout', id: :other_layout\n        def use_layout(layout, options = {})\n          internal.register_layout(layout, options)\n        end\n\n        # @example\n        #   page = report.start_new_page\n        #\n        #   report.start_new_page do |page|\n        #     page.item(:text).value = 'value'\n        #   end\n        #\n        #   report.use_layout 'foo.tlf', default: true\n        #   report.use_layout 'bar.tlf', id: :bar\n        #\n        #   report.start_new_page                   # Use 'foo.tlf'\n        #   report.start_new_page layout: :bar      # Use 'bar.tlf'\n        #   report.start_new_page layout: 'boo.tlf' # Use 'boo.tlf'\n        # @param [Hash] options\n        # @option options [String, Symbol] :layout (nil)\n        # @option options [Boolean] :count (true)\n        # @yield [page]\n        # @yieldparam [Thinreports::BasicReport::Report::Page] page\n        # @return [Thinreports::BasicReport::Report::Page]\n        def start_new_page(options = {}, &block)\n          layout = internal.load_layout(options.delete(:layout))\n\n          raise Thinreports::BasicReport::Errors::NoRegisteredLayoutFound unless layout\n\n          page = internal.add_page(Report::Page.new(self, layout, options))\n          call_block_in(page, &block)\n        end\n\n        # @param [Hash] options\n        # @option options [Boolean] :count (true)\n        # @return [Thinreports::BasicReport::Report::BlankPage]\n        def add_blank_page(options = {})\n          internal.add_page(Report::BlankPage.new(options[:count]))\n        end\n        alias blank_page add_blank_page\n\n        # @param [Symbol, nil] id\n        # @return [Thinreports::BasicReport::Layout::Base]\n        def layout(id = nil)\n          if id\n            internal.layout_registry[id] ||\n              raise(Thinreports::BasicReport::Errors::UnknownLayoutId)\n          else\n            internal.default_layout\n          end\n        end\n\n        # @param [String] filename\n        # @param [Hash] security (see http://prawnpdf.org/api-docs/2.0/Prawn/Document/Security.html#encrypt_document-instance_method)\n        # @param [String] title Value of the title attribute of the PDF document metadata.\n        #   if nil, the title of the default layout file is set.\n        # @return [String]\n        # @example Generate PDF data\n        #   report.generate # => \"%PDF-1.4....\"\n        # @example Create a PDF file\n        #   report.generate(filename: 'foo.pdf')\n        def generate(filename: nil, security: nil, title: nil)\n          Thinreports::BasicReport::Generator::PDF.new(self, security: security, title: title).generate(filename)\n        end\n\n        # @see Thinreports::BasicReport::Core::Shape::Manager::Target#list\n        def list(id = nil, &block)\n          start_new_page if page.nil? || page.finalized?\n          page.list(id, &block)\n        end\n\n        def_delegators :internal, :finalize, :finalized?\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/report/internal.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Report\n      class Internal\n        attr_reader :pages\n        attr_reader :page\n        attr_reader :page_count\n        attr_reader :default_layout\n        attr_reader :layout_registry\n\n        attr_accessor :page_create_handler\n\n        # @param [Thinreports::BasicReport::Report::Base] report\n        # @param options (see Thinreports::BasicReport::Report::Base#initialize)\n        def initialize(report, options)\n          @report = report\n          @default_layout = options[:layout] ? init_layout(options[:layout]) : nil\n\n          @layout_registry = {}\n          @finalized = false\n          @pages = []\n          @page = nil\n          @page_count = 0\n\n          @page_create_handler = nil\n        end\n\n        # @see Thinreports::BasicReport::Report::Base#use_layout\n        def register_layout(layout, options = {})\n          if options.empty? || options[:default]\n            @default_layout = init_layout(layout)\n          else\n            id = options[:id].to_sym\n\n            raise ArgumentError, \"Id :#{id} is already in use.\" if layout_registry.key?(id)\n            layout_registry[id] = init_layout(layout, id)\n          end\n        end\n\n        def add_page(new_page)\n          finalize_current_page\n          insert_page(new_page)\n        end\n\n        def copy_page\n          finalize_current_page(at: :copy)\n          insert_page(page.copy)\n        end\n\n        def finalize\n          return if finalized?\n\n          finalize_current_page\n          @finalized = true\n        end\n\n        def finalized?\n          @finalized\n        end\n\n        def load_layout(id_or_filename)\n          return @default_layout if id_or_filename.nil?\n\n          layout =\n            case id_or_filename\n            when Symbol\n              layout_registry[id_or_filename]\n            when String\n              init_layout(id_or_filename)\n            else\n              raise ArgumentError, 'Invalid argument for layout.'\n            end\n\n          @default_layout ||= layout\n          layout\n        end\n\n        private\n\n        def insert_page(new_page)\n          @pages << new_page\n\n          if new_page.count?\n            @page_count += 1\n            new_page.no = @page_count\n          end\n\n          @page_create_handler.call(new_page) if !new_page.blank? && @page_create_handler\n          @page = new_page\n        end\n\n        # @param (see Thinreports::BasicReport::Report::Page#finalize)\n        def finalize_current_page(options = {})\n          page.finalize(options) unless page.nil? || page.blank?\n        end\n\n        def init_layout(filename, id = nil)\n          filename = filename.to_path if filename.is_a?(Pathname)\n\n          Thinreports::BasicReport::Layout.new(filename, id: id)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/report/page.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Report\n      class BlankPage\n        # @example\n        #   3.times do\n        #     page = report.start_new_page\n        #     puts page.no\n        #   end\n        #   # => 1, 2, 3\n        # @return [Integer]\n        attr_accessor :no\n\n        # @param [Boolean] count (nil)\n        def initialize(count = nil)\n          @count = count.nil? ? true : count\n        end\n\n        # @example\n        #   page = report.start_new_page\n        #   page.count? # => true\n        #\n        #   page = report.start_new_page count: false\n        #   page.count? # => false\n        # @return [Boolean]\n        def count?\n          @count\n        end\n\n        # @return [Boolean] (true)\n        def blank?\n          true\n        end\n      end\n\n      class Page < BlankPage\n        include Core::Shape::Manager::Target\n\n        # @return [Thinreports::BasicReport::Report::Base]\n        attr_reader :report\n\n        # @return [Thinreports::BasicReport::Layout::Base]\n        attr_reader :layout\n\n        # @param [Thinreports::BasicReport::Report::Base] report\n        # @param [Thinreports::BasicReport::Layout::Base] layout\n        # @param [Hash] options ({})\n        # @option options [Boolean] :count (true)\n        def initialize(report, layout, options = {})\n          super(options.key?(:count) ? options[:count] : true)\n\n          @report = report\n          @layout = layout\n          @finalized = false\n\n          initialize_manager(layout.format) do |f|\n            Core::Shape::Interface(self, f)\n          end\n        end\n\n        # @return [Boolean] (false)\n        def blank?\n          false\n        end\n\n        def copy\n          new_page = self.class.new(report, layout, count: count?)\n\n          manager.shapes.each do |id, shape|\n            new_shape = shape.copy(new_page)\n            new_page.manager.shapes[id] = new_shape\n\n            new_page.manager.lists[id] = new_shape if new_shape.internal.type_of?(Core::Shape::List::TYPE_NAME)\n          end\n          new_page\n        end\n\n        # @param [Hash] options\n        # @option options [:create, :copy] :at (:create)\n        def finalize(options = {})\n          at = options[:at] || :create\n\n          # For list shapes.\n          manager.lists.each_value { |list| list.manager.finalize } if at == :create\n\n          @finalized = true\n        end\n\n        def finalized?\n          @finalized\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/basic_report/report.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module BasicReport\n    module Report\n      # @see Thinreports::BasicReport::Report::Base#initialize\n      def self.new(*args)\n        Base.new(*args)\n      end\n\n      # @see Thinreports::BasicReport::Report::Base#create\n      def self.create(*args, &block)\n        Base.create(*args, &block)\n      end\n\n      # @see Thinreports::BasicReport::Report::Base#generate\n      def self.generate(**args, &block)\n        Base.generate(**args, &block)\n      end\n    end\n  end\nend\n\nrequire_relative 'report/base'\nrequire_relative 'report/internal'\nrequire_relative 'report/page'\n"
  },
  {
    "path": "lib/thinreports/basic_report.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'basic_report/core/utils'\nrequire_relative 'basic_report/core/errors'\nrequire_relative 'basic_report/core/format/base'\nrequire_relative 'basic_report/core/shape'\nrequire_relative 'basic_report/core/utils'\nrequire_relative 'basic_report/report'\nrequire_relative 'basic_report/layout'\nrequire_relative 'basic_report/generator/pdf'\n\nmodule Thinreports\n  Report = BasicReport::Report\n  Layout = BasicReport::Layout\nend\n"
  },
  {
    "path": "lib/thinreports/config.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  # @yield [config]\n  # @yieldparam [Thinreports::Configuration] config\n  def self.configure(&block)\n    block.call(config)\n  end\n\n  # @return [Thinreports::Configuration]\n  def self.config\n    @config ||= Thinreports::Configuration.new\n  end\n\n  class Configuration\n    def initialize\n      @fallback_fonts = []\n    end\n\n    # @return [Array<String>]\n    # @example\n    #   config.fallback_fonts # => ['Times New Roman', '/path/to/font.ttf']\n    def fallback_fonts\n      @fallback_fonts ||= []\n    end\n\n    # @param [Array<String>,String] font_names\n    # @example\n    #   config.fallback_fonts = 'Times New Roman'\n    #   config.fallback_fonts = '/path/to/font.ttf'\n    #   config.fallback_fonts = ['/path/to/font.ttf', 'IPAGothic']\n    def fallback_fonts=(font_names)\n      @fallback_fonts = font_names.is_a?(Array) ? font_names : [font_names]\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/build.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'schema/loader'\nrequire_relative 'builder/report_builder'\n\nmodule Thinreports\n  module SectionReport\n    class Build\n      def call(report_params)\n        schema = load_schema(report_params)\n        params = report_params[:params] || {}\n\n        Builder::ReportBuilder.new(schema).build(params)\n      end\n\n      private\n\n      def load_schema(report_params)\n        loader = Schema::Loader.new\n\n        case\n        when report_params[:layout_file]\n          loader.load_from_file(report_params[:layout_file])\n        when report_params[:layout_data]\n          loader.load_from_data(report_params[:layout_data])\n        else\n          raise Errors::LayoutFileNotFound\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/builder/item_builder.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'stack_view_builder'\n\nmodule Thinreports\n  module SectionReport\n    module Builder\n      class ItemBuilder\n        Context = Struct.new(:parent_schema)\n\n        def initialize(item_schema, parent_schema)\n          @item = Core::Shape::Interface(nil, item_schema)\n          @parent_schema = parent_schema\n        end\n\n        def build(item_params)\n          params = build_params(item_params)\n\n          item.visible(params[:display]) if params.key?(:display)\n          item.value(params[:value]) if params.key?(:value)\n          item.styles(params[:styles]) if params.key?(:styles)\n\n          if item.internal.format.attributes['type'] == Core::Shape::StackView::TYPE_NAME\n            StackViewBuilder.new(item).update(params)\n          end\n\n          item\n        end\n\n        private\n\n        attr_reader :item, :parent_schema\n\n        def build_params(params)\n          return {} unless params\n\n          case params\n          when Hash\n            params\n          when Proc\n            params.call(Context.new(parent_schema))\n          else\n            { value: params }\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/builder/report_builder.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'report_data'\nrequire_relative 'item_builder'\n\nmodule Thinreports\n  module SectionReport\n    module Builder\n      class ReportBuilder\n        def initialize(schema)\n          @schema = schema\n        end\n\n        def build(params)\n          ReportData::Main.new(\n            schema,\n            build_groups(params[:groups])\n          )\n        end\n\n        private\n\n        attr_reader :schema\n\n        def build_groups(groups_params)\n          return [] unless groups_params\n\n          groups_params.map do |group_params|\n            ReportData::Group.new(\n              build_sections(:header, group_params[:headers] || {}),\n              build_detail_sections(group_params[:details] || []),\n              build_sections(:footer, group_params[:footers] || {})\n            )\n          end\n        end\n\n        def build_sections(section_type, sections_params)\n          sections_schemas =\n            case section_type\n            when :header then schema.headers\n            when :footer then schema.footers\n            end\n\n          sections_schemas.each_with_object([]) do |(section_id, section_schema), sections|\n            section_params = sections_params[section_id.to_sym] || {}\n            next unless section_enabled?(section_schema, section_params)\n\n            items = build_items(section_schema, section_params[:items] || {})\n            sections << ReportData::Section.new(section_schema, items, section_params[:min_height])\n          end\n        end\n\n        def build_detail_sections(details_params)\n          details_params.each_with_object([]) do |detail_params, details|\n            detail_id = detail_params[:id].to_sym\n            detail_schema = schema.details[detail_id]\n\n            next unless detail_schema\n\n            items = build_items(detail_schema, detail_params[:items] || {})\n            details << ReportData::Section.new(detail_schema, items, detail_params[:min_height])\n          end\n        end\n\n        def build_items(section_schema, items_params)\n          section_schema.items.each_with_object([]) do |item_schema, items|\n            item = ItemBuilder.new(item_schema, section_schema).build(items_params[item_schema.id&.to_sym])\n            items << item if item.visible?\n          end\n        end\n\n        def section_enabled?(section_schema, section_params)\n          if section_params.key?(:display)\n            section_params[:display]\n          else\n            section_schema.display?\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/builder/report_data.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module SectionReport\n    module Builder\n      module ReportData\n        Main = Struct.new :schema, :groups\n        Group = Struct.new :headers, :details, :footers\n        Section = Struct.new :schema, :items, :min_height\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/builder/stack_view_builder.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'stack_view_data'\n\nmodule Thinreports\n  module SectionReport\n    module Builder\n      class StackViewBuilder\n        def initialize(item)\n          @item = item\n        end\n\n        def update(params)\n          rows_params = params[:rows] || {}\n          rows_schema = item.internal.format.rows\n\n          rows = []\n          rows_schema.each do |row_schema|\n            row_params = rows_params[row_schema.id.to_sym] || {}\n            next unless row_enabled?(row_schema, row_params)\n\n            items = build_row_items(\n              row_schema,\n              row_params[:items] || {}\n            )\n\n            rows << StackViewData::Row.new(row_schema, items, row_params[:min_height])\n          end\n          item.internal.rows = rows\n        end\n\n        private\n\n        attr_reader :item\n\n        def build_row_items(row_schema, items_params)\n          row_schema.items.each_with_object([]) do |item_schema, items|\n            item = ItemBuilder.new(item_schema, row_schema).build(items_params[item_schema.id&.to_sym])\n            items << item if item.visible?\n          end\n        end\n\n        def row_enabled?(row_schema, row_params)\n          if row_params.key?(:display)\n            row_params[:display]\n          else\n            row_schema.display?\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/builder/stack_view_data.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module SectionReport\n    module Builder\n      module StackViewData\n        Row = Struct.new :schema, :items, :min_height\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/generate.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'build'\nrequire_relative 'pdf/render'\n\nmodule Thinreports\n  module SectionReport\n    class Generate\n      def initialize\n        @pdf = Thinreports::Generator::PDF::Document.new\n      end\n\n      def call(report_params, filename: nil)\n        report = Build.new.call(report_params)\n\n        PDF::Render.new(pdf).call!(report)\n\n        filename ? pdf.render_file(filename) : pdf.render\n      end\n\n      private\n\n      attr_reader :pdf\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/render.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'renderer/group_renderer'\n\nmodule Thinreports\n  module SectionReport\n    module PDF\n      class Render\n        def initialize(pdf)\n          @group_renderer = Renderer::GroupRenderer.new(pdf)\n        end\n\n        def call!(report)\n          report.groups.each { |group| group_renderer.render(report, group) }\n        end\n\n        private\n\n        attr_reader :group_renderer\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/renderer/draw_item.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module SectionReport\n    module Renderer\n      module DrawItem\n        def draw_item(item, expanded_height = 0)\n          shape = item.internal\n\n          if shape.type_of?(Core::Shape::TextBlock::TYPE_NAME)\n            computed_height = shape.format.attributes['height']\n            computed_height += expanded_height if shape.format.follow_stretch == 'height'\n\n            if shape.style.finalized_styles['overflow'] == 'expand'\n              # When overflow is \"expand\", the value of the height argument is ignored and the shape is expanded to\n              # the bottom of the outer bounding box.\n              # That causes a position shift problem if vertical-align is \"middle\" or \"bottom\".\n              # To solve it, we overwrite the overflow to \"truncate\" when drawing.\n              # To emulate the \"expand\" behavior in the \"truncate\" mode,\n              # here we pass the greater value of the computed_height and the text height as text block height.\n              pdf.draw_shape_tblock(shape, height: [computed_height, calc_text_block_height(shape)].max, overflow: :truncate)\n            else\n              pdf.draw_shape_tblock(shape, height: computed_height)\n            end\n          elsif shape.type_of?(Core::Shape::ImageBlock::TYPE_NAME)\n            pdf.draw_shape_iblock(shape)\n          elsif shape.type_of?('text')\n            case shape.format.follow_stretch\n            when 'height'\n              pdf.draw_shape_text(shape, expanded_height)\n            else\n              pdf.draw_shape_text(shape)\n            end\n          elsif shape.type_of?('image')\n            pdf.draw_shape_image(shape)\n          elsif shape.type_of?('ellipse')\n            pdf.draw_shape_ellipse(shape)\n          elsif shape.type_of?('rect')\n            case shape.format.follow_stretch\n            when 'height'\n              pdf.draw_shape_rect(shape, expanded_height)\n            else\n              pdf.draw_shape_rect(shape)\n            end\n          elsif shape.type_of?('line')\n            case shape.format.follow_stretch\n            when 'height'\n              y1, y2 = shape.format.attributes.values_at('y1', 'y2')\n              if y1 < y2\n                pdf.draw_shape_line(shape, 0, expanded_height)\n              else\n                pdf.draw_shape_line(shape, expanded_height, 0)\n              end\n            when 'y'\n              pdf.draw_shape_line(shape, expanded_height, expanded_height)\n            else\n              pdf.draw_shape_line(shape)\n            end\n          elsif shape.type_of?(Core::Shape::StackView::TYPE_NAME)\n            stack_view_renderer.render(shape)\n          else\n            raise Thinreports::Errors::UnknownShapeType\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/renderer/group_renderer.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'section_renderer'\n\nmodule Thinreports\n  module SectionReport\n    module Renderer\n      class GroupRenderer\n        def initialize(pdf)\n          @pdf = pdf\n          @section_renderer = Renderer::SectionRenderer.new(pdf)\n        end\n\n        def render(report, group)\n          pdf.start_new_page_for_section_report report.schema\n          current_page_height = 0\n\n          max_page_height = pdf.max_content_height\n\n          group.headers.each do |header|\n            section_renderer.render(header)\n            current_page_height += section_renderer.section_height(header)\n          end\n\n          group.details.each do |detail|\n            if current_page_height + section_renderer.section_height(detail) > max_page_height\n              pdf.start_new_page_for_section_report report.schema\n              current_page_height = 0\n\n              group.headers.each do |header|\n                if header.schema.every_page?\n                  section_renderer.render(header)\n                  current_page_height += section_renderer.section_height(header)\n                end\n              end\n            end\n            section_renderer.render(detail)\n            current_page_height += section_renderer.section_height(detail)\n          end\n\n          group.footers.each do |footer|\n            if current_page_height + section_renderer.section_height(footer) > max_page_height\n              pdf.start_new_page_for_section_report report.schema\n              current_page_height = 0\n            end\n            section_renderer.render(footer)\n            current_page_height += section_renderer.section_height(footer)\n          end\n        end\n\n        private\n\n        attr_reader :pdf, :section_renderer\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/renderer/section_height.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module SectionReport\n    module Renderer\n      module SectionHeight\n        LayoutInfo = Struct.new(:shape, :content_height, :top_margin, :bottom_margin)\n\n        def section_height(section)\n          return [section.min_height || 0, section.schema.height].max if !section.schema.auto_stretch? || section.items.empty?\n\n          item_layouts = section.items.map { |item| item_layout(section, item.internal) }.compact\n\n          min_bottom_margin = item_layouts.each_with_object([]) do |l, margins|\n            margins << l.bottom_margin if l.shape.format.affect_bottom_margin?\n          end.min.to_f\n\n          max_content_bottom = item_layouts.each_with_object([]) do |l, bottoms|\n            bottoms << l.top_margin + l.content_height if l.shape.format.affect_bottom_margin?\n          end.max.to_f\n\n          [section.min_height || 0, max_content_bottom + min_bottom_margin].max\n        end\n\n        def calc_float_content_bottom(section)\n          item_layouts = section.items.map { |item| item_layout(section, item.internal) }.compact\n          item_layouts\n            .map { |l| l.top_margin + l.content_height }\n            .max.to_f\n        end\n\n        def item_layout(section, shape)\n          if shape.type_of?(Core::Shape::TextBlock::TYPE_NAME)\n            text_layout(section, shape)\n          elsif shape.type_of?(Core::Shape::StackView::TYPE_NAME)\n            stack_view_layout(section, shape)\n          elsif shape.type_of?(Core::Shape::ImageBlock::TYPE_NAME)\n            image_block_layout(section, shape)\n          elsif shape.type_of?('ellipse')\n            cy, ry = shape.format.attributes.values_at('cy', 'ry')\n            static_layout(section, shape, cy - ry, ry * 2)\n          elsif shape.type_of?('line')\n            y1, y2 = shape.format.attributes.values_at('y1', 'y2')\n            static_layout(section, shape, [y1, y2].min, (y2 - y1).abs)\n          else\n            y, height = shape.format.attributes.values_at('y', 'height')\n            raise ArgumentError.new(\"Unknown layout for #{shape}\") if height == nil || y == nil\n            static_layout(section, shape, y, height)\n          end\n        end\n\n        def static_layout(section, shape, y, height)\n          LayoutInfo.new(shape, height, y, section.schema.height - height - y)\n        end\n\n        def image_block_layout(section, shape)\n          y, height = shape.format.attributes.values_at('y', 'height')\n          if shape.style.finalized_styles['position-y'] == 'top'\n            dimensions = pdf.shape_iblock_dimenions(shape)\n            content_height = dimensions ? dimensions[1] : 0\n\n            LayoutInfo.new(shape, content_height, y, section.schema.height - height - y)\n          else\n            static_layout(section, shape, y, height)\n          end\n        end\n\n        def calc_text_block_height(shape)\n          height = 0\n\n          pdf.draw_shape_tblock(shape) do |array, options|\n            modified_options = options.merge(at: [0, 10_000], height: 10_000)\n            height = pdf.pdf.height_of_formatted(array, modified_options)\n          end\n          height\n        end\n\n        def text_layout(section, shape)\n          y, schema_height = shape.format.attributes.values_at('y', 'height')\n\n          content_height = if shape.style.finalized_styles['overflow'] == 'expand'\n            [schema_height, calc_text_block_height(shape)].max\n          else\n            schema_height\n          end\n\n          LayoutInfo.new(shape, content_height, y, section.schema.height - schema_height - y)\n        end\n\n        def stack_view_layout(section, shape)\n          schema_height = 0\n          shape.format.rows.each {|row| schema_height += row.attributes['height']}\n\n          y = shape.format.attributes['y']\n          LayoutInfo.new(shape, stack_view_renderer.section_height(shape), y, section.schema.height - schema_height - y)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/renderer/section_renderer.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'stack_view_renderer'\nrequire_relative 'section_height'\nrequire_relative 'draw_item'\n\nmodule Thinreports\n  module SectionReport\n    module Renderer\n      class SectionRenderer\n        include SectionHeight\n        include DrawItem\n\n        def initialize(pdf)\n          @pdf = pdf\n        end\n\n        def render(section)\n          doc = pdf.pdf\n\n          actual_height = section_height(section)\n          doc.bounding_box([0, doc.cursor], width: doc.bounds.width, height: actual_height) do\n            section.items.each do |item|\n              draw_item(item, (actual_height - section.schema.height))\n            end\n          end\n        end\n\n        private\n\n        attr_reader :pdf\n\n        def stack_view_renderer\n          @stack_view_renderer ||= Renderer::StackViewRenderer.new(pdf)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/renderer/stack_view_renderer.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'stack_view_row_renderer'\n\nmodule Thinreports\n  module SectionReport\n    module Renderer\n      class StackViewRenderer\n        def initialize(pdf)\n          @pdf = pdf\n          @row_renderer = Renderer::StackViewRowRenderer.new(pdf)\n        end\n\n        RowLayout = Struct.new(:row, :height, :top)\n\n        def section_height(shape)\n          row_layouts = build_row_layouts(shape.rows)\n\n          total_row_height = row_layouts.sum(0, &:height)\n          float_content_bottom = row_layouts\n            .map { |l| row_renderer.calc_float_content_bottom(l.row) + l.top }\n            .max.to_f\n\n          [total_row_height, float_content_bottom].max\n        end\n\n        def render(shape)\n          doc = pdf.pdf\n\n          x, y, w = shape.format.attributes.values_at('x', 'y', 'width')\n          doc.bounding_box([x, doc.bounds.height - y], width: w, height: section_height(shape)) do\n            shape.rows.each do |row|\n              row_renderer.render(row)\n            end\n          end\n        end\n\n        private\n\n        attr_reader :pdf, :row_renderer\n\n        def build_row_layouts(rows)\n          row_layouts = rows.map { |row| RowLayout.new(row, row_renderer.section_height(row)) }\n\n          row_layouts.inject(0) do |top, row_layout|\n            row_layout.top = top\n            top + row_layout.height\n          end\n\n          row_layouts\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/pdf/renderer/stack_view_row_renderer.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'section_height'\nrequire_relative 'draw_item'\n\nmodule Thinreports\n  module SectionReport\n    module Renderer\n      class StackViewRowRenderer\n        include SectionHeight\n        include DrawItem\n\n        def initialize(pdf)\n          @pdf = pdf\n        end\n\n        def render(row)\n          doc = pdf.pdf\n\n          actual_height = section_height(row)\n          doc.bounding_box([0, doc.cursor], width: doc.bounds.width, height: actual_height) do\n            row.items.each do |item|\n              draw_item(item, (actual_height - row.schema.height))\n            end\n          end\n        end\n\n        private\n\n        attr_reader :pdf\n\n        def stack_view_renderer\n          raise Thinreports::Errors::InvalidLayoutFormat, 'nested StackView does not supported'\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/schema/loader.rb",
    "content": "# frozen_string_literal: true\n\nrequire_relative 'parser'\n\nmodule Thinreports\n  module SectionReport\n    module Schema\n      class Loader\n        def initialize\n          @parser = Schema::Parser.new\n        end\n\n        def load_from_file(filename)\n          data = File.read(filename, encoding: 'UTF-8')\n          load_from_data(data)\n        end\n\n        def load_from_data(data)\n          parser.parse(data)\n        end\n\n        private\n\n        attr_reader :parser\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/schema/parser.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'json'\n\nrequire_relative 'report'\nrequire_relative 'section'\n\nmodule Thinreports\n  module SectionReport\n    module Schema\n      class Parser\n        def parse(schema_json_data)\n          schema_data = JSON.parse(schema_json_data)\n\n          section_schema_datas = schema_data['sections'].group_by { |section| section['type'] }\n\n          Schema::Report.new(\n            schema_data,\n            headers: parse_sections(:header, section_schema_datas['header']),\n            details: parse_sections(:detail, section_schema_datas['detail']),\n            footers: parse_sections(:footer, section_schema_datas['footer'])\n          )\n        end\n\n        private\n\n        attr_reader :schema_data\n\n        def parse_sections(section_type, section_schema_datas = nil)\n          return {} if section_schema_datas.nil?\n\n          section_schema_datas.each_with_object({}) do |section_schema_data, section_schemas|\n            id = section_schema_data['id']\n            section_schemas[id.to_sym] = parse_section(section_type, section_schema_data)\n          end\n        end\n\n        def parse_section(type, section_schema_data)\n          items = section_schema_data['items'].map do |item_schema_data|\n            item_type = item_schema_data['type']\n            Core::Shape::Format(item_type).new(item_schema_data)\n          end\n          section_schema_class_for(type).new(section_schema_data, items: items)\n        end\n\n        def section_schema_class_for(section_type)\n          Schema::Section.const_get(section_type.capitalize)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/schema/report.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module SectionReport\n    module Schema\n      class Report < Core::Shape::Manager::Format\n        config_reader last_version: %w( version )\n        config_reader report_title: %w( title )\n        config_reader page_paper_type: %w( report paper-type ),\n                      page_orientation: %w( report orientation ),\n                      page_margin: %w( report margin ),\n                      page_width: %w[report width],\n                      page_height: %w[report height]\n\n        attr_reader :headers, :details, :footers\n\n        def user_paper_type?\n          page_paper_type == 'user'\n        end\n\n        def initialize(schema_data, headers:, details:, footers:)\n          super(schema_data)\n          @headers = headers\n          @details = details\n          @footers = footers\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report/schema/section.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  module SectionReport\n    module Schema\n      module Section\n        class Base < Core::Shape::Manager::Format\n          config_reader :id, :type\n          config_reader :height\n          config_checker true, :display\n          config_checker true, auto_stretch: 'auto-stretch'\n\n          attr_reader :items\n\n          def initialize(schema_data, items:)\n            super(schema_data)\n            initialize_items(items)\n          end\n\n          def find_item(id)\n            @item_with_ids[id.to_sym]\n          end\n\n          private\n\n          def initialize_items(items)\n            @items = items\n            @item_with_ids = items.each_with_object({}) do |item, item_with_ids|\n              next if item.id.empty?\n              item_with_ids[item.id.to_sym] = item\n            end\n          end\n        end\n\n        class Header < Base\n          config_checker true, every_page: 'every-page'\n        end\n\n        class Footer < Base\n        end\n\n        class Detail < Base\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/thinreports/section_report.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  Core = BasicReport::Core\n  Generator = BasicReport::Generator\n\n  def self.generate(report_params, filename: nil)\n    SectionReport::Generate.new.call(report_params, filename: filename)\n  end\nend\n\nrequire_relative 'section_report/generate'\n"
  },
  {
    "path": "lib/thinreports/version.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports\n  VERSION = '0.14.2'\nend\n"
  },
  {
    "path": "lib/thinreports.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'pathname'\n\nmodule Thinreports\n  def self.root\n    @root ||= Pathname.new(__FILE__).join('..', '..')\n  end\nend\n\nrequire_relative 'thinreports/version'\nrequire_relative 'thinreports/config'\nrequire_relative 'thinreports/basic_report'\nrequire_relative 'thinreports/section_report'\n"
  },
  {
    "path": "test/basic_report/data/legacy_layout/all-items.tlf",
    "content": "{\"version\":\"0.8.2\",\"config\":{\"title\":\"Report Title\",\"option\":{},\"page\":{\"paper-type\":\"A4\",\"orientation\":\"portrait\",\"margin-top\":\"20\",\"margin-bottom\":\"30\",\"margin-left\":\"40\",\"margin-right\":\"50\"}},\"svg\":\"<svg width=\\\"595.2\\\" height=\\\"841.8\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" preserveAspectRatio=\\\"none\\\" viewBox=\\\"0 0 595.2 841.8\\\"><g class=\\\"canvas\\\"><rect stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"1\\\" class=\\\"s-rect\\\" x-display=\\\"true\\\" x-stroke-type=\\\"solid\\\" stroke-dasharray=\\\"none\\\" x-id=\\\"\\\" rx=\\\"0\\\" ry=\\\"0\\\" id=\\\"goog_852326033\\\" width=\\\"102.6\\\" height=\\\"42\\\" x=\\\"40\\\" y=\\\"20\\\"/><ellipse stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"1\\\" class=\\\"s-ellipse\\\" x-display=\\\"true\\\" x-stroke-type=\\\"solid\\\" stroke-dasharray=\\\"none\\\" x-id=\\\"\\\" id=\\\"goog_852326034\\\" rx=\\\"37.5\\\" ry=\\\"22.5\\\" cx=\\\"209.1\\\" cy=\\\"42.5\\\"/><line stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" class=\\\"s-line\\\" x-display=\\\"true\\\" x-stroke-type=\\\"solid\\\" stroke-dasharray=\\\"none\\\" x-id=\\\"\\\" id=\\\"goog_852326035\\\" x1=\\\"287.6\\\" x2=\\\"349.6\\\" y1=\\\"20\\\" y2=\\\"61\\\"/><g class=\\\"s-text\\\" stroke-width=\\\"0\\\" fill=\\\"#000000\\\" fill-opacity=\\\"1\\\" kerning=\\\"auto\\\" letter-spacing=\\\"normal\\\" x-display=\\\"true\\\" x-id=\\\"\\\" id=\\\"goog_852326036\\\" font-size=\\\"18\\\" font-family=\\\"Courier New\\\" font-weight=\\\"normal\\\" font-style=\\\"normal\\\" text-anchor=\\\"start\\\" text-decoration=\\\"none\\\" x-width=\\\"114.6\\\" x-height=\\\"31\\\" x-left=\\\"40\\\" x-top=\\\"92\\\"><rect class=\\\"s-text-box\\\" stroke=\\\"none\\\" fill=\\\"#000000\\\" fill-opacity=\\\"0.001\\\" width=\\\"114.6\\\" height=\\\"31\\\" x=\\\"40\\\" y=\\\"92\\\"/><text class=\\\"s-text-l0\\\" xml:space=\\\"preserve\\\" stroke=\\\"none\\\" fill=\\\"inherit\\\" fill-opacity=\\\"1\\\" text-decoration=\\\"none\\\" x=\\\"40\\\" y=\\\"107\\\">text</text></g><image image-rendering=\\\"optimizeQuality\\\" preserveAspectRatio=\\\"none\\\" class=\\\"s-image\\\" x-display=\\\"true\\\" x-id=\\\"\\\" id=\\\"goog_852326037\\\" x=\\\"166.6\\\" y=\\\"90\\\" x-natural-width=\\\"1966\\\" x-natural-height=\\\"375\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xlink:href=\\\"data:image/png;base64,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\\\" width=\\\"259\\\" height=\\\"49.2\\\"/><!--SHAPE{\\\"type\\\":\\\"s-tblock\\\",\\\"id\\\":\\\"text\\\",\\\"display\\\":\\\"true\\\",\\\"desc\\\":null,\\\"multiple\\\":\\\"false\\\",\\\"valign\\\":\\\"\\\",\\\"line-height\\\":\\\"\\\",\\\"line-height-ratio\\\":\\\"\\\",\\\"box\\\":{\\\"x\\\":40,\\\"y\\\":160,\\\"width\\\":107.6,\\\"height\\\":20.5},\\\"format\\\":{\\\"base\\\":\\\"\\\",\\\"type\\\":\\\"\\\"},\\\"value\\\":\\\"\\\",\\\"ref-id\\\":\\\"\\\",\\\"overflow\\\":\\\"\\\",\\\"word-wrap\\\":\\\"break-word\\\",\\\"svg\\\":{\\\"tag\\\":\\\"text\\\",\\\"attrs\\\":{\\\"x\\\":40,\\\"y\\\":175,\\\"xml:space\\\":\\\"preserve\\\",\\\"kerning\\\":\\\"auto\\\",\\\"letter-spacing\\\":\\\"normal\\\",\\\"id\\\":\\\"goog_852326038\\\",\\\"fill\\\":\\\"#000000\\\",\\\"fill-opacity\\\":\\\"1\\\",\\\"font-size\\\":\\\"18\\\",\\\"font-family\\\":\\\"Courier New\\\",\\\"font-weight\\\":\\\"normal\\\",\\\"font-style\\\":\\\"normal\\\",\\\"text-anchor\\\":\\\"start\\\",\\\"text-decoration\\\":\\\"none\\\"}}}SHAPE--><!--LAYOUT<g xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"s-tblock\\\" x-format-type=\\\"\\\" x-value=\\\"\\\" x-format-base=\\\"\\\" x-ref-id=\\\"\\\" kerning=\\\"auto\\\" letter-spacing=\\\"normal\\\" x-display=\\\"true\\\" x-multiple=\\\"false\\\" id=\\\"goog_852326038\\\" x-id=\\\"text\\\" fill=\\\"#000000\\\" fill-opacity=\\\"1\\\" font-size=\\\"18\\\" font-family=\\\"Courier New\\\" font-weight=\\\"normal\\\" font-style=\\\"normal\\\" text-anchor=\\\"start\\\" text-decoration=\\\"none\\\" x-width=\\\"107.6\\\" x-height=\\\"20.5\\\" x-left=\\\"40\\\" x-top=\\\"160\\\"><rect class=\\\"s-tblock-box\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"0.2\\\" width=\\\"107.6\\\" height=\\\"20.5\\\" x=\\\"40\\\" y=\\\"160\\\"/><text class=\\\"s-tblock-id\\\" font-size=\\\"10.5\\\" font-family=\\\"Helvetica\\\" font-weight=\\\"normal\\\" font-style=\\\"normal\\\" text-decoration=\\\"none\\\" text-anchor=\\\"start\\\" kerning=\\\"auto\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"1\\\" x=\\\"44\\\" y=\\\"171\\\">text</text></g>LAYOUT--><!--SHAPE{\\\"type\\\":\\\"s-iblock\\\",\\\"id\\\":\\\"image\\\",\\\"display\\\":\\\"true\\\",\\\"desc\\\":null,\\\"box\\\":{\\\"x\\\":171.6,\\\"y\\\":161,\\\"width\\\":177,\\\"height\\\":73},\\\"position-x\\\":\\\"left\\\",\\\"position-y\\\":\\\"top\\\",\\\"svg\\\":{\\\"tag\\\":\\\"image\\\",\\\"attrs\\\":{\\\"x\\\":171.6,\\\"y\\\":161,\\\"width\\\":177,\\\"height\\\":73}}}SHAPE--><!--LAYOUT<g xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"s-iblock\\\" x-display=\\\"true\\\" id=\\\"goog_852326039\\\" x-id=\\\"image\\\" x-width=\\\"177\\\" x-height=\\\"73\\\" x-left=\\\"171.6\\\" x-top=\\\"161\\\"><rect class=\\\"s-iblock-box\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"0.2\\\" width=\\\"177\\\" height=\\\"73\\\" x=\\\"171.6\\\" y=\\\"161\\\"/><image width=\\\"16\\\" height=\\\"16\\\" class=\\\"s-iblock-mark\\\" opacity=\\\"0.5\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xlink:href=\\\"assets/icons/x-image-mark.svg\\\" display=\\\"inline\\\" x=\\\"251.60000000000002\\\" y=\\\"189\\\"/><text class=\\\"s-iblock-id\\\" font-size=\\\"10.5\\\" font-family=\\\"Helvetica\\\" font-weight=\\\"normal\\\" font-style=\\\"normal\\\" text-decoration=\\\"none\\\" text-anchor=\\\"start\\\" kerning=\\\"auto\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"1\\\" x=\\\"175.6\\\" y=\\\"172\\\">image</text></g>LAYOUT--><!--SHAPE{\\\"type\\\":\\\"s-pageno\\\",\\\"id\\\":\\\"\\\",\\\"display\\\":\\\"true\\\",\\\"desc\\\":null,\\\"box\\\":{\\\"x\\\":375.6,\\\"y\\\":160,\\\"width\\\":128,\\\"height\\\":20.5},\\\"target\\\":\\\"\\\",\\\"format\\\":\\\"{page}\\\",\\\"overflow\\\":\\\"\\\",\\\"svg\\\":{\\\"tag\\\":\\\"text\\\",\\\"attrs\\\":{\\\"x\\\":439.6,\\\"y\\\":175,\\\"kerning\\\":\\\"auto\\\",\\\"letter-spacing\\\":\\\"normal\\\",\\\"id\\\":\\\"goog_852326040\\\",\\\"fill\\\":\\\"#000000\\\",\\\"fill-opacity\\\":\\\"1\\\",\\\"font-size\\\":\\\"18\\\",\\\"font-family\\\":\\\"Courier New\\\",\\\"font-weight\\\":\\\"normal\\\",\\\"font-style\\\":\\\"normal\\\",\\\"text-anchor\\\":\\\"middle\\\",\\\"text-decoration\\\":\\\"none\\\"}}}SHAPE--><!--LAYOUT<g xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"s-pageno\\\" kerning=\\\"auto\\\" letter-spacing=\\\"normal\\\" x-display=\\\"true\\\" x-format=\\\"{page}\\\" id=\\\"goog_852326040\\\" fill=\\\"#000000\\\" fill-opacity=\\\"1\\\" font-size=\\\"18\\\" font-family=\\\"Courier New\\\" font-weight=\\\"normal\\\" font-style=\\\"normal\\\" text-anchor=\\\"middle\\\" text-decoration=\\\"none\\\" x-width=\\\"128\\\" x-height=\\\"20.5\\\" x-left=\\\"375.6\\\" x-top=\\\"160\\\" x-id=\\\"\\\"><rect class=\\\"s-pageno-box\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"0.2\\\" width=\\\"128\\\" height=\\\"20.5\\\" x=\\\"375.6\\\" y=\\\"160\\\"/><text kerning=\\\"auto\\\" font-size=\\\"10\\\" font-family=\\\"Helvetica\\\" text-anchor=\\\"middle\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"1\\\" y=\\\"171\\\" x=\\\"439.6\\\">{page}</text></g>LAYOUT--><!--SHAPE{\\\"type\\\":\\\"s-list\\\",\\\"id\\\":\\\"default\\\",\\\"display\\\":\\\"true\\\",\\\"desc\\\":null,\\\"footer\\\":{\\\"height\\\":28.2,\\\"svg\\\":{\\\"tag\\\":\\\"g\\\",\\\"content\\\":\\\"\\\"},\\\"translate\\\":{\\\"x\\\":0,\\\"y\\\":-65.79999999999995}},\\\"footer-enabled\\\":\\\"true\\\",\\\"page-footer\\\":{\\\"height\\\":28.2,\\\"svg\\\":{\\\"tag\\\":\\\"g\\\",\\\"content\\\":\\\"\\\"},\\\"translate\\\":{\\\"x\\\":0,\\\"y\\\":-37.599999999999966}},\\\"page-footer-enabled\\\":\\\"true\\\",\\\"detail\\\":{\\\"height\\\":37.6,\\\"svg\\\":{\\\"tag\\\":\\\"g\\\",\\\"content\\\":\\\"\\\"},\\\"translate\\\":{\\\"x\\\":0,\\\"y\\\":0}},\\\"header\\\":{\\\"height\\\":37.6,\\\"svg\\\":{\\\"tag\\\":\\\"g\\\",\\\"content\\\":\\\"<rect xmlns=\\\\\\\"http://www.w3.org/2000/svg\\\\\\\" stroke=\\\\\\\"#000000\\\\\\\" stroke-width=\\\\\\\"1\\\\\\\" fill=\\\\\\\"#FFFFFF\\\\\\\" fill-opacity=\\\\\\\"1\\\\\\\" class=\\\\\\\"s-rect\\\\\\\" x-display=\\\\\\\"true\\\\\\\" x-stroke-type=\\\\\\\"solid\\\\\\\" stroke-dasharray=\\\\\\\"none\\\\\\\" x-id=\\\\\\\"\\\\\\\" rx=\\\\\\\"0\\\\\\\" ry=\\\\\\\"0\\\\\\\" id=\\\\\\\"goog_852326042\\\\\\\" width=\\\\\\\"85.6\\\\\\\" height=\\\\\\\"18\\\\\\\" x=\\\\\\\"40\\\\\\\" y=\\\\\\\"265\\\\\\\"/>\\\"},\\\"translate\\\":{\\\"x\\\":0,\\\"y\\\":0}},\\\"header-enabled\\\":\\\"true\\\",\\\"svg\\\":{\\\"tag\\\":\\\"g\\\",\\\"attrs\\\":{}},\\\"content-height\\\":150.4,\\\"page-break\\\":\\\"true\\\"}SHAPE--><!--LAYOUT<g xmlns=\\\"http://www.w3.org/2000/svg\\\" class=\\\"s-list\\\" x-id=\\\"default\\\" x-header-enabled=\\\"true\\\" x-page-footer-enabled=\\\"true\\\" x-footer-enabled=\\\"true\\\" x-changing-page=\\\"true\\\" x-display=\\\"true\\\" id=\\\"goog_852326041\\\" width=\\\"365.6\\\" height=\\\"188\\\" x=\\\"40\\\" y=\\\"256\\\"><g class=\\\"s-list-header\\\" transform=\\\"translate(0,0) rotate(0 0 0)\\\" x-top=\\\"256\\\" x-height=\\\"37.6\\\"><rect stroke=\\\"#000000\\\" stroke-width=\\\"1\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"1\\\" class=\\\"s-rect\\\" x-display=\\\"true\\\" x-stroke-type=\\\"solid\\\" stroke-dasharray=\\\"none\\\" x-id=\\\"\\\" rx=\\\"0\\\" ry=\\\"0\\\" id=\\\"goog_852326042\\\" width=\\\"85.6\\\" height=\\\"18\\\" x=\\\"40\\\" y=\\\"265\\\"/></g><g class=\\\"s-list-detail\\\" transform=\\\"translate(0,0) rotate(0 0 0)\\\" x-top=\\\"293.6\\\" x-height=\\\"37.6\\\"/><g class=\\\"s-list-page-footer\\\" transform=\\\"translate(0,0) rotate(0 0 0)\\\" x-top=\\\"331.2\\\" x-height=\\\"28.2\\\"/><g class=\\\"s-list-footer\\\" transform=\\\"translate(0,0) rotate(0 0 0)\\\" x-top=\\\"359.4\\\" x-height=\\\"28.2\\\"/><text class=\\\"s-list-id\\\" font-size=\\\"10\\\" font-family=\\\"Helvetica\\\" font-weight=\\\"normal\\\" font-style=\\\"normal\\\" text-anchor=\\\"start\\\" stroke=\\\"none\\\" fill=\\\"#0096fd\\\" fill-opacity=\\\"1\\\" x=\\\"44\\\" y=\\\"268\\\">default</text><rect stroke-dasharray=\\\"2\\\" stroke=\\\"#0096fd\\\" stroke-width=\\\"0.5\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"0\\\" class=\\\"s-list-face\\\" width=\\\"365.6\\\" height=\\\"188\\\" x=\\\"40\\\" y=\\\"256\\\"/></g>LAYOUT--></g></svg>\",\"state\":{\"layout-guide\":[]}}"
  },
  {
    "path": "test/basic_report/features/dynamic_style/templates/styles.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 42,\n      \"width\": 374.1,\n      \"height\": 23,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 20,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"The Basic Style\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 72,\n      \"width\": 280,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Visibility: To true from false.\"\n      ]\n    },\n    {\n      \"id\": \"basic_show1\",\n      \"type\": \"rect\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 90,\n      \"width\": 52,\n      \"height\": 34,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"basic_show2\",\n      \"type\": \"ellipse\",\n      \"display\": false,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 118.45,\n      \"cy\": 108.5,\n      \"rx\": 31.55,\n      \"ry\": 21.5\n    },\n    {\n      \"id\": \"basic_show3\",\n      \"type\": \"text\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 165.1,\n      \"y\": 97,\n      \"width\": 36,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Text\"\n      ]\n    },\n    {\n      \"id\": \"basic_show4\",\n      \"type\": \"image\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 213.1,\n      \"y\": 91,\n      \"width\": 41,\n      \"height\": 41,\n      \"data\": {\n        \"mime-type\": \"image/png\",\n        \"base64\": \"iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOdAAADnQBaySz1gAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOS8xNS8xMe/neuYAAAAfdEVYdFNvZnR3YXJlAE1hY3JvbWVkaWEgRmlyZXdvcmtzIDi1aNJ4AAAAV0lEQVRoge3PAQ3AMAzAsH78OfckLi26bATJM7M7P3BuB3zFSI2RGiM1RmqM1BipMVJjpMZIjZEaIzVGaozUGKkxUmOkxkiNkRojNUZqjNQYqTFSY6TmBQWzAmLkoN8LAAAAAElFTkSuQmCC\"\n      }\n    },\n    {\n      \"id\": \"basic_show5\",\n      \"type\": \"text-block\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 267.1,\n      \"y\": 97,\n      \"width\": 106,\n      \"height\": 20,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 147,\n      \"width\": 280,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Visibility: To false from true.\"\n      ]\n    },\n    {\n      \"id\": \"basic_hide1\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 165,\n      \"width\": 52,\n      \"height\": 34,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"basic_hide2\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 118.45,\n      \"cy\": 183.5,\n      \"rx\": 31.55,\n      \"ry\": 21.5\n    },\n    {\n      \"id\": \"basic_hide3\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 165.1,\n      \"y\": 172,\n      \"width\": 36,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Text\"\n      ]\n    },\n    {\n      \"id\": \"basic_hide4\",\n      \"type\": \"image\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 213.1,\n      \"y\": 166,\n      \"width\": 41,\n      \"height\": 41,\n      \"data\": {\n        \"mime-type\": \"image/png\",\n        \"base64\": \"iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOdAAADnQBaySz1gAAABZ0RVh0Q3JlYXRpb24gVGltZQAwOS8xNS8xMe/neuYAAAAfdEVYdFNvZnR3YXJlAE1hY3JvbWVkaWEgRmlyZXdvcmtzIDi1aNJ4AAAAV0lEQVRoge3PAQ3AMAzAsH78OfckLi26bATJM7M7P3BuB3zFSI2RGiM1RmqM1BipMVJjpMZIjZEaIzVGaozUGKkxUmOkxkiNkRojNUZqjNQYqTFSY6TmBQWzAmLkoN8LAAAAAElFTkSuQmCC\"\n      }\n    },\n    {\n      \"id\": \"basic_hide5\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 267.1,\n      \"y\": 172,\n      \"width\": 106,\n      \"height\": 20,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 222,\n      \"width\": 374.1,\n      \"height\": 23,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 20,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"The Graphic Style\"\n      ]\n    },\n    {\n      \"id\": \"graphic_bcolor1\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 269,\n      \"width\": 89,\n      \"height\": 44,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 252,\n      \"width\": 245,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Border Color: To red from black.\"\n      ]\n    },\n    {\n      \"id\": \"graphic_bcolor2\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 167.05,\n      \"cy\": 291,\n      \"rx\": 38.05,\n      \"ry\": 23\n    },\n    {\n      \"id\": \"graphic_bcolor3\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 227.1,\n      \"y1\": 276,\n      \"x2\": 286.1,\n      \"y2\": 302\n    },\n    {\n      \"id\": \"graphic_bcolor4\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 311.1,\n      \"y\": 268,\n      \"width\": 89,\n      \"height\": 44,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#e5b9b7\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 311,\n      \"y\": 316.9,\n      \"width\": 182.1,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To none from red.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 332,\n      \"width\": 245,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Border Width: To 5 from 1.\"\n      ]\n    },\n    {\n      \"id\": \"graphic_bwidth1\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 350,\n      \"width\": 89,\n      \"height\": 44,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"graphic_bwidth2\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 167.05,\n      \"cy\": 370.9,\n      \"rx\": 38.05,\n      \"ry\": 23\n    },\n    {\n      \"id\": \"graphic_bwidth3\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 227.1,\n      \"y1\": 355.9,\n      \"x2\": 286.1,\n      \"y2\": 381.9\n    },\n    {\n      \"id\": \"graphic_bwidth4\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 311.1,\n      \"y\": 343,\n      \"width\": 89,\n      \"height\": 44,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 0,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#e5b9b7\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 311,\n      \"y\": 391.9,\n      \"width\": 182.1,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To 2 from none(0).\"\n      ]\n    },\n    {\n      \"id\": \"graphic_bwidth5\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 448.1,\n      \"y\": 343,\n      \"width\": 89,\n      \"height\": 44,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#e5b9b7\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 448,\n      \"y\": 391.9,\n      \"width\": 129.6,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To none(0) from 1.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 412,\n      \"width\": 245,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Fill Color: To red from white.\"\n      ]\n    },\n    {\n      \"id\": \"graphic_fcolor1\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 428.8,\n      \"width\": 89,\n      \"height\": 44,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"graphic_fcolor2\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 167.05,\n      \"cy\": 450.8,\n      \"rx\": 38.05,\n      \"ry\": 23\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 226,\n      \"y\": 476.7,\n      \"width\": 182.1,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To none from black.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 302.5,\n      \"cy\": 434.5,\n      \"rx\": 37.5,\n      \"ry\": 15.5\n    },\n    {\n      \"id\": \"graphic_fcolor3\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 226,\n      \"y\": 427.8,\n      \"width\": 73,\n      \"height\": 35.2,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#000000\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 371,\n      \"y\": 476.7,\n      \"width\": 182.1,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To red from none.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 447.5,\n      \"cy\": 434.5,\n      \"rx\": 37.5,\n      \"ry\": 15.5\n    },\n    {\n      \"id\": \"graphic_fcolor4\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 371,\n      \"y\": 427.8,\n      \"width\": 73,\n      \"height\": 35.2,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 497,\n      \"width\": 374.1,\n      \"height\": 23,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 20,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"The Text Style\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 527,\n      \"width\": 122,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Bold Style:\"\n      ]\n    },\n    {\n      \"id\": \"text_b1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 549.2,\n      \"width\": 131,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To bold from normal.\"\n      ]\n    },\n    {\n      \"id\": \"text_b2\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 567,\n      \"width\": 144,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"bold\"\n        ]\n      },\n      \"texts\": [\n        \"To normal from bold.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 150,\n      \"y\": 527,\n      \"width\": 122,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Italic Style:\"\n      ]\n    },\n    {\n      \"id\": \"text_i1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 150,\n      \"y\": 549.2,\n      \"width\": 132,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To italic from normal.\"\n      ]\n    },\n    {\n      \"id\": \"text_i2\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 150,\n      \"y\": 567,\n      \"width\": 146,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"italic\"\n        ]\n      },\n      \"texts\": [\n        \"To normal from italic.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 280,\n      \"y\": 527,\n      \"width\": 122,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Underline Style:\"\n      ]\n    },\n    {\n      \"id\": \"text_u1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 280,\n      \"y\": 549.2,\n      \"width\": 132,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To underline from none.\"\n      ]\n    },\n    {\n      \"id\": \"text_u2\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 280,\n      \"y\": 567,\n      \"width\": 146,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"To none from underline.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 527,\n      \"width\": 136.8,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Line-Through Style:\"\n      ]\n    },\n    {\n      \"id\": \"text_l1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 549.2,\n      \"width\": 145,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To line-through from none.\"\n      ]\n    },\n    {\n      \"id\": \"text_l2\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 567,\n      \"width\": 146,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"linethrough\"\n        ]\n      },\n      \"texts\": [\n        \"To none from line-through.\"\n      ]\n    },\n    {\n      \"id\": \"text_b3\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 586.2,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_b4\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 606,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"bold\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_i3\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 150,\n      \"y\": 586.2,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_i4\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 150,\n      \"y\": 606,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"italic\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_u3\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 280,\n      \"y\": 586.2,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_u4\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 280,\n      \"y\": 606,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_l3\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 586.2,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_l4\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 606,\n      \"width\": 119,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"linethrough\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 637,\n      \"width\": 223.1,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Text Align: To right from left.\"\n      ]\n    },\n    {\n      \"id\": \"text_a1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 659,\n      \"width\": 155.1,\n      \"height\": 23.2,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To right from left.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 659,\n      \"width\": 155.1,\n      \"height\": 23.2,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"text_a2\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 192.1,\n      \"y\": 660.2,\n      \"width\": 138,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text_a3\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"日本語\",\n      \"x\": 344.1,\n      \"y\": 660.2,\n      \"width\": 153.1,\n      \"height\": 44.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 192.1,\n      \"y\": 660.2,\n      \"width\": 138,\n      \"height\": 22,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 344.1,\n      \"y\": 660.2,\n      \"width\": 153.1,\n      \"height\": 44.1,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 712,\n      \"width\": 251.9,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Vertical Align: To bottom from top.\"\n      ]\n    },\n    {\n      \"id\": \"text_va1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 729,\n      \"width\": 155.1,\n      \"height\": 50.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To bottom from top.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 729,\n      \"width\": 155.1,\n      \"height\": 50.3,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"text_va2\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"日本語\",\n      \"x\": 189,\n      \"y\": 730,\n      \"width\": 153.1,\n      \"height\": 50.3,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 189,\n      \"y\": 730,\n      \"width\": 153.1,\n      \"height\": 50.3,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 789,\n      \"width\": 245,\n      \"height\": 14,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Text Color: To red from black.\"\n      ]\n    },\n    {\n      \"id\": \"text_color1\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 809,\n      \"width\": 131,\n      \"height\": 15,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"To red from black.\"\n      ]\n    },\n    {\n      \"id\": \"text_color2\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"日本語\",\n      \"x\": 136,\n      \"y\": 808.1,\n      \"width\": 119,\n      \"height\": 12,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 12,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"title\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 183.1,\n      \"y\": 22,\n      \"width\": 208,\n      \"height\": 19,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"bold\",\n          \"underline\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"basic_show6\",\n      \"type\": \"image-block\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 387,\n      \"y\": 87,\n      \"width\": 74,\n      \"height\": 58,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"top\"\n      }\n    },\n    {\n      \"id\": \"basic_hide6\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 387,\n      \"y\": 162,\n      \"width\": 74,\n      \"height\": 58,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"top\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"Dynamic Style\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/dynamic_style/templates/styles_in_list.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"list\",\n      \"type\": \"list\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 77,\n      \"width\": 555.2,\n      \"height\": 415.2,\n      \"header\": {\n        \"enabled\": true,\n        \"height\": 51,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": 57\n        },\n        \"items\": [\n          {\n            \"id\": \"rect\",\n            \"type\": \"rect\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 110.1,\n            \"y\": 31,\n            \"width\": 77,\n            \"height\": 31,\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\",\n              \"fill-color\": \"#FFFFFF\"\n            },\n            \"border-radius\": 0\n          },\n          {\n            \"id\": \"text\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 223.1,\n            \"y\": 21,\n            \"width\": 147,\n            \"height\": 45.1,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"left\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"Header Text\"\n            ]\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"rect\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 223.1,\n            \"y\": 21,\n            \"width\": 147,\n            \"height\": 45.1,\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\",\n              \"fill-color\": \"none\"\n            },\n            \"border-radius\": 0\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"rect\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 389.1,\n            \"y\": 23,\n            \"width\": 144.1,\n            \"height\": 42.1,\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\",\n              \"fill-color\": \"none\"\n            },\n            \"border-radius\": 0\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 71,\n            \"x2\": 575.2,\n            \"y2\": 71\n          },\n          {\n            \"id\": \"tblock\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 389.1,\n            \"y\": 23,\n            \"width\": 144.1,\n            \"height\": 42.1,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"left\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"Header Tblock\",\n            \"multiple-line\": true,\n            \"format\": {\n              \"base\": \"\",\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"detail\": {\n        \"height\": 57,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": 1.2\n        },\n        \"items\": [\n          {\n            \"id\": \"rect\",\n            \"type\": \"rect\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 111.1,\n            \"y\": 137.8,\n            \"width\": 77,\n            \"height\": 31,\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\",\n              \"fill-color\": \"#FFFFFF\"\n            },\n            \"border-radius\": 0\n          },\n          {\n            \"id\": \"text\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 223.1,\n            \"y\": 132.8,\n            \"width\": 147,\n            \"height\": 45.1,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"left\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"Detail Text\"\n            ]\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"rect\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 223.1,\n            \"y\": 132.8,\n            \"width\": 147,\n            \"height\": 45.1,\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\",\n              \"fill-color\": \"none\"\n            },\n            \"border-radius\": 0\n          },\n          {\n            \"id\": \"tblock\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 389.1,\n            \"y\": 134.8,\n            \"width\": 144.1,\n            \"height\": 42.1,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"left\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"Detail Tblock\",\n            \"multiple-line\": true,\n            \"format\": {\n              \"base\": \"\",\n              \"type\": \"\"\n            }\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"rect\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 389.1,\n            \"y\": 134.8,\n            \"width\": 144.1,\n            \"height\": 42.1,\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\",\n              \"fill-color\": \"none\"\n            },\n            \"border-radius\": 0\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 183.8,\n            \"x2\": 575.2,\n            \"y2\": 183.8\n          }\n        ]\n      },\n      \"page-footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -48.6\n        },\n        \"items\": []\n      },\n      \"footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -128.7\n        },\n        \"items\": []\n      },\n      \"content-height\": 364.2,\n      \"auto-page-break\": true\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 197.6,\n      \"y\": 36,\n      \"width\": 200,\n      \"height\": 20,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Dynamic Style in List\"\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"Dynamic Style in List\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/dynamic_style/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestDynamicStyleFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    image = path_of('image.png')\n    setup_values = Proc.new do |page|\n      # The Basic Style\n      page.values(basic_show5: 'TextBlock',\n                  basic_show6: image,\n                  basic_hide5: 'TextBlock',\n                  basic_hide6: image)\n      # The Text Style\n      page.values(text_b3: 'To bold',\n                  text_b4: 'To normal',\n                  text_i3: 'To italic',\n                  text_i4: 'To normal',\n                  text_u3: 'To underline',\n                  text_u4: 'To none',\n                  text_l3: 'To line-through',\n                  text_l4: 'To none')\n      page.values(text_a2: 'To right align',\n                  text_a3: \"To right align\\n右寄せ\",\n                  text_va2: \"To bottom align\\n下揃え\",\n                  text_color2: '赤色')\n    end\n\n    report = Thinreports::BasicReport::Report.new layout: template_path('templates/styles.tlf')\n\n    # Create raw-page.\n    report.start_new_page\n    report.page.item(:title).value('Original Page')\n\n    setup_values.call(report.page)\n\n    # Create styled-page.\n    report.start_new_page\n\n    setup_values.call(report.page)\n    report.page.item(:title).value('Styled Page')\n\n    # The Basic Style\n    6.times do |i|\n      report.page.item(\"basic_show#{i + 1}\").style(:visible, true)\n      report.page.item(\"basic_hide#{i + 1}\").style(:visible, false)\n    end\n\n    # The Graphic Style\n    report.page.item(:graphic_bcolor1).style(:border_color, '#ff0000')\n    report.page[:graphic_bcolor2].style(:border_color, 'red')\n    # nil or 'none'.\n    report.page.item(:graphic_bcolor4).style(:border_color, nil)\n\n    report.page.item(:graphic_bwidth1).style(:border_width, 5)\n    report.page.item(:graphic_bwidth2).style(:border_width, 5)\n    report.page.item(:graphic_bwidth3).style(:border_width, 5)\n    report.page.item(:graphic_bwidth4).style(:border_width, 2)\n    report.page.item(:graphic_bwidth5).style(:border_width, 0)\n\n    report.page.item(:graphic_fcolor1).style(:fill_color, '#ff0000')\n    # nil or 'none'\n    report.page.item(:graphic_fcolor3).style(:fill_color, 'none')\n    report.page.item(:graphic_fcolor4).style(:fill_color, 'ff0000')\n\n    # The Text Style\n    [1, 3].each do |i|\n      report.page[\"text_b#{i}\"].style(:bold, true)\n      report.page.item(\"text_i#{i}\").style(:italic, true)\n      report.page.item(\"text_u#{i}\").style(:underline, true)\n      report.page.item(\"text_l#{i}\").style(:linethrough, true)\n    end\n    [2, 4].each do |i|\n      report.page.item(\"text_b#{i}\").style(:bold, false)\n      report.page.item(\"text_i#{i}\").style(:italic, false)\n      report.page.item(\"text_u#{i}\").style(:underline, false)\n      report.page.item(\"text_l#{i}\").style(:linethrough, false)\n    end\n\n    3.times do |i|\n      report.page.item(\"text_a#{i + 1}\").style(:align, :right)\n    end\n    2.times do |i|\n      report.page.item(\"text_va#{i + 1}\").style(:valign, :bottom)\n    end\n\n    2.times do |i|\n      report.page[\"text_color#{i + 1}\"].style(:color, 'ff0000')\n    end\n\n    report.start_new_page(layout: template_path('templates/styles_in_list.tlf'))\n\n    # Settings for Header.\n    report.page.list(:list).header do |header|\n      header.item(:rect).styles(border_color: nil,\n                                fill_color: 'ff00ff')\n      header.item(:text).styles(align: :center,\n                                valign: :middle,\n                                bold: true)\n      header[:tblock].styles(align: :center,\n                            valign: :middle,\n                            color: 'red',\n                            linethrough: true)\n    end\n\n    1.step(10, 1) do |i|\n      # Flag of overflowed list-page.\n      is_overflowed = report.page.list(:list).overflow?\n\n      # Add details.\n      report.page.list(:list).add_row do |row|\n        case\n        when i % 2 == 0\n          row.item(:rect).styles(border_color: 'ff0000',\n                                border_width: 3,\n                                fill_color: '0000ff')\n          row.item(:text).styles(color: 'red',\n                                align: :left,\n                                valign: :middle)\n          row.item(:tblock).styles(color: 'blue',\n                                  align: :left,\n                                  valign: :middle)\n        when i % 3 == 0\n          row.item(:rect).style(:visible, false)\n          row.item(:text).styles(color: '0000ff',\n                                align: :right,\n                                valign: :bottom)\n          row.item(:tblock).styles(color: 'ff0000',\n                                  align: :right,\n                                  valign: :bottom)\n        end\n      end\n\n      # Change header styles when list-page was overflowed.\n      if is_overflowed\n        report.page.list(:list).header do |header|\n          header.item(:rect).styles(border_color: 'black',\n                                    fill_color: '#ffffff')\n          header.item(:text).styles(align: :left,\n                                    valign: :top,\n                                    bold: false)\n          header.item(:tblock).styles(align: :left,\n                                      valign: :top,\n                                      color: '#000000',\n                                      linethrough: false)\n        end\n      end\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/eudc/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 105.4,\n      \"y\": 60,\n      \"width\": 631,\n      \"height\": 100,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"日本で生まれ世界が育てた言語 Ruby\"\n      ]\n    },\n    {\n      \"id\": \"eudc\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 154.3,\n      \"width\": 801.8,\n      \"height\": 61,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": null,\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"eudc_bold\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 249.2,\n      \"y\": 249,\n      \"width\": 343.3,\n      \"height\": 61,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": null,\n        \"font-style\": [\n          \"bold\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"eudc_italic\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 249.2,\n      \"y\": 329.1,\n      \"width\": 343.3,\n      \"height\": 61,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": null,\n        \"font-style\": [\n          \"italic\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"eudc_bold_italic\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 249.2,\n      \"y\": 409,\n      \"width\": 343.3,\n      \"height\": 61,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": null,\n        \"font-style\": [\n          \"bold\",\n          \"italic\"\n        ],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"EUDC\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"landscape\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/eudc/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestEudcFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    Thinreports.configure do |config|\n      config.fallback_fonts = path_of('eudc.ttf')\n    end\n\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page do |page|\n      page.item(:eudc).value('日本で生まれ世界が育てた言語 Ruby')\n      page.values(\n        eudc_bold: '太字',\n        eudc_italic: '斜体',\n        eudc_bold_italic: '太字斜体'\n      )\n    end\n\n    assert_pdf report.generate\n  end\n\n  def teardown\n    Thinreports.config.fallback_fonts = []\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/graphics/template.tlf",
    "content": "{\n  \"version\": \"0.10.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 59,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 155,\n      \"y\": 59,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 10\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 20,\n      \"width\": 103.1,\n      \"height\": 21,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Rect (static)\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 290,\n      \"y\": 59,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"dashed\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 10\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 59,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"dotted\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 10\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 140,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 155,\n      \"y\": 140,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"none\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#ff0000\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 250,\n      \"y\": 140,\n      \"width\": 97.1,\n      \"height\": 43,\n      \"style\": {\n        \"border-color\": \"#0070c0\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"rect1\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 265,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"rect2\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 155,\n      \"y\": 265,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 10\n    },\n    {\n      \"id\": \"rect3\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 290,\n      \"y\": 265,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"dashed\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 10\n    },\n    {\n      \"id\": \"rect4\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 425,\n      \"y\": 265,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"dotted\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 10\n    },\n    {\n      \"id\": \"rect5\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 346,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"rect6\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 155,\n      \"y\": 346,\n      \"width\": 120.1,\n      \"height\": 62,\n      \"style\": {\n        \"border-color\": \"none\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#ff0000\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"rect7\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 250,\n      \"y\": 346,\n      \"width\": 97.1,\n      \"height\": 43,\n      \"style\": {\n        \"border-color\": \"#0070c0\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 225,\n      \"width\": 125.1,\n      \"height\": 21,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Rect (dynamic)\"\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/graphics/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestGraphicsFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/hidden_item/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 69,\n      \"y\": 75,\n      \"width\": 172.1,\n      \"height\": 84,\n      \"style\": {\n        \"border-color\": \"none\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#ff0000\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 19,\n      \"width\": 279.1,\n      \"height\": 40,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Visible\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 297.6,\n      \"y1\": 20,\n      \"x2\": 297.6,\n      \"y2\": 821.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 349,\n      \"y\": 74,\n      \"width\": 172.1,\n      \"height\": 84,\n      \"style\": {\n        \"border-color\": \"none\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#ff0000\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 297,\n      \"y\": 18,\n      \"width\": 279.1,\n      \"height\": 40,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Hidden\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"ellipse\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 205.55,\n      \"cy\": 161.55,\n      \"rx\": 57.55,\n      \"ry\": 50.55\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"ellipse\",\n      \"display\": false,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"cx\": 485.55,\n      \"cy\": 161.55,\n      \"rx\": 57.55,\n      \"ry\": 50.55\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"image\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 96.1,\n      \"y\": 177,\n      \"width\": 123.6,\n      \"height\": 142,\n      \"data\": {\n        \"mime-type\": \"image/jpeg\",\n        \"base64\": \"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\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"image\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 376,\n      \"y\": 177,\n      \"width\": 123.6,\n      \"height\": 142,\n      \"data\": {\n        \"mime-type\": \"image/jpeg\",\n        \"base64\": \"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\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 64,\n      \"y\": 333.1,\n      \"width\": 200,\n      \"height\": 40,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#c00000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Ruby\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 339,\n      \"y\": 333.1,\n      \"width\": 200,\n      \"height\": 40,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#c00000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Ruby\"\n      ]\n    },\n    {\n      \"id\": \"v_thinreports\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 45,\n      \"y\": 376.1,\n      \"width\": 236.1,\n      \"height\": 19,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"Thinreports\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"h_thinreports\",\n      \"type\": \"text-block\",\n      \"display\": false,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 376.1,\n      \"width\": 236.1,\n      \"height\": 19,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"Thinreports\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"List\",\n      \"type\": \"list\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 430.1,\n      \"width\": 555.2,\n      \"height\": 306.1,\n      \"header\": {\n        \"enabled\": true,\n        \"height\": 51.1,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": 0\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 63,\n            \"y\": 443,\n            \"width\": 200,\n            \"height\": 24.3,\n            \"style\": {\n              \"font-family\": [\n                \"IPAMincho\"\n              ],\n              \"font-size\": 24,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"表示\"\n            ]\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": false,\n            \"description\": \"\",\n            \"x\": 338,\n            \"y\": 443,\n            \"width\": 200,\n            \"height\": 24.3,\n            \"style\": {\n              \"font-family\": [\n                \"IPAMincho\"\n              ],\n              \"font-size\": 24,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"非表示\"\n            ]\n          }\n        ]\n      },\n      \"detail\": {\n        \"height\": 46,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -22.5\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 63,\n            \"y\": 516.5,\n            \"width\": 200,\n            \"height\": 24.3,\n            \"style\": {\n              \"font-family\": [\n                \"IPAMincho\"\n              ],\n              \"font-size\": 24,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"表示\"\n            ]\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": false,\n            \"description\": \"\",\n            \"x\": 338,\n            \"y\": 516.5,\n            \"width\": 200,\n            \"height\": 24.3,\n            \"style\": {\n              \"font-family\": [\n                \"IPAMincho\"\n              ],\n              \"font-size\": 24,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"非表示\"\n            ]\n          }\n        ]\n      },\n      \"page-footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -50.1\n        },\n        \"items\": []\n      },\n      \"footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -105.3\n        },\n        \"items\": []\n      },\n      \"content-height\": 255.00000000000003,\n      \"auto-page-break\": true\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/hidden_item/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestHiddenItemFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    2.times { report.list(:List).add_row }\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/image_block/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 51,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 443,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 20,\n      \"width\": 200,\n      \"height\": 26.7,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 24,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Positioning\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 130,\n      \"y\": 51,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 240,\n      \"y\": 51,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 385,\n      \"width\": 200,\n      \"height\": 26.7,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 24,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Overflowing\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 25,\n      \"y\": 411,\n      \"width\": 288,\n      \"height\": 26,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Resize automatically to 150x75 from 200x100.\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 565,\n      \"width\": 200,\n      \"height\": 26.7,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 24,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Open URI\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 628,\n      \"width\": 555.2,\n      \"height\": 92.3,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 25,\n      \"y\": 595,\n      \"width\": 369.4,\n      \"height\": 26,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"http://www.thinreports.org/assets/logos/thinreports-logo.png\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 443,\n      \"width\": 150,\n      \"height\": 76,\n      \"style\": {\n        \"border-color\": \"#f79646\",\n        \"border-width\": 1,\n        \"border-style\": \"dashed\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"list\",\n      \"type\": \"list\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 361.1,\n      \"y\": 55,\n      \"width\": 199.1,\n      \"height\": 312.1,\n      \"header\": {\n        \"enabled\": true,\n        \"height\": 33.2,\n        \"translate\": {\n          \"x\": 10,\n          \"y\": -395.2\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 351.1,\n            \"y\": 450.2,\n            \"width\": 199.1,\n            \"height\": 33.2,\n            \"style\": {\n              \"font-family\": [\n                \"Times New Roman\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"middle\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"In List\"\n            ]\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 353.1,\n            \"y1\": 483.4,\n            \"x2\": 560.2,\n            \"y2\": 483.4\n          }\n        ]\n      },\n      \"detail\": {\n        \"height\": 60,\n        \"translate\": {\n          \"x\": 10,\n          \"y\": -395.2\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 351.1,\n            \"y1\": 543.2,\n            \"x2\": 560.2,\n            \"y2\": 543.2\n          },\n          {\n            \"id\": \"in_list\",\n            \"type\": \"image-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 351.1,\n            \"y\": 483.4,\n            \"width\": 198.1,\n            \"height\": 58.8,\n            \"style\": {\n              \"position-x\": \"center\",\n              \"position-y\": \"middle\"\n            }\n          }\n        ]\n      },\n      \"page-footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 10,\n          \"y\": -368.4\n        },\n        \"items\": []\n      },\n      \"footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 10,\n          \"y\": -393.3\n        },\n        \"items\": []\n      },\n      \"content-height\": 278.90000000000003,\n      \"auto-page-break\": false\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 359,\n      \"y\": 20,\n      \"width\": 200,\n      \"height\": 26.7,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 24,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Use in List\"\n      ]\n    },\n    {\n      \"id\": \"pos_top_left\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 51,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"top\"\n      }\n    },\n    {\n      \"id\": \"pos_top_center\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 130,\n      \"y\": 51,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"center\",\n        \"position-y\": \"top\"\n      }\n    },\n    {\n      \"id\": \"pos_top_right\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 240,\n      \"y\": 51,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"right\",\n        \"position-y\": \"top\"\n      }\n    },\n    {\n      \"id\": \"pos_center_left\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 161,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"middle\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 161,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"pos_center_center\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 130,\n      \"y\": 161,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"center\",\n        \"position-y\": \"middle\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 130,\n      \"y\": 161,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"pos_center_right\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 240,\n      \"y\": 161,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"right\",\n        \"position-y\": \"middle\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 240,\n      \"y\": 161,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"pos_bottom_left\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 271,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"bottom\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 271,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"pos_bottom_center\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 130,\n      \"y\": 271,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"center\",\n        \"position-y\": \"bottom\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 130,\n      \"y\": 271,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"pos_bottom_right\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 240,\n      \"y\": 271,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"right\",\n        \"position-y\": \"bottom\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 240,\n      \"y\": 271,\n      \"width\": 100,\n      \"height\": 100,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"overflow\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 443,\n      \"width\": 150,\n      \"height\": 100,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"top\"\n      }\n    },\n    {\n      \"id\": \"thinreports_logo\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 628,\n      \"width\": 555.2,\n      \"height\": 92.3,\n      \"style\": {\n        \"position-x\": \"center\",\n        \"position-y\": \"middle\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 340.1\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 371.1\n      }\n    ]\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/image_block/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'open-uri'\nrequire 'openssl'\n\nclass Thinreports::BasicReport::TestImageBlockFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    image50x50 = path_of('img50x50.png')\n    image200x100 = path_of('img200x100.png')\n\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    report.page.values(\n      pos_top_left: image50x50,\n      pos_top_center: image50x50,\n      pos_top_right: image50x50,\n      pos_center_left: image50x50,\n      pos_center_center: image50x50,\n      pos_center_right: image50x50,\n      pos_bottom_left: image50x50,\n      pos_bottom_center: image50x50,\n      pos_bottom_right: image50x50\n    )\n\n    report.page.item(:overflow).src = image200x100\n    report.page[:thinreports_logo] = StringIO.new(dir.join('thinreports-logo.png').binread)\n\n    report.page.list(:list) do |list|\n      3.times { list.add_row in_list: image50x50 }\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/list_events/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"default\",\n      \"type\": \"list\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 103,\n      \"width\": 555.2,\n      \"height\": 300,\n      \"header\": {\n        \"enabled\": true,\n        \"height\": 50,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -61.1\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 214.1,\n            \"x2\": 575.2,\n            \"y2\": 214.1\n          },\n          {\n            \"id\": \"title\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 169.2,\n            \"y\": 180.1,\n            \"width\": 249,\n            \"height\": 18,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"\",\n            \"multiple-line\": false,\n            \"format\": {\n              \"base\": \"\",\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"detail\": {\n        \"height\": 50,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -86.5\n        },\n        \"items\": [\n          {\n            \"id\": \"price\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 169.2,\n            \"y\": 255.5,\n            \"width\": 249,\n            \"height\": 18,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"right\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"\",\n            \"multiple-line\": false,\n            \"format\": {\n              \"base\": \"\",\n              \"type\": \"number\",\n              \"number\": {\n                \"delimiter\": \",\",\n                \"precision\": 0\n              }\n            }\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 289.5,\n            \"x2\": 575.2,\n            \"y2\": 289.5\n          }\n        ]\n      },\n      \"page-footer\": {\n        \"enabled\": true,\n        \"height\": 50,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -111.9\n        },\n        \"items\": [\n          {\n            \"id\": \"price\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 169.2,\n            \"y\": 330.9,\n            \"width\": 249,\n            \"height\": 18,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"right\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"\",\n            \"multiple-line\": false,\n            \"format\": {\n              \"base\": \"\",\n              \"type\": \"number\",\n              \"number\": {\n                \"delimiter\": \",\",\n                \"precision\": 0\n              }\n            }\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 364.9,\n            \"x2\": 575.2,\n            \"y2\": 364.9\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 74.1,\n            \"y\": 332.9,\n            \"width\": 77.4,\n            \"height\": 18.5,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 16,\n              \"color\": \"#000000\",\n              \"text-align\": \"right\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"Page Total\"\n            ]\n          }\n        ]\n      },\n      \"footer\": {\n        \"enabled\": true,\n        \"height\": 50,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -118.5\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 421.5,\n            \"x2\": 575.2,\n            \"y2\": 421.5\n          },\n          {\n            \"id\": \"price\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 169.2,\n            \"y\": 387.5,\n            \"width\": 249,\n            \"height\": 18,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"right\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"\",\n            \"multiple-line\": false,\n            \"format\": {\n              \"base\": \"\",\n              \"type\": \"number\",\n              \"number\": {\n                \"delimiter\": \",\",\n                \"precision\": 0\n              }\n            }\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 74.1,\n            \"y\": 389.5,\n            \"width\": 77.4,\n            \"height\": 18.5,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 16,\n              \"color\": \"#000000\",\n              \"text-align\": \"right\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"Total\"\n            ]\n          }\n        ]\n      },\n      \"content-height\": 250,\n      \"auto-page-break\": true\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 140.1,\n      \"y\": 31,\n      \"width\": 315.1,\n      \"height\": 48,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 26,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"List Events for 0.8 or higher\"\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 418.2\n      },\n      {\n        \"type\": \"x\",\n        \"position\": 169.2\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 84\n      }\n    ]\n  },\n  \"title\": \"List Events\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/list_events/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestListEventsFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n\n    report.list.header title: 'Prices'\n\n    report.list do |list|\n      price_for = { page: 0, all: 0 }\n\n      list.on_page_finalize do\n        price_for[:all] += price_for[:page]\n        price_for[:page] = 0\n      end\n\n      list.on_page_footer_insert do |footer|\n        footer.item(:price).value(price_for[:page])\n      end\n\n      list.on_footer_insert do |footer|\n        footer.item(:price).value(price_for[:all])\n      end\n\n      [100, 200, 250, 50, 100, 20, 30, 50, 100, 100].each do |price|\n        list.add_row price: price\n        # Calculate sum price for each page of list\n        price_for[:page] += price\n      end\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/list_manually/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"default\",\n      \"type\": \"list\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 22,\n      \"width\": 555.2,\n      \"height\": 320.1,\n      \"header\": {\n        \"enabled\": true,\n        \"height\": 46.3,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -35\n        },\n        \"items\": [\n          {\n            \"id\": \"header\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 160.6,\n            \"y\": 62,\n            \"width\": 274.1,\n            \"height\": 36,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 36,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"\",\n            \"multiple-line\": false,\n            \"format\": {\n              \"base\": \"Header#{value}\",\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"detail\": {\n        \"height\": 57.7,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -45.3\n        },\n        \"items\": [\n          {\n            \"id\": \"detail\",\n            \"type\": \"text-block\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 211.4,\n            \"y\": 124.5,\n            \"width\": 172.5,\n            \"height\": 36,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 36,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"top\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": [],\n              \"overflow\": \"truncate\",\n              \"word-wrap\": \"break-word\"\n            },\n            \"reference-id\": \"\",\n            \"value\": \"\",\n            \"multiple-line\": false,\n            \"format\": {\n              \"base\": \"Detail#{value}\",\n              \"type\": \"\"\n            }\n          }\n        ]\n      },\n      \"page-footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -44.2\n        },\n        \"items\": []\n      },\n      \"footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -86.7\n        },\n        \"items\": []\n      },\n      \"content-height\": 273.8,\n      \"auto-page-break\": false\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"List Manual Generation\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/list_manually/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestListManuallyFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.list.header do |h|\n      h.item(:header).value(report.page.no)\n    end\n\n    25.times do |row_index|\n      if report.list.overflow?\n        report.start_new_page\n        report.list.header header: report.page.no\n      end\n\n      report.list.page_break if row_index == 15\n\n      report.list.add_row detail: row_index\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/page_number/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"pageno\",\n      \"type\": \"page-number\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 50,\n      \"y\": 205,\n      \"width\": 139.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\"\n      },\n      \"format\": \"{page} / {total}\",\n      \"target\": \"\"\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 46,\n      \"width\": 176.1,\n      \"height\": 28,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Basis\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 195,\n      \"y\": 114,\n      \"width\": 199.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"(Center Alignment)\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 195,\n      \"y\": 143,\n      \"width\": 199.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"(Right Alignment)\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 180,\n      \"width\": 176.1,\n      \"height\": 28,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"With ID\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"page-number\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 50,\n      \"y\": 113,\n      \"width\": 130.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\"\n      },\n      \"format\": \"{page}\",\n      \"target\": \"\"\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"page-number\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 50,\n      \"y\": 84,\n      \"width\": 130.1,\n      \"height\": 18.9,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"letter-spacing\": 10,\n        \"font-style\": [],\n        \"overflow\": \"truncate\"\n      },\n      \"format\": \"{page}\",\n      \"target\": \"\"\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"page-number\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 50,\n      \"y\": 140,\n      \"width\": 130.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\"\n      },\n      \"format\": \"{page}\",\n      \"target\": \"\"\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/page_number/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestPageNumberFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n\n    report.start_new_page do |page|\n      page.item(:pageno).hide\n    end\n    report.start_new_page do |page|\n      page.item(:pageno).styles(color: 'red',\n                                bold: true,\n                                underline: true,\n                                linethrough: true)\n    end\n\n    report.start_new_page count: false\n    report.start_new_page count: true\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/page_number_with_list/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"default\",\n      \"type\": \"list\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 109,\n      \"width\": 555.2,\n      \"height\": 390.2,\n      \"header\": {\n        \"enabled\": true,\n        \"height\": 58.1,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": 0\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 167.1,\n            \"x2\": 575.2,\n            \"y2\": 167.1\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 197.6,\n            \"y\": 125.6,\n            \"width\": 200,\n            \"height\": 25.1,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"middle\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"Header\"\n            ]\n          }\n        ]\n      },\n      \"detail\": {\n        \"height\": 52.9,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -19.9\n        },\n        \"items\": [\n          {\n            \"id\": \"\",\n            \"type\": \"line\",\n            \"display\": true,\n            \"description\": \"\",\n            \"style\": {\n              \"border-color\": \"#000000\",\n              \"border-width\": 1,\n              \"border-style\": \"solid\"\n            },\n            \"x1\": 20,\n            \"y1\": 239.9,\n            \"x2\": 575.2,\n            \"y2\": 239.9\n          },\n          {\n            \"id\": \"\",\n            \"type\": \"text\",\n            \"display\": true,\n            \"description\": \"\",\n            \"x\": 197.6,\n            \"y\": 203.6,\n            \"width\": 200,\n            \"height\": 25.1,\n            \"style\": {\n              \"font-family\": [\n                \"Helvetica\"\n              ],\n              \"font-size\": 18,\n              \"color\": \"#000000\",\n              \"text-align\": \"center\",\n              \"vertical-align\": \"middle\",\n              \"line-height\": \"\",\n              \"line-height-ratio\": \"\",\n              \"letter-spacing\": \"\",\n              \"font-style\": []\n            },\n            \"texts\": [\n              \"Detail\"\n            ]\n          }\n        ]\n      },\n      \"page-footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -45\n        },\n        \"items\": []\n      },\n      \"footer\": {\n        \"enabled\": false,\n        \"height\": 0,\n        \"translate\": {\n          \"x\": 0,\n          \"y\": -103.5\n        },\n        \"items\": []\n      },\n      \"content-height\": 332.09999999999997,\n      \"auto-page-break\": true\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"page-number\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 273.1,\n      \"y\": 756.3,\n      \"width\": 186,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\"\n      },\n      \"format\": \"{page} / {total}\",\n      \"target\": \"\"\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"page-number\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 434.1,\n      \"y\": 69,\n      \"width\": 141.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\"\n      },\n      \"format\": \"{page} / {total}\",\n      \"target\": \"default\"\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 115,\n      \"y\": 755,\n      \"width\": 150.1,\n      \"height\": 18.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 16,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Report PageNo:\"\n      ]\n    },\n    {\n      \"id\": \"group_no\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 69,\n      \"width\": 142.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/page_number_with_list/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestPageNumberWithListFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n\n    report.start_new_page\n    report.page.item(:group_no).value('Group A')\n\n    10.times { report.list.add_row }\n\n    report.start_new_page\n    report.page.item(:group_no).value('Group B')\n\n    20.times { report.list.add_row }\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/palleted_png/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"image\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 20,\n      \"width\": 200,\n      \"height\": 200,\n      \"data\": {\n        \"mime-type\": \"image/png\",\n        \"base64\": \"iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAD1BMVEX/AAD/AAD/AAD/AAD////Icf73AAAAA3RSTlO/fz8qtTX3AAAAAWJLR0QEj2jZUQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAMtJREFUeNrtzwERgEAAw7AH/HtGBr2RKGjPM+J8HWDESJyRGiM1RmqM1BipMVJjpMZIjZEaIzVGaozUGKkxUmOkxkiNkRojNUZqjNQYqTFSszMCAAAAAAAAAAAA/3SNMFJjpMZIjZEaIzVGaozUGKkxUmOkxkiNkRojNUZqjNQYqTFSY6TGSI2RGiM1RmqM1Bip2Rm5RxipMVJjpMZIjZEaIzVGaozUGKkxUmOkxkiNkRojNUZqjNQYqTFSY6TGSI2RGiM1RmqM1MyMvMkE6mEsuD8jAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE0LTEwLTA5VDEwOjM1OjI1KzAyOjAwxhRVNQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNC0xMC0wOVQxMDozNToyNSswMjowMLdJ7YkAAAAASUVORK5CYII=\"\n      }\n    },\n    {\n      \"id\": \"image\",\n      \"type\": \"image-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 278.2,\n      \"y\": 20,\n      \"width\": 266.7,\n      \"height\": 223.7,\n      \"style\": {\n        \"position-x\": \"left\",\n        \"position-y\": \"top\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/palleted_png/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestPalletedPngFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page do |page|\n      page.item(:image).src = path_of('palleted_png.png')\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/report_callbacks/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"text1\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 45,\n      \"width\": 357.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text2\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 75,\n      \"width\": 357.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text3\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 105,\n      \"width\": 357.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"text4\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 135,\n      \"width\": 357.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/report_callbacks/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestReportCallbacksFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n\n    report.on_page_create do |page|\n      page.item(:text2).value('Rendered by on_page_create')\n    end\n\n    report.start_new_page\n    report.start_new_page\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_align/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 19,\n      \"width\": 555.2,\n      \"height\": 84.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Align Right\",\n        \"Helvetica\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 297.6,\n      \"y1\": 20,\n      \"x2\": 297.6,\n      \"y2\": 821.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 105,\n      \"width\": 555.2,\n      \"height\": 72,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"右寄せ\",\n        \"IPA明朝\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 297.6,\n      \"y1\": 20,\n      \"x2\": 297.6,\n      \"y2\": 821.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 575.2,\n      \"y1\": 20,\n      \"x2\": 575.2,\n      \"y2\": 821.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 241,\n      \"width\": 555.2,\n      \"height\": 84.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Align Center\",\n        \"Helvetica\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 330,\n      \"width\": 555.2,\n      \"height\": 72,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"中央寄せ\",\n        \"IPA明朝\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 490,\n      \"width\": 555.2,\n      \"height\": 84.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Align Left\",\n        \"Helvetica\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 580,\n      \"width\": 555.2,\n      \"height\": 72,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"左寄せ\",\n        \"IPA明朝\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 20,\n      \"y1\": 20,\n      \"x2\": 20,\n      \"y2\": 821.8\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"Case: Text Align\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_align/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextAlignFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_block_formatting/template.tlf",
    "content": "{\n  \"version\": \"0.10.0\",\n  \"items\": [\n    {\n      \"id\": \"basic\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 110,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"Price: {value}\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"date_with_not_a_date\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 225,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"datetime\",\n        \"datetime\": {\n          \"format\": \"%Y/%m/%d %H:%M:%S\"\n        }\n      }\n    },\n    {\n      \"id\": \"number_with_delimiter\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 285,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"number\",\n        \"number\": {\n          \"delimiter\": \",\"\n        }\n      }\n    },\n    {\n      \"id\": \"number_with_precision\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 310,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"number\",\n        \"number\": {\n          \"precision\": 3\n        }\n      }\n    },\n    {\n      \"id\": \"number_with_delimiter_and_precision\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 335,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"number\",\n        \"number\": {\n          \"delimiter\": \"_\",\n          \"precision\": 5\n        }\n      }\n    },\n    {\n      \"id\": \"number_with_invalid_string_number\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 385,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"number\",\n        \"number\": {\n          \"delimiter\": \"_\",\n          \"precision\": 5\n        }\n      }\n    },\n    {\n      \"id\": \"padding_left\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 450,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"padding\",\n        \"padding\": {\n          \"length\": 10,\n          \"char\": \"0\",\n          \"direction\": \"L\"\n        }\n      }\n    },\n    {\n      \"id\": \"padding_right\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 475,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"padding\",\n        \"padding\": {\n          \"length\": 10,\n          \"char\": \"_\",\n          \"direction\": \"R\"\n        }\n      }\n    },\n    {\n      \"id\": \"padding_with_blank_value\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 550,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"padding\",\n        \"padding\": {\n          \"length\": 10,\n          \"char\": \"0\",\n          \"direction\": \"L\"\n        }\n      }\n    },\n    {\n      \"id\": \"date_with_date\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 175,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"datetime\",\n        \"datetime\": {\n          \"format\": \"%Y/%m/%d\"\n        }\n      }\n    },\n    {\n      \"id\": \"date_with_time\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 200,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"datetime\",\n        \"datetime\": {\n          \"format\": \"%Y/%m/%d %H:%M:%S\"\n        }\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 20,\n      \"width\": 149.1,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"bold\"\n        ]\n      },\n      \"texts\": [\n        \"Formatting\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 85,\n      \"width\": 149.1,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Basic Format\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 150,\n      \"width\": 149.1,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Date Format\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 260,\n      \"width\": 149.1,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Number Format\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 425,\n      \"width\": 149.1,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Padding Format\"\n      ]\n    },\n    {\n      \"id\": \"multiline_basic\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 110,\n      \"width\": 205.1,\n      \"height\": 35,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"Address: {value}\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"multiline_number\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 285,\n      \"width\": 205.1,\n      \"height\": 35,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"number\",\n        \"number\": {\n          \"delimiter\": \",\",\n          \"precision\": 5\n        }\n      }\n    },\n    {\n      \"id\": \"multiline_padding\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 450,\n      \"width\": 205.1,\n      \"height\": 35,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"padding\",\n        \"padding\": {\n          \"length\": 10,\n          \"char\": \"0\",\n          \"direction\": \"L\"\n        }\n      }\n    },\n    {\n      \"id\": \"multiline_date\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 175,\n      \"width\": 205.1,\n      \"height\": 35,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"datetime\",\n        \"datetime\": {\n          \"format\": \"%Y/%m/%d %H:%M:%S\"\n        }\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 85,\n      \"width\": 195,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Basic Format (multi-line)\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 150,\n      \"width\": 189,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Date Format (multi-line)\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 260,\n      \"width\": 215,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Number Format (multi-line)\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 320,\n      \"y\": 425,\n      \"width\": 217,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [\n          \"underline\"\n        ]\n      },\n      \"texts\": [\n        \"Padding Format (multi-line)\"\n      ]\n    },\n    {\n      \"id\": \"number_with_valid_string_number\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 360,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"number\",\n        \"number\": {\n          \"delimiter\": \"_\",\n          \"precision\": 5\n        }\n      }\n    },\n    {\n      \"id\": \"padding_with_number_value\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 525,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"padding\",\n        \"padding\": {\n          \"length\": 10,\n          \"char\": \"0\",\n          \"direction\": \"R\"\n        }\n      }\n    },\n    {\n      \"id\": \"padding_with_value_longer_than_length\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 500,\n      \"width\": 205.1,\n      \"height\": 16.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 14,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"padding\",\n        \"padding\": {\n          \"length\": 10,\n          \"char\": \"0\",\n          \"direction\": \"L\"\n        }\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 225.1\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 84\n      }\n    ]\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_block_formatting/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'date'\n\nclass Thinreports::BasicReport::TestTextBlockFormattingFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new\n\n    report.start_new_page layout: template_path do |page|\n      # Basic\n      page.item(:basic).value = 1980\n\n      # Date\n      page.values(\n        date_with_date: Date.new(2019, 1, 1),\n        date_with_time: Time.new(2019, 1, 1, 12, 30, 45),\n        date_with_not_a_date: 'Not applied'\n      )\n\n      # Number\n      page.values(\n        number_with_delimiter: 9_999_999,\n        number_with_precision: 1_000.1,\n        number_with_delimiter_and_precision: 198_000,\n        number_with_valid_string_number: '198000',\n        number_with_invalid_string_number: 'Not applied'\n      )\n\n      # Padding\n      page.values(\n        padding_left: '1234',\n        padding_right: 'abcd',\n        padding_with_value_longer_than_length: '9' * 11,\n        padding_with_number_value: 9_999,\n        padding_with_blank_value: ''\n      )\n\n      # Basic (multi-line)\n      page.item(:multiline_basic).value = 'TitleTitle'\n\n      # Date (multi-line)\n      page.item(:multiline_date).value = Date.new(2019, 2, 1)\n\n      # Number (multi-line)\n      page.item(:multiline_number).value = 123_456\n\n      # Padding (multi-line)\n      page.item(:multiline_padding).value = '123'\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_block_overflow/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 262.1,\n      \"y\": 76,\n      \"width\": 206.1,\n      \"height\": 41,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 74,\n      \"width\": 164.2,\n      \"height\": 17,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"truncate\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 74,\n      \"width\": 164.2,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 43,\n      \"y\": 46,\n      \"width\": 200,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Overflow: \\\"truncate\\\"\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 99,\n      \"width\": 164.2,\n      \"height\": 18,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"truncate_ja\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 99,\n      \"width\": 164.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 43,\n      \"y\": 140,\n      \"width\": 200,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Overflow: \\\"fit\\\"\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 169,\n      \"width\": 164.2,\n      \"height\": 30.7,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"fit\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 169,\n      \"width\": 164.2,\n      \"height\": 30.7,\n      \"style\": {\n        \"font-family\": [\n          \"Courier New\"\n        ],\n        \"font-size\": 28,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"fit\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 209,\n      \"width\": 164.2,\n      \"height\": 28,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"fit_ja\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 209,\n      \"width\": 164.2,\n      \"height\": 28,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 28,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"fit\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 43,\n      \"y\": 250,\n      \"width\": 200,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Overflow: \\\"expand\\\"\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 279,\n      \"width\": 164.2,\n      \"height\": 18.9,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"expand\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 279,\n      \"width\": 164.2,\n      \"height\": 18.9,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"expand\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 370,\n      \"width\": 164.2,\n      \"height\": 18,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"expand_ja\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 57.9,\n      \"y\": 370,\n      \"width\": 164.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"expand\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"truncate_m\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 262.1,\n      \"y\": 76,\n      \"width\": 206.1,\n      \"height\": 41,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 262.9,\n      \"y\": 169,\n      \"width\": 206.1,\n      \"height\": 71.1,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"fit_m\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 262.9,\n      \"y\": 169,\n      \"width\": 206.1,\n      \"height\": 71.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 26,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"fit\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 262.9,\n      \"y\": 279,\n      \"width\": 206.1,\n      \"height\": 41,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"#FFFFFF\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"expand_m\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 262.9,\n      \"y\": 279,\n      \"width\": 206.1,\n      \"height\": 41,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 26,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": 30,\n        \"line-height-ratio\": 1,\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"expand\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"Tblock Overflow\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_block_overflow/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextBlockOverflowFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n\n    report.start_new_page do |page|\n      page.values(truncate: 'The string overflowing from the area will be truncated',\n                  truncate_ja: '領域から溢れたテキストは切り捨てられます。',\n                  truncate_m: 'The string overflowing from the area will be truncated')\n\n      page.values(fit: 'The string overflowing from the area will be reduced',\n                  fit_ja: '領域から溢れたテキストは縮小されます。',\n                  fit_m: '複数行モードでも、領域から溢れたテキストは自動的に縮小され折り返して表示されます。')\n\n      page.values(expand: 'If a string was overflowed, a box will be expanded automatically',\n                  expand_ja: 'テキストが溢れた場合、ボックスが自動的に拡張されます。',\n                  expand_m: 'If a string was overflowed, a box will be expanded automatically')\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_block_singleline/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"fallback_to_ipafont\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 37,\n      \"y\": 102,\n      \"width\": 291.1,\n      \"height\": 26,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 24,\n        \"color\": \"#ff0000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 38,\n      \"y\": 52,\n      \"width\": 488,\n      \"height\": 36,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 16,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Helveticaフォントが設定されているTblockに日本語をセットする。\",\n        \"溢れたテキストは表示されない。\"\n      ]\n    },\n    {\n      \"id\": \"set_multiline_text\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 37,\n      \"y\": 178,\n      \"width\": 291.1,\n      \"height\": 24,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 24,\n        \"color\": \"#ff0000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 38,\n      \"y\": 147,\n      \"width\": 208,\n      \"height\": 16,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 16,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"複数行テキストをセットする\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 37,\n      \"y\": 102,\n      \"width\": 291.1,\n      \"height\": 26,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 37,\n      \"y\": 178,\n      \"width\": 291.1,\n      \"height\": 24,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"Single Line Tblock\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_block_singleline/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextBlockSinglelineFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    report.page.item(:fallback_to_ipafont).value('IPA明朝に自動的にフォールバックされる')\n    report.page.item(:set_multiline_text).value(\"１行目\\n2行目\\n3行目\\n4行目\\n5行目\")\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_block_style/templates/basic_styles.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 21,\n      \"width\": 555.2,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Char Space in Single(Helvetica)\"\n      ]\n    },\n    {\n      \"id\": \"space_single_helvetica\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 50,\n      \"width\": 555.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 426,\n      \"y1\": 20,\n      \"x2\": 426,\n      \"y2\": 78\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 83,\n      \"width\": 323,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"文字間隔 in 単行（IPA明朝）\"\n      ]\n    },\n    {\n      \"id\": \"space_single_ipamincho\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 110,\n      \"width\": 555.2,\n      \"height\": 18,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 333,\n      \"y1\": 80,\n      \"x2\": 333,\n      \"y2\": 138\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 148,\n      \"width\": 555.2,\n      \"height\": 38,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Char Space\",\n        \"in Multiple(Times New Roman)\"\n      ]\n    },\n    {\n      \"id\": \"space_multi_times\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 199.9,\n      \"width\": 555.2,\n      \"height\": 51.2,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 386,\n      \"y1\": 165,\n      \"x2\": 386,\n      \"y2\": 251.1\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 149,\n      \"y1\": 148,\n      \"x2\": 149,\n      \"y2\": 234.1\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 275,\n      \"width\": 323,\n      \"height\": 36,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"文字間隔\",\n        \"in 複数行（IPA明朝）\"\n      ]\n    },\n    {\n      \"id\": \"space_multi_ipamincho\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 324,\n      \"width\": 555.2,\n      \"height\": 52.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 5,\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 249,\n      \"y1\": 292,\n      \"x2\": 249,\n      \"y2\": 378.1\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 107,\n      \"y1\": 273,\n      \"x2\": 107,\n      \"y2\": 359.1\n    },\n    {\n      \"id\": \"left_top\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 406.1,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"left_center\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 215.1,\n      \"y\": 406.1,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"left_bottom\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 410,\n      \"y\": 406.1,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"bottom\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 406.1,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 215.1,\n      \"y\": 406.1,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 410,\n      \"y\": 406.1,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"line_height\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 311.1,\n      \"y\": 678,\n      \"width\": 179.1,\n      \"height\": 90,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": 41,\n        \"line-height-ratio\": 2,\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 99,\n      \"y\": 678,\n      \"width\": 179.1,\n      \"height\": 142.8,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": 41,\n        \"line-height-ratio\": 2,\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"行間隔2.0\",\n        \"日本語\",\n        \"Thinreports\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 93,\n      \"y1\": 692.8,\n      \"x2\": 511.2,\n      \"y2\": 692.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 93,\n      \"y1\": 727.8,\n      \"x2\": 511.2,\n      \"y2\": 727.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 93,\n      \"y1\": 766.8,\n      \"x2\": 511.2,\n      \"y2\": 766.8\n    },\n    {\n      \"id\": \"center_top\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 481,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"center_center\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 215.1,\n      \"y\": 481,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"center_bottom\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 410,\n      \"y\": 481,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"center\",\n        \"vertical-align\": \"bottom\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 481,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 215.1,\n      \"y\": 481,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 410,\n      \"y\": 481,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"right_top\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 556,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"right_center\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 215.1,\n      \"y\": 556,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"middle\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"right_bottom\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 410,\n      \"y\": 556,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"font-family\": [\n          \"IPAGothic\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"bottom\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 556,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 215.1,\n      \"y\": 556,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 410,\n      \"y\": 556,\n      \"width\": 165.1,\n      \"height\": 69.1,\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  },\n  \"title\": \"Tblock Styles\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_block_style/templates/font_size.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 40,\n      \"y\": 60,\n      \"width\": 151.8,\n      \"height\": 46,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"サイズ18\"\n      ]\n    },\n    {\n      \"id\": \"text_single24\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 165,\n      \"y\": 60,\n      \"width\": 151.8,\n      \"height\": 46,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"サイズ24\"\n      ]\n    },\n    {\n      \"id\": \"text_single32\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 345,\n      \"y\": 60,\n      \"width\": 151.8,\n      \"height\": 46,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"サイズ32\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 35,\n      \"y\": 179.8,\n      \"width\": 200,\n      \"height\": 100,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"サイズ18\",\n        \"サイズ18\"\n      ]\n    },\n    {\n      \"id\": \"text_multiple24\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 165,\n      \"y\": 179.8,\n      \"width\": 200,\n      \"height\": 100,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"サイズ24\",\n        \"サイズ24\"\n      ]\n    },\n    {\n      \"id\": \"text_multiple32\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 345,\n      \"y\": 179.8,\n      \"width\": 200,\n      \"height\": 100,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"サイズ32\",\n        \"サイズ32\"\n      ]\n    },\n    {\n      \"id\": \"block_single18\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 40,\n      \"y\": 320.6,\n      \"width\": 103.4,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"block_single24\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 165,\n      \"y\": 320.6,\n      \"width\": 157.2,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"block_single32\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 345,\n      \"y\": 320.6,\n      \"width\": 230.2,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"block_multiple18\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 40,\n      \"y\": 390,\n      \"width\": 103.4,\n      \"height\": 113.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"block_multiple24\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 165,\n      \"y\": 390,\n      \"width\": 157.2,\n      \"height\": 113.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"block_multiple32\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 345,\n      \"y\": 390,\n      \"width\": 230.2,\n      \"height\": 113.3,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 164.4\n      },\n      {\n        \"type\": \"x\",\n        \"position\": 344.1\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 503.3\n      }\n    ]\n  },\n  \"title\": \"FontSize\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_block_style/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextBlockStyleFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new\n\n    report.start_new_page layout: template_path('templates/basic_styles.tlf') do |page|\n      page.item(:space_single_helvetica).value('Char Space in Single(Helvetica)')\n      page.item(:space_single_ipamincho).value = '文字間隔 in 単行（IPA明朝）'\n\n      page[:space_multi_times] = \"Char Space\\nin Multiple(Times New Roman)\"\n      page.item(:space_multi_ipamincho).value(\"文字間隔\\nin 複数行（IPA明朝）\")\n\n      page.values(left_top:       '左上揃え',\n                  left_center:    '左中央揃え',\n                  left_bottom:    '左下揃え',\n                  center_top:     '中央上揃え',\n                  center_center: '中央揃え',\n                  center_bottom: '中央下揃え',\n                  right_top:      '右上揃え',\n                  right_center:   '右中央揃え',\n                  right_bottom:   '右下揃え')\n\n      page.item(:line_height).value(\"行間隔2.0\\n日本語\\nThinreports\")\n    end\n\n    report.start_new_page layout: template_path('templates/font_size.tlf') do |page|\n      page[:text_single24].style(:font_size, 24)\n      page[:text_single32].style(:font_size, 32)\n\n      page.item(:text_multiple24).style(:font_size, 24)\n      page.item(:text_multiple32).style(:font_size, 32)\n\n      page.item(:block_single18).value('サイズ18')\n      page.item(:block_single24).style(:font_size, 24).value('サイズ24')\n      page.item(:block_single32).style(:font_size, 32).value('サイズ32')\n\n      page.item(:block_multiple18).value(\"サイズ18\\nサイズ18\")\n      page.item(:block_multiple24).style(:font_size, 24).value(\"サイズ24\\nサイズ24\")\n      page.item(:block_multiple32).style(:font_size, 32).value(\"サイズ32\\nサイズ32\")\n    end\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_character_spacing/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 21,\n      \"width\": 555.2,\n      \"height\": 40,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 10,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Times Roman Left\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 436,\n      \"y1\": 20,\n      \"x2\": 436,\n      \"y2\": 57\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 137,\n      \"width\": 555.2,\n      \"height\": 36,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 10,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"IPA明朝 左寄せ\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 351,\n      \"y1\": 136,\n      \"x2\": 351,\n      \"y2\": 173\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 260,\n      \"width\": 555.2,\n      \"height\": 38.5,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 10,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"IPA Pゴシック　左寄せ\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 487,\n      \"y1\": 262,\n      \"x2\": 487,\n      \"y2\": 299\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 70,\n      \"width\": 555.2,\n      \"height\": 40,\n      \"style\": {\n        \"font-family\": [\n          \"Times New Roman\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 10,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Times Roman Right\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 575,\n      \"y1\": 21,\n      \"x2\": 575.2,\n      \"y2\": 821.8\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 131,\n      \"y1\": 66,\n      \"x2\": 131,\n      \"y2\": 103\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 186.9,\n      \"width\": 555.2,\n      \"height\": 36,\n      \"style\": {\n        \"font-family\": [\n          \"IPAMincho\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 10,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"IPA明朝 右寄せ\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 247,\n      \"y1\": 185.9,\n      \"x2\": 247,\n      \"y2\": 222.9\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 316,\n      \"width\": 555.2,\n      \"height\": 38.5,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 36,\n        \"color\": \"#000000\",\n        \"text-align\": \"right\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": 10,\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"IPA Pゴシック　右寄せ\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#ff0000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 108,\n      \"y1\": 318,\n      \"x2\": 108,\n      \"y2\": 355\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 59.5\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 434.1\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 374.1\n      }\n    ]\n  },\n  \"title\": \"Character Spacing\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_character_spacing/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextCharacterSpacingFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_overflow_wrap/template.tlf",
    "content": "{\n  \"version\": \"0.12.0\",\n  \"items\": [\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 20,\n      \"width\": 191,\n      \"height\": 20,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"overflow-wrap: normal\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 230,\n      \"width\": 199.9,\n      \"height\": 20,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"overflow-wrap: anywhere\"\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 445,\n      \"width\": 353.8,\n      \"height\": 20,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"overflow-wrap: disable-break-word-by-space\"\n      ]\n    },\n    {\n      \"id\": \"normal\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 49,\n      \"width\": 243.6,\n      \"height\": 162,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 16,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\",\n        \"overflow-wrap\": \"normal\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"anywhere\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 261,\n      \"width\": 243.6,\n      \"height\": 162,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 16,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\",\n        \"overflow-wrap\": \"anywhere\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"disable_break_word_by_space\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 20,\n      \"y\": 481,\n      \"width\": 243.6,\n      \"height\": 162,\n      \"style\": {\n        \"font-family\": [\n          \"IPAPGothic\"\n        ],\n        \"font-size\": 16,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\",\n        \"overflow-wrap\": \"disable-break-word-by-space\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 20,\n      \"y1\": 41,\n      \"x2\": 263.6,\n      \"y2\": 41\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 20,\n      \"y1\": 253,\n      \"x2\": 263.6,\n      \"y2\": 253\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 20,\n      \"y1\": 470,\n      \"x2\": 263.6,\n      \"y2\": 470\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 263.6\n      }\n    ]\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}\n"
  },
  {
    "path": "test/basic_report/features/text_overflow_wrap/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextOverflowWrapFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    text = 'Thinreports is a PDF generation tool ' +\n           'that provides thinreports-editor and thinreports-generator. ' +\n           'Thinreports は thinreports-editor と thinreports-generator を提供するPDF 生成ツールです。'\n\n    report.page.values(\n      normal: text,\n      anywhere: text,\n      disable_break_word_by_space: text\n    )\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/features/text_word_wrap/template.tlf",
    "content": "{\n  \"version\": \"0.9.0\",\n  \"items\": [\n    {\n      \"id\": \"single_none\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 33.1,\n      \"y\": 101,\n      \"width\": 210.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"expand\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"multiple_none\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 290.2,\n      \"y\": 101.9,\n      \"width\": 259.1,\n      \"height\": 105.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"none\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 290.2,\n      \"y\": 101.9,\n      \"width\": 259.1,\n      \"height\": 105.1,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"multiple_break_word\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 290.2,\n      \"y\": 232.9,\n      \"width\": 259.1,\n      \"height\": 105.1,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": true,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 290.2,\n      \"y\": 232.9,\n      \"width\": 259.1,\n      \"height\": 105.1,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"line\",\n      \"display\": true,\n      \"description\": \"\",\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\"\n      },\n      \"x1\": 252,\n      \"y1\": 100,\n      \"x2\": 252,\n      \"y2\": 379.1\n    },\n    {\n      \"id\": \"single_break_word\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 35,\n      \"y\": 235,\n      \"width\": 210.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"expand\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"text\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 32.1,\n      \"y\": 33,\n      \"width\": 58,\n      \"height\": 20.5,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": []\n      },\n      \"texts\": [\n        \"Locale:\"\n      ]\n    },\n    {\n      \"id\": \"locale\",\n      \"type\": \"text-block\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 100,\n      \"y\": 36,\n      \"width\": 145.1,\n      \"height\": 17,\n      \"style\": {\n        \"font-family\": [\n          \"Helvetica\"\n        ],\n        \"font-size\": 18,\n        \"color\": \"#000000\",\n        \"text-align\": \"left\",\n        \"vertical-align\": \"top\",\n        \"line-height\": \"\",\n        \"line-height-ratio\": \"\",\n        \"letter-spacing\": \"\",\n        \"font-style\": [],\n        \"overflow\": \"truncate\",\n        \"word-wrap\": \"break-word\"\n      },\n      \"reference-id\": \"\",\n      \"value\": \"\",\n      \"multiple-line\": false,\n      \"format\": {\n        \"base\": \"\",\n        \"type\": \"\"\n      }\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 33.1,\n      \"y\": 101,\n      \"width\": 210.1,\n      \"height\": 17,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"rect\",\n      \"display\": true,\n      \"description\": \"\",\n      \"x\": 34.1,\n      \"y\": 235,\n      \"width\": 210.1,\n      \"height\": 17,\n      \"style\": {\n        \"border-color\": \"#000000\",\n        \"border-width\": 1,\n        \"border-style\": \"solid\",\n        \"fill-color\": \"none\"\n      },\n      \"border-radius\": 0\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": [\n      {\n        \"type\": \"x\",\n        \"position\": 59.5\n      },\n      {\n        \"type\": \"y\",\n        \"position\": 61\n      }\n    ]\n  },\n  \"title\": \"\",\n  \"report\": {\n    \"paper-type\": \"A4\",\n    \"orientation\": \"portrait\",\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  }\n}"
  },
  {
    "path": "test/basic_report/features/text_word_wrap/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestTextWordWrapFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    report = Thinreports::BasicReport::Report.new layout: template_path\n    report.start_new_page\n\n    report.page.item(:locale).value('ja')\n\n    text = 'Thinreports は Ruby 向けのオープンソース帳票・PDF ツールです。'\n    report.page.values single_none: text,\n                       single_break_word: text,\n                       multiple_none: text,\n                       multiple_break_word: text\n\n    report.start_new_page\n\n    report.page.item(:locale).value('en')\n\n    text = 'Thinreports is the OSS reporting tool for Ruby-lang.'\n    report.page.values single_none: text,\n                       single_break_word: text,\n                       multiple_none: text,\n                       multiple_break_word: text\n\n    assert_pdf report.generate\n  end\nend\n"
  },
  {
    "path": "test/basic_report/schema_helper.rb",
    "content": "# frozen_string_literal: true\n\nmodule Thinreports::BasicReport::SchemaHelper\n  BASIC_SCHEMA_JSON = <<-EOF\n  {\n    \"version\": \"%{version}\",\n    \"title\": \"Report Title\",\n    \"report\": {\n      \"paper-type\": \"A4\",\n      \"width\": 100.0,\n      \"height\": 200.0,\n      \"orientation\": \"landscape\",\n      \"margin\": [100.0, 200.0, 300.0, 999.9]\n    },\n    \"state\": {\n      \"layout-guides\": [\n        { \"type\": \"x\", \"position\": 0.1 }\n      ]\n    },\n    \"items\": [\n      {\n        \"type\": \"rect\",\n        \"id\": \"rect_with_id\",\n        \"display\": true,\n        \"description\": \"\",\n        \"x\": 20,\n        \"y\": 59,\n        \"width\": 120.1,\n        \"height\": 62,\n        \"style\": {\n          \"border-color\": \"#000000\",\n          \"border-width\": 1,\n          \"border-style\": \"solid\",\n          \"fill-color\": \"#FFFFFF\"\n        },\n        \"border-radius\": 0\n      },\n      { \"type\": \"text-block\", \"id\": \"text_block\", \"x\": 100.0, \"y\": 100.0, \"value\": \"\", \"display\": true },\n      { \"type\": \"text-block\", \"id\": \"text_block_referenced\", \"x\": 100.0, \"y\": 100.0, \"value\": \"\", \"display\": true, \"reference-id\": \"text_block\" },\n      { \"type\": \"text-block\", \"id\": \"text_block_hidden\", \"x\": 100.0, \"y\": 100.0, \"value\": \"default value\", \"display\": false },\n      { \"type\": \"image-block\", \"id\": \"image_block\", \"x\": 200.0, \"y\": 200.0, \"width\": 150.0, \"height\": 150.0, \"value\": \"\", \"display\": true },\n      {\n        \"type\": \"list\",\n        \"id\": \"default\",\n        \"x\": 1.0,\n        \"y\": 2.0,\n        \"display\": true,\n        \"width\": 200.0,\n        \"content-height\": 300,\n        \"auto-page-break\": true,\n        \"header\": {\n          \"enabled\": true,\n          \"height\": 10.0,\n          \"items\": []\n        },\n        \"detail\": {\n          \"height\": 70.0,\n          \"items\": [\n            { \"type\": \"text-block\", \"id\": \"name\", \"value\": \"\" }\n          ]\n        },\n        \"page-footer\": {\n          \"enabled\": true,\n          \"items\": [],\n          \"height\": 30.0\n        },\n        \"footer\": {\n          \"enabled\": true,\n          \"items\": [],\n          \"height\": 40.0\n        }\n      }\n    ]\n  }\nEOF\n\n  LIST_NO_HEADER_SCHEMA_JSON = <<-EOF\n  {\n    \"version\": \"%{version}\",\n    \"title\": \"Report Title\",\n    \"report\": {\n      \"paper-type\": \"A4\",\n      \"width\": 100.0,\n      \"height\": 200.0,\n      \"orientation\": \"landscape\",\n      \"margin\": [100.0, 200.0, 300.0, 999.9]\n    },\n    \"state\": {\n      \"layout-guides\": []\n    },\n    \"items\": [\n      {\n        \"type\": \"list\",\n        \"id\": \"default\",\n        \"x\": 1.0,\n        \"y\": 2.0,\n        \"display\": true,\n        \"header\": {\n          \"enabled\": false,\n          \"height\": 10.0,\n          \"items\": []\n        },\n        \"width\": 200.0,\n        \"content-height\": 300,\n        \"auto-page-break\": true,\n        \"detail\": {\n          \"height\": 20.0,\n          \"items\": [\n            { \"type\": \"text-block\", \"id\": \"name\", \"value\": \"\" }\n          ]\n        },\n        \"page-footer\": {\n          \"enabled\": true,\n          \"items\": [],\n          \"height\": 30.0\n        },\n        \"footer\": {\n          \"enabled\": true,\n          \"items\": [],\n          \"height\": 40.0\n        }\n      }\n    ]\n  }\nEOF\n\n  def layout_file(options = {})\n    schema_version = options[:version] || Thinreports::VERSION\n    schema_json = options[:schema] || BASIC_SCHEMA_JSON\n\n    Tempfile.open %w( test-thinreports-layout .tlf ) do |file|\n      file.puts (schema_json % { version: schema_version })\n      file\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/test_helper.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'minitest/autorun'\nrequire 'minitest/spec'\nrequire 'minitest/unit'\nrequire 'mocha/minitest'\nrequire 'pdf/inspector'\n\nrequire 'digest/sha1'\nrequire 'pathname'\nrequire 'thinreports'\n\nrequire 'schema_helper'\nrequire 'feature_test'\n\nMocha.configure do |c|\n  c.strict_keyword_argument_matching = true\nend\n\nmodule Thinreports\n  module BasicReport\n    module TestHelper\n      ROOT = Pathname.new(File.expand_path('..', __FILE__))\n\n      include SchemaHelper\n\n      def assert_deprecated(&block)\n        _out, err = capture_io { block.call }\n        assert err.to_s.include?('[DEPRECATION]')\n      end\n\n      def data_file(*paths)\n        ROOT.join('data', *paths).to_s\n      end\n\n      def read_data_file(*paths)\n        File.read(data_file(*paths))\n      end\n\n      def analyze_pdf_images(pdf_data)\n        analyzer = PDF::Inspector::XObject.analyze(pdf_data)\n        analyzer.page_xobjects\n          .reduce(:merge).values\n          .select { |o| o.hash[:Subtype] == :Image }\n      end\n\n      def assert_pdf_data(data)\n        assert_equal '%PDF-', data[0..4]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/format/test_base.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Format::BaseTest < Minitest::Test\n  TEST_FORMAT_CONFIG = {\n    'c1' => 'c1',\n    'c2' => {\n      'c2_1' => 'c2_1'\n    },\n    'c3' => {\n      'c3_1' => {\n        'c3_1_1' => 'c3_1_1',\n        'c3_1_2' => 'c3_1_2'\n      }\n    },\n    'c4' => 'c4',\n    'c5' => 'c5',\n    'c6' => 9999,\n    'c7' => true,\n    'c8' => false,\n    'c9' => {\n      'c9_1' => true,\n      'c9_2' => false\n    },\n    'c10' => 'c10',\n    'c11' => {\n      'c11_1' => 'c11_1'\n    },\n    'c20' => 'c20',\n    'c21' => 'c21'\n  }\n\n  class TestFormat < Thinreports::BasicReport::Core::Format::Base\n    # For testing\n    attr_reader :config\n\n    # Basic methods\n    config_reader :c1\n    config_reader c2_1: %w( c2 c2_1 ),\n                  c3_1_1: %w( c3 c3_1 c3_1_1 )\n    config_reader :c4, :c5\n    config_reader 'c6'\n\n    # Alias methods\n    config_reader c1_alias: %w( c1 ),\n                  c2_1_alias: %w( c2 c2_1 )\n\n    # Invalid methods\n    config_reader c3_invalid: %w( c3 c3_1 not_exist_key )\n\n    # Customized methods\n    config_reader c2_1_customized: %w( c2 c2_1 ) do |val|\n      \"Customized #{val}\"\n    end\n\n    # Checker methods\n    config_checker true, :c7, :c8\n    config_checker true, c9_1: %w( c9 c9_1 ),\n                         c9_2: %w( c9 c9_2 )\n\n    # Writer methods\n    config_writer :c10\n    config_writer c10_alias: %w( c10 )\n    config_writer c11_1: %w( c11 c11_1 )\n    # Writer for not exist config on default\n    config_writer c11_2: %w( c11 c11_2 )\n\n    # Accessor methods\n    config_accessor :c20\n    config_accessor :c21 do |val|\n      \"Customized #{val}\"\n    end\n  end\n\n  def setup\n    @format = TestFormat.new(TEST_FORMAT_CONFIG)\n  end\n\n  def test_definition_of_all_config_methods\n    methods = [:c1, :c2_1, :c3_1_1, :c4, :c5, :c6,\n               :c1_alias, :c2_1_alias,\n               :c3_invalid,\n               :c2_1_customized,\n               :c7?, :c8?, :c9_1?, :c9_2?,\n               :c10=, :c10_alias=, :c11_1=, :c11_2=,\n               :c20, :c20=, :c21, :c21=]\n    assert methods.all? {|m| TestFormat.method_defined?(m) }\n  end\n\n  def test_readers\n    # Basic\n    assert_equal @format.c1, 'c1'\n    assert_equal @format.c2_1, 'c2_1'\n    assert_equal @format.c3_1_1, 'c3_1_1'\n    assert_equal @format.c4, 'c4'\n    assert_equal @format.c5, 'c5'\n    assert_equal @format.c6, 9999\n    # Alias\n    assert_equal @format.c1_alias, @format.c1\n    assert_equal @format.c2_1_alias, @format.c2_1\n    # Invalid location\n    assert_nil @format.c3_invalid\n    # Customized\n    assert_equal @format.c2_1_customized, 'Customized c2_1'\n  end\n\n  def test_checkers\n    assert_equal @format.c7?, true\n    assert_equal @format.c8?, false\n    assert_equal @format.c9_1?, true\n    assert_equal @format.c9_2?, false\n  end\n\n  def test_reader_cannot_write_value\n    assert_raises NoMethodError do\n      @format.c1 = 'write'\n    end\n    # Alias method\n    assert_raises NoMethodError do\n      @format.c1_alias = 'write'\n    end\n  end\n\n  def test_writers\n    config = @format.config\n\n    @format.c10 = 'c1_changed'\n    assert_equal config['c10'], 'c1_changed'\n\n    @format.c10_alias = 'c10_changed_by_alias'\n    assert_equal config['c10'], 'c10_changed_by_alias'\n\n    @format.c11_1 = 'c11_1_changed'\n    assert_equal config['c11']['c11_1'], 'c11_1_changed'\n\n    @format.c11_2 = 'c11_2_created'\n    assert_equal config['c11']['c11_2'], 'c11_2_created'\n  end\n\n  def test_accessors\n    @format.c20 = 'c20_changed'\n    assert_equal @format.c20, 'c20_changed'\n\n    @format.c21 = 'c21_changed'\n    assert_equal @format.c21, 'Customized c21_changed'\n  end\n\n  def test_attributes\n    assert_same @format.config, @format.attributes\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/base/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Base::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def setup\n    @report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    @report.start_new_page\n  end\n\n  def create_internal(format_config = {}, &block)\n    format =\n      unless format_config.empty?\n        format_klass = Class.new(Thinreports::BasicReport::Core::Shape::Basic::Format) {\n          config_reader(*format_config.keys.map {|k| k.to_sym })\n        }\n        format_klass.new(format_config)\n      else\n        Thinreports::BasicReport::Core::Shape::Basic::Format.new({})\n      end\n\n    klass = Class.new(Thinreports::BasicReport::Core::Shape::Base::Internal, &block)\n    klass.new(@report.page, format)\n  end\n\n  def test_self_format_delegators_should_defines_method_delegated_from_format\n    internal = create_internal('m1' => 'm1_value') {\n      format_delegators :m1\n    }\n    assert_respond_to internal, :m1\n  end\n\n  def test_method_delegated_from_format_should_return_same_value_as_an_format\n    internal = create_internal('m1' => 'm1 value') {\n      format_delegators :m1\n    }\n    assert_same internal.m1, internal.format.m1\n  end\n\n  def test_copied_internal_should_have_the_new_value_specified_as_a_parent_property\n    new_page = @report.start_new_page\n    internal = create_internal {\n      def style\n        @style ||= Thinreports::BasicReport::Core::Shape::Style::Base.new(format)\n      end\n    }\n\n    assert_same internal.copy(new_page).parent, new_page\n  end\n\n  def test_copied_internal_should_have_style_copied_from_original\n    internal = create_internal {\n      def style\n        @style ||= Thinreports::BasicReport::Core::Shape::Style::Base.new(format)\n      end\n    }\n    internal.style.write_internal_style(:foo, 'bar')\n    new_internal = internal.copy(@report.start_new_page)\n\n    assert_equal new_internal.style.read_internal_style(:foo), 'bar'\n  end\n\n  def test_copied_internal_should_have_states_property_copied_from_original\n    internal = create_internal {\n      def style\n        @style ||= Thinreports::BasicReport::Core::Shape::Style::Base.new(format)\n      end\n    }\n    internal.states[:foo] = 'bar'\n    new_internal = internal.copy(@report.start_new_page)\n\n    assert_equal new_internal.states[:foo], 'bar'\n  end\n\n  def test_copy_should_execute_block_with_new_internal_as_argument\n    internal = create_internal {\n      def style\n        @style ||= Thinreports::BasicReport::Core::Shape::Style::Base.new(format)\n      end\n    }\n    internal.copy(@report.start_new_page) do |new_internal|\n      assert_equal new_internal.is_a?(Thinreports::BasicReport::Core::Shape::Base::Internal), true\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/basic/test_block_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Basic::TestBlockFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  BLOCK_FORMAT = {\n    'value' => 'default value',\n    'x' => 100.0,\n    'y' => 200.0,\n    'width' => 300.0,\n    'height' => 400.0\n  }\n\n  Basic = Thinreports::BasicReport::Core::Shape::Basic\n\n  def test_attribute_readers\n    format = Basic::BlockFormat.new(BLOCK_FORMAT)\n\n    assert_equal 'default value', format.value\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/basic/test_block_interface.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Basic::TestBlockInterface < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Basic = Thinreports::BasicReport::Core::Shape::Basic\n\n  def setup\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    parent = report.start_new_page\n\n    format = Basic::BlockFormat.new({})\n    internal = Basic::BlockInternal.new parent, format\n\n    @interface = Basic::BlockInterface.new parent, format, internal\n  end\n\n  def test_value_should_work_as_reader_with_no_arguments\n    @interface.internal.write_value('new value')\n    assert_equal @interface.value, 'new value'\n  end\n\n  def test_value_should_work_as_writer_with_arguments\n    @interface.value('new value')\n    assert_equal @interface.internal.read_value, 'new value'\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/basic/test_block_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Basic::TestBlockInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Basic = Thinreports::BasicReport::Core::Shape::Basic\n\n  def test_read_value_should_return_value_from_format\n    internal = init_internal('value' => 'default value')\n    assert_equal internal.read_value, 'default value'\n  end\n\n  def test_read_value_should_return_value_from_state_with_value_key\n    internal = init_internal\n    internal.states[:value] = 'new value'\n    assert_equal internal.read_value, 'new value'\n  end\n\n  def test_real_value_should_return_the_same_value_as_a_read_value_method\n    internal = init_internal\n    internal.states[:value] = 'foo'\n    assert_same internal.real_value, internal.read_value\n  end\n\n  def test_write_value_should_save_value_to_states_store_as_value\n    internal = init_internal\n    internal.write_value('new value')\n    assert_equal internal.states[:value], 'new value'\n  end\n\n  def test_type_of_asker_should_return_true_when_given_the_block_value\n    assert_equal init_internal.type_of?(:block), true\n  end\n\n  def test_value_should_works_the_same_as_read_value_method\n    internal = init_internal\n    internal.write_value('new value')\n    assert_same internal.read_value, internal.value\n  end\n\n  def test_type_of_asker_should_return_false_otherwise\n    assert_equal %w( image-block text-block text list ).all? {|t| !init_internal.type_of?(t)}, true\n  end\n\n  private\n\n  def init_internal(format = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    parent = report.start_new_page\n\n    Basic::BlockInternal.new(parent, Basic::BlockFormat.new(format))\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/basic/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Basic::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  RECT_FORMAT = {\n    \"id\" => \"\",\n    \"type\" => \"rect\",\n    \"x\" => 100.0,\n    \"y\" => 200.0,\n    \"width\" => 300.0,\n    \"height\" => 400.0,\n    \"description\" => \"Description for rect\",\n    \"display\" => true,\n    \"rx\" => 1.0,\n    \"ry\" => 1.0,\n    \"style\" => {\n      \"border-width\" => 1,\n      \"border-color\" => \"#000000\",\n      \"border-style\" => \"dashed\",\n      \"fill-color\" => \"#ff0000\"\n    }\n  }\n\n  Basic = Thinreports::BasicReport::Core::Shape::Basic\n\n  def test_attribute_readers\n    format = Basic::Format.new(RECT_FORMAT)\n\n    assert_equal '', format.id\n    assert_equal 'rect', format.type\n    assert_equal RECT_FORMAT['style'], format.style\n    assert_equal true, format.display?\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/basic/test_interface.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Basic::TestInterface < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Basic = Thinreports::BasicReport::Core::Shape::Basic\n\n  def create_interface(format_config = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    parent = report.start_new_page\n\n    Basic::Interface.new parent, Basic::Format.new(format_config)\n  end\n\n  def test_id_should_return_id_with_reference_to_internal\n    basic = create_interface('id' => 'foo')\n    assert_equal basic.id, basic.internal.id\n  end\n\n  def test_id_should_return_cloned_id\n    basic = create_interface('id' => 'basic-id')\n    refute_same basic.id, basic.internal.id\n  end\n\n  def test_type_should_operate_as_delegator_of_internal\n    basic = create_interface('type' => 'rect')\n    assert_same basic.type, basic.internal.type\n  end\n\n  def test_visible_asker_should_return_result_with_reference_to_style_of_internal\n    basic = create_interface('display' => false)\n    assert_equal basic.visible?, basic.internal.style.visible\n  end\n\n  def test_visible_should_properly_set_visibility_to_style_of_internal\n    basic = create_interface('display' => false)\n    basic.visible(true)\n\n    assert_equal basic.internal.style.visible, true\n  end\n\n  def test_style_should_operate_as_reader_when_one_argument_is_given\n    basic = create_interface('style' => { 'fill-color' => '#ff0000' })\n\n    assert_equal basic.style(:fill_color), '#ff0000'\n  end\n\n  def test_style_should_operate_as_writer_when_two_arguments_are_given\n    basic = create_interface\n    basic.style(:border_color, '#000000')\n\n    assert_equal basic.style(:border_color), '#000000'\n  end\n\n  def test_style_should_operate_as_writer_for_border_style_when_three_arguments_are_given\n    basic = create_interface\n    basic.style(:border, 1, '#ffffff')\n\n    assert_equal basic.style(:border), [1, '#ffffff']\n  end\n\n  def test_style_should_return_self_when_two_arguments_are_given\n    assert_instance_of Basic::Interface, create_interface.style(:border_width, 1)\n  end\n\n  def test_style_should_return_self_when_three_arguments_are_given\n    assert_instance_of Basic::Interface, create_interface.style(:border, 1, '#000000')\n  end\n\n  def test_styles_should_properly_set_the_specified_styles_as_Hash\n    basic = create_interface\n    basic.styles(fill_color: '#ff0000',\n                 border_color: '#000000',\n                 border_width: 5,\n                 visible: false)\n\n    assert_equal [basic.style(:fill_color),\n                  basic.style(:border_color),\n                  basic.style(:border_width),\n                  basic.style(:visible)],\n                 ['#ff0000', '#000000', 5, false]\n  end\n\n  def test_hide_should_properly_set_false_to_visibility\n    basic = create_interface\n    basic.hide\n\n    assert_equal basic.visible?, false\n  end\n\n  def test_hide_should_return_self\n    assert_instance_of Basic::Interface, create_interface.hide\n  end\n\n  def test_show_should_properly_set_true_to_visibility\n    basic = create_interface\n    basic.show\n\n    assert_equal basic.visible?, true\n  end\n\n  def test_show_should_return_self\n    assert_instance_of Basic::Interface, create_interface.show\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/basic/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Basic::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Basic = Thinreports::BasicReport::Core::Shape::Basic\n\n  def create_internal(format_config = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n\n    Basic::Internal.new report.page, Basic::Format.new(format_config)\n  end\n\n  def test_id_should_operate_as_delegator_of_format\n    basic = create_internal('id' => 'basic-id')\n    assert_same basic.id, basic.format.id\n  end\n\n  def test_type_should_operate_as_delegator_of_format\n    basic = create_internal('type' => 'ellipse')\n    assert_same basic.type, basic.format.type\n  end\n\n  def test_style_should_return_instance_of_StyleGraphic\n    assert_instance_of Thinreports::BasicReport::Core::Shape::Style::Graphic,\n                       create_internal.style\n  end\n\n  def test_type_of_asker_should_already_return_true_when_the_specified_type_is_basic\n    assert_equal create_internal.type_of?(:basic), true\n  end\n\n  def test_type_of_asker_should_return_true_when_the_specified_type_equal_self_type_name\n    result = []\n\n    result << create_internal('type' => 'rect').type_of?('rect')\n    result << create_internal('type' => 'ellipse').type_of?('ellipse')\n    result << create_internal('type' => 'line').type_of?('line')\n    result << create_internal('type' => 'image').type_of?('image')\n\n    assert_equal result.all?, true\n  end\n\n  def test_identifier\n    basic = create_internal 'id' => 'basic-id'\n\n    assert_equal 'basic-id', basic.identifier\n\n    basic.style.stubs(identifier: 'style-identifier')\n    assert_equal basic.identifier, 'basic-idstyle-identifier'\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/image_block/test_interface.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::ImageBlock::TestInterface < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  ImageBlock = Thinreports::BasicReport::Core::Shape::ImageBlock\n\n  def setup\n    @report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    @page = @report.start_new_page\n  end\n\n  def test_src\n    @page.item(:image_block).src('/path/to/image.png')\n    assert_equal '/path/to/image.png', @page.item(:image_block).src\n  end\n\n  def test_src=\n    @page.item(:image_block).src = '/path/to/image.png'\n    assert_equal '/path/to/image.png', @page.item(:image_block).src\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/image_block/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::ImageBlock::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  ImageBlock = Thinreports::BasicReport::Core::Shape::ImageBlock\n\n  def test_src_should_return_the_same_value_as_value_method\n    internal = create_internal\n    internal.write_value('/path/to/image.png')\n\n    assert_same internal.src, internal.read_value\n  end\n\n  def test_type_of_asker_should_return_true_when_iblock_value_is_given\n    assert_equal create_internal.type_of?('image-block'), true\n  end\n\n  def test_type_of_asker_should_return_true_when_block_value_is_given\n    assert_equal create_internal.type_of?(:block), true\n  end\n\n  def create_internal\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    parent = report.start_new_page\n\n    ImageBlock::Internal.new parent, ImageBlock::Format.new({})\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  LIST_FORMAT = {\n    'type' => 'list',\n    'id' => 'list',\n    'display' => true,\n    'x' => 10.0,\n    'y' => 20.0,\n    'width' => 30.0,\n    'height' => 40.0,\n    'content-height' => 255,\n    'auto-page-break' => true,\n    'header' => {\n      'enabled' => true,\n      'height' => 10.0,\n      'translate' => { 'x' => 210.0, 'y' => 310.0 },\n      'items' => []\n    },\n    'detail' => {\n      'height' => 20.0,\n      'translate' => { 'x' => 220.0, 'y' => 320.0 },\n      'items' => []\n    },\n    'page-footer' => {\n      'enabled' => true,\n      'height' => 30.0,\n      'translate' => { 'x' => 230.0, 'y' => 330.0 },\n      'items' => []\n    },\n    'footer' => {\n      'enabled' => false,\n      'height' => 40.0,\n      'translate' => { 'x' => 240.0, 'y' => 340.0 },\n      'items' => []\n    }\n  }\n\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  def test_has_section?\n    format = List::Format.new(LIST_FORMAT)\n\n    assert_equal true, format.has_section?(:detail)\n    assert_equal true, format.has_section?(:page_footer)\n    assert_equal false, format.has_section?(:footer)\n  end\n\n  def test_section_height\n    format = List::Format.new(LIST_FORMAT)\n\n    assert_equal 10.0, format.section_height(:header)\n  end\n\n  def test_attribute_readers\n    format = List::Format.new(LIST_FORMAT)\n\n    assert_equal 255, format.height\n    assert_equal true, format.auto_page_break?\n    assert_equal true, format.has_header?\n    assert_equal true, format.has_page_footer?\n    assert_equal false, format.has_footer?\n    assert_equal 20.0, format.detail_height\n    assert_equal 30.0, format.page_footer_height\n    assert_equal 40.0, format.footer_height\n    assert_equal 10.0, format.header_height\n  end\n\n  def test_section_base_position_top\n    page_footer_disabled = LIST_FORMAT\n\n    format = List::Format.new(page_footer_disabled)\n    assert_equal 310.0, format.section_base_position_top(:header)\n    assert_equal 320.0, format.section_base_position_top(:detail)\n    assert_equal 310.0, format.section_base_position_top(:page_footer)\n    assert_equal 0, format.section_base_position_top(:footer)\n\n    format_footer_enabled = format_section_enabled(true, 'footer', LIST_FORMAT)\n\n    format = List::Format.new(format_footer_enabled)\n    assert_equal 290.0, format.section_base_position_top(:footer)\n\n    format_footer_enabld_and_page_footer_disabled = format_section_enabled(false, 'page-footer', format_footer_enabled)\n\n    format = List::Format.new(format_footer_enabld_and_page_footer_disabled)\n    assert_equal 320.0, format.section_base_position_top(:footer)\n  end\n\n  def test_initialize_sections\n    format = List::Format.new(LIST_FORMAT)\n\n    assert_instance_of List::SectionFormat, format.sections[:header]\n    assert_instance_of List::SectionFormat, format.sections[:detail]\n    assert_instance_of List::SectionFormat, format.sections[:page_footer]\n\n    assert_nil format.sections[:footer]\n  end\n\n  private\n\n  def format_section_enabled(enable, section, list_format)\n    section_format = list_format[section].dup\n    section_format['enabled'] = enable\n\n    list_format.merge(section => section_format)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_manager.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestManager < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  def create_report(&block)\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    block.call(report) if block_given?\n    report\n  end\n\n  def list_manager\n    report = create_report {|r| r.start_new_page }\n    report.page.list.manager\n  end\n\n  def test_current_page_should_return_the_instance_of_ListPage\n    assert_instance_of List::Page, list_manager.current_page\n  end\n\n  def test_current_page_state_should_return_the_instance_of_ListPageState\n    assert_instance_of List::PageState, list_manager.current_page_state\n  end\n\n  def test_switch_current_should_replace_own_current_page_property_by_the_given_page\n    report = create_report {|r| r.start_new_page }\n    list = report.page.list\n    new_page = List::Page.new(report.page, list.internal.format)\n\n    list.manager.switch_current!(new_page)\n\n    assert_same list.manager.current_page, new_page\n  end\n\n  def test_switch_current_should_replace_own_current_page_state_property_by_internal_property_of_the_given_page\n    report = create_report {|r| r.start_new_page }\n    list = report.page.list\n    new_page = List::Page.new(report.page, list.internal.format)\n\n    list.manager.switch_current!(new_page)\n\n    assert_same list.manager.current_page_state, new_page.internal\n  end\n\n  def test_switch_current_should_return_the_self\n    report = create_report {|r| r.start_new_page }\n    list = report.page.list\n    new_page = List::Page.new(report.page, list.internal.format)\n\n    assert_same list.manager.switch_current!(new_page), list.manager\n  end\n\n  def test_page_count\n    report = create_report\n    assert_equal report.page_count, 0\n\n    report.list.page_break\n    report.list.page_break\n\n    assert_equal report.list.manager.page_count, 2\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_page.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestPage < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  LIST_SCHEMA = {\n    'type' => 'list',\n    'id' => 'list',\n    'display' => true,\n    'x' => 10.0,\n    'y' => 20.0,\n    'width' => 30.0,\n    'height' => 40.0,\n    'content-height' => 255,\n    'auto-page-break' => true,\n    'header' => {\n      'enabled' => true,\n      'height' => 10.0,\n      'translate' => { 'x' => 210.0, 'y' => 310.0 },\n      'items' => []\n    },\n    'detail' => {\n      'height' => 20.0,\n      'translate' => { 'x' => 220.0, 'y' => 320.0 },\n      'items' => []\n    },\n    'page-footer' => {\n      'enabled' => false,\n      'height' => 30.0,\n      'translate' => { 'x' => 230.0, 'y' => 330.0 },\n      'items' => []\n    },\n    'footer' => {\n      'enabled' => false,\n      'height' => 40.0,\n      'translate' => { 'x' => 240.0, 'y' => 340.0 },\n      'items' => []\n    }\n  }\n\n  def create_report(&block)\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    block.call(report) if block_given?\n    report\n  end\n\n  def test_on_page_finalize_callback\n    report = create_report\n    list = report.list\n\n    counter = 0\n    callback = -> { counter += 1 }\n\n    list.on_page_finalize(&callback)\n\n    5.times { list.add_row }\n    assert_equal 1, counter\n\n    report.finalize\n    assert_equal 2, counter\n  end\n\n  def test_on_page_footer_insert_callback\n    report = create_report\n    list = report.list\n\n    tester = 0\n    callback = -> footer {\n      assert_instance_of List::SectionInterface, footer\n      assert_equal footer.internal.section_name, :page_footer\n\n      tester += 1\n    }\n\n    list.on_page_footer_insert(&callback)\n\n    5.times { list.add_row }\n    assert_equal 1, tester\n\n    report.finalize\n    assert_equal 2, tester\n  end\n\n  def test_on_footer_insert_callback\n    report = create_report\n    list = report.list\n\n    tester = 0\n    callback = -> footer {\n      assert_instance_of List::SectionInterface, footer\n      assert_equal footer.internal.section_name, :footer\n\n      tester += 1\n    }\n\n    list.on_footer_insert(&callback)\n\n    5.times { list.add_row }\n    assert_equal 0, tester\n\n    report.finalize\n    assert_equal 1, tester\n  end\n\n  def test_copy_should_properly_work_when_list_has_not_header\n    report = Thinreports::BasicReport::Report.new layout: layout_file(schema: LIST_NO_HEADER_SCHEMA_JSON).path\n\n    10.times { report.list.add_row }\n  rescue => e\n    flunk exception_details(e, 'Not worked when list has not header')\n  end\n\n  def test_copy_when_auto_page_break_disabled\n    list_schema = LIST_SCHEMA.merge('auto-page-break' => false)\n\n    report = Thinreports::BasicReport::Report::Base.new\n    layout = Thinreports::BasicReport::Layout::Base.new(layout_file.path)\n\n    list_format = Thinreports::BasicReport::Core::Shape::List::Format.new(list_schema)\n\n    list_page = List::Page.new(report.page, list_format)\n\n    2.times { list_page.add_row }\n\n    copied_list_page = list_page.copy(Thinreports::BasicReport::Report::Page.new(report, layout))\n\n    assert list_page.manager.finalized?\n    assert copied_list_page.manager.finalized?\n    assert_equal 2, copied_list_page.internal.rows.count\n  end\n\n  def test_copy_when_auto_page_break_enabled\n    list_schema = LIST_SCHEMA.merge('auto-page-break' => true)\n\n    report = Thinreports::BasicReport::Report::Base.new\n    layout = Thinreports::BasicReport::Layout::Base.new(layout_file.path)\n\n    list_format = Thinreports::BasicReport::Core::Shape::List::Format.new(list_schema)\n\n    list_page = List::Page.new(report.page, list_format)\n\n    2.times { list_page.add_row }\n    list_page.manager.finalize_page\n\n    copied_list_page = list_page.copy(Thinreports::BasicReport::Report::Page.new(report, layout))\n\n    refute list_page.manager.finalized?\n    refute copied_list_page.manager.finalized?\n    assert_empty copied_list_page.internal.rows\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_page_state.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestPageState < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  def setup\n    parent = mock('parent')\n    format = mock('format')\n\n    @state = List::PageState.new(parent, format)\n  end\n\n  def test_alias_class\n    assert_same List::PageState, List::Internal\n  end\n\n  def test_type_of?\n    assert_equal @state.type_of?('list'), true\n  end\n\n  def test_finalized!\n    assert_equal @state.finalized?, false\n    @state.finalized!\n    assert_equal @state.finalized?, true\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_section_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestSectionFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  LIST_SECTION_FORMAT = {\n    'enabled' => true,\n    'height' => 47.7,\n    'translate' => { 'x' => 0, 'y' => -64.2 },\n    'items' => [\n      { 'type' => 'rect', 'id' => '' },\n      { 'type' => 'text-block', 'id' => 'text_block' }\n    ]\n  }\n\n  Shape = Thinreports::BasicReport::Core::Shape\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  def test_attribute_readers\n    format = List::SectionFormat.new(LIST_SECTION_FORMAT)\n\n    assert_equal 47.7, format.height\n    assert_equal 0, format.relative_left\n    assert_equal(-64.2, format.relative_top)\n    assert_equal true, format.display?\n  end\n\n  def test_initialize_items\n    format = List::SectionFormat.new(LIST_SECTION_FORMAT)\n\n    assert_equal 1, format.shapes.count\n    assert_instance_of Shape::TextBlock::Format, format.shapes[:text_block]\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_section_interface.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestSectionInterface < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  BASIC_SECTION_SCHEMA = {\n    'height' => 1.0,\n    'enabled' => true,\n    'items' => []\n  }\n\n  # Alias\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  def setup\n    @report = Thinreports::BasicReport::Report.new layout: layout_file.path\n  end\n\n  def create_interface(extra_section_schema = {})\n    parent = @report.start_new_page\n\n    List::SectionInterface.new(\n      parent,\n      List::SectionFormat.new(BASIC_SECTION_SCHEMA.merge(extra_section_schema)),\n      :section\n    )\n  end\n\n  def test_internal_should_return_instance_of_SectionInternal\n    assert_instance_of List::SectionInternal, create_interface.internal\n  end\n\n  def test_initialize_should_properly_set_the_specified_section_name_to_internal\n    assert_equal create_interface.internal.section_name, :section\n  end\n\n  def test_initialize_should_properly_initialize_manager\n    assert_instance_of Thinreports::BasicReport::Core::Shape::Manager::Internal,\n                       create_interface.manager\n  end\n\n  def test_height_should_operate_as_delegator_of_internal\n    list = create_interface('height' => 100)\n    assert_same list.height, list.internal.height\n  end\n\n  def test_copied_interface_should_succeed_an_section_name_of_original\n    list = create_interface\n    new_parent = @report.start_new_page\n\n    assert_same list.copy(new_parent).internal.section_name,\n                list.internal.section_name\n  end\n\n  def test_copied_interface_should_have_all_the_copies_of_Shape_which_original_holds\n    list = create_interface\n    copied_list(list) do |new_list|\n      assert_equal new_list.manager.shapes.size, 3\n    end\n  end\n\n  def copied_list(list, &block)\n    tblock = Thinreports::BasicReport::Core::Shape::TextBlock\n    new_parent = @report.start_new_page\n\n    %w( foo bar hoge ).each do |id|\n      list.manager.format.shapes[id.to_sym] = tblock::Format.new('type' => 'text-block', 'id' => id)\n      list.item(id).value(10)\n    end\n\n    block.call(list.copy(new_parent))\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/list/test_section_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::List::TestSectionInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  BASIC_SECTION_SCHEMA = {\n    'height' => 1.0,\n    'enabled' => true,\n    'items' => []\n  }\n\n  # Alias\n  List = Thinreports::BasicReport::Core::Shape::List\n\n  def create_internal(extra_section_schema = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n\n    List::SectionInternal.new(\n      report,\n      List::SectionFormat.new(BASIC_SECTION_SCHEMA.merge(extra_section_schema))\n    )\n  end\n\n  def test_height_should_operate_as_delegator_of_format\n    list = create_internal('height' => 100)\n    assert_same list.height, list.format.height\n  end\n\n  def test_relative_left_should_operate_as_delegator_of_format\n    list = create_internal('translate' => {'x' => 10})\n    assert_same list.relative_left, list.format.relative_left\n  end\n\n  def test_move_top_to_should_properly_set_value_to_states_as_relative_top\n    list = create_internal\n    list.move_top_to(200)\n\n    assert_equal list.states[:relative_top], 200\n  end\n\n  def test_relative_top\n    list = create_internal('translate' => { 'y' => 100 })\n    assert_equal 0, list.relative_top\n\n    list.move_top_to 50\n    assert_equal 50, list.relative_top\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/manager/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Manager::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  class TestFormat < Thinreports::BasicReport::Core::Shape::Manager::Format; end\n\n  def test_identifier_should_return_the_same_as_object_id_when_id_is_not_given\n    format = TestFormat.new({})\n    assert_equal format.identifier, format.object_id\n  end\n\n  def test_identifier_should_return_the_specified_id_when_id_is_given\n    assert_equal TestFormat.new({}, :any_id).identifier, :any_id\n  end\n\n  def test_has_shape\n    format = TestFormat.new({}) do |f|\n      f.shapes[:foo] = 1\n    end\n    assert format.has_shape?(:foo)\n    refute format.has_shape?(:unknown)\n  end\n\n  def test_find_shape_should_return_format_of_shape_when_shape_is_found\n    format = TestFormat.new({}) do |f|\n      f.shapes[:foo] = Thinreports::BasicReport::Core::Shape::TextBlock::Format.new('id' => 'foo',\n                                                                       'type' => 'text-block')\n    end\n    assert_equal format.find_shape(:foo).id, 'foo'\n  end\n\n  def test_find_shape_should_return_nil_when_shape_is_not_found\n    assert_nil TestFormat.new({}).find_shape(:unknown)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/manager/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Manager::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Shape = Thinreports::BasicReport::Core::Shape\n\n  def create_shape_format(type, id, other_config = {})\n    Shape::Format(type).new({'id' => id,\n                             'type' => type,\n                             'display' => true}.merge(other_config))\n  end\n\n  def create_internal(&block)\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    format = report.layout.format\n\n    block.call(format) if block_given?\n\n    report.start_new_page.manager\n  end\n\n  def test_find_format_should_return_format_with_the_specified_Symbol_id\n    assert_equal create_internal.find_format(:text_block).id, 'text_block'\n  end\n\n  def test_find_format_should_return_format_with_the_specified_String_id\n    assert_equal create_internal.find_format('text_block').id, 'text_block'\n  end\n\n  def test_find_format_should_return_nil_when_format_with_specified_id_is_not_found\n    assert_nil create_internal.find_format(:unknown)\n  end\n\n  def test_find_item_should_return_shape_with_the_specified_id\n    assert_instance_of Shape::TextBlock::Interface, create_internal.find_item(:text_block)\n  end\n\n  def test_find_item_should_return_shape_in_shapes_registry_when_the_specified_shape_exists_in_registry\n    internal = create_internal\n    internal.find_item(:text_block)\n\n    assert_same internal.find_item(:text_block), internal.shapes[:text_block]\n  end\n\n  def test_find_item_should_return_shape_when_passing_in_the_specified_only_filter\n    internal = create_internal\n    assert_equal internal.find_item(:text_block, only: 'text-block').id, 'text_block'\n  end\n\n  def test_find_item_should_return_nil_when_not_passing_in_the_specified_only_filter\n    internal = create_internal\n    assert_nil internal.find_item(:text_block, only: 'list')\n  end\n\n  def test_find_item_should_return_shape_when_passing_in_the_specified_except_filter\n    internal = create_internal\n    assert_equal internal.find_item(:default, except: 'text-block').id, 'default'\n  end\n\n  def test_find_item_should_return_shape_when_not_passing_in_the_specified_except_filter\n    internal = create_internal\n    assert_nil internal.find_item(:default, except: 'list')\n  end\n\n  def test_final_shape_should_return_nil_when_shape_is_not_found\n    internal = create_internal\n    assert_nil internal.final_shape(:unknown)\n  end\n\n  def test_final_shape_should_return_nil_when_shape_is_stored_in_shapes_and_hidden\n    internal = create_internal\n    internal.find_item(:text_block).hide\n\n    assert_nil internal.final_shape(:text_block)\n  end\n\n  def test_final_shape_should_return_shape_when_shape_is_stored_in_shapes_and_TextBlock_with_value\n    internal = create_internal\n    internal.find_item(:text_block).value('value')\n\n    assert_equal internal.final_shape(:text_block).id, 'text_block'\n  end\n\n  def test_final_shape_should_return_nil_when_shape_is_stored_in_shapes_and_TextBlock_with_no_value\n    internal = create_internal\n    internal.find_item(:text_block)\n\n    assert_nil internal.final_shape(:text_block)\n  end\n\n  def test_final_shape_should_return_shape_when_shape_is_stored_in_shapes_and_ImageBlock_with_src\n    internal = create_internal\n    internal.find_item(:image_block).src('/path/to/image.png')\n\n    assert_equal internal.final_shape(:image_block).id, 'image_block'\n  end\n\n  def test_final_shape_should_return_nil_when_shape_is_stored_in_shapes_and_ImageBlock_with_no_src\n    internal = create_internal\n    assert_nil internal.final_shape(:image_block)\n  end\n\n  def test_final_shape_should_return_nil_when_shape_isnot_stored_in_shapes_and_hidden\n    assert_nil create_internal.final_shape(:text_block_hidden)\n  end\n\n  def test_final_shape_should_return_shape_when_shape_isnot_stored_in_shapes_and_not_Block\n    assert_equal create_internal.final_shape(:rect_with_id).id, 'rect_with_id'\n  end\n\n  def test_final_shape_should_return_nil_when_shape_isnot_stored_in_shapes_and_ImageBlock\n    internal = create_internal do |f|\n      f.shapes[:iblock] = create_shape_format('image-block', 'iblock')\n    end\n\n    assert_nil internal.final_shape(:iblock)\n  end\n\n  def test_final_shape_should_return_shape_when_shape_isnot_stored_in_shapes_and_TextBlock_with_reference\n    assert_equal create_internal.final_shape(:text_block_referenced).id, 'text_block_referenced'\n  end\n\n  def test_final_shape_should_return_nil_when_shape_isnot_stored_in_shapes_and_TextBlock_with_no_value_no_reference\n    internal = create_internal\n\n    assert_nil internal.final_shape(:t1)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/manager/test_target.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Manager::TestTarget < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Shape = Thinreports::BasicReport::Core::Shape\n\n  class TestManager\n    include Shape::Manager::Target\n\n    attr_reader :layout, :report\n\n    def initialize(report, layout)\n      @report = report\n      @layout = layout\n\n      initialize_manager(layout.format) do |f|\n        Shape::Interface(self, f)\n      end\n    end\n  end\n\n  def create_shape_format(type, id)\n    Shape::Format(type).new('id' => id, 'type' => type)\n  end\n\n  def create_manager\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    layout = report.layout\n\n    TestManager.new(report, layout)\n  end\n\n  def test_shorthand_for_finding_item\n    manager = create_manager\n\n    text_block1 = manager[:text_block]\n    text_block1.value = 'block1'\n\n    assert_instance_of Shape::TextBlock::Interface, manager[:text_block]\n    assert_instance_of Shape::ImageBlock::Interface, manager[:image_block]\n    assert_instance_of Shape::Basic::Interface, manager[:rect_with_id]\n\n    assert_raises Thinreports::BasicReport::Errors::UnknownItemId do\n      manager[:unknown_id]\n    end\n\n    assert_raises Thinreports::BasicReport::Errors::UnknownItemId do\n      manager[:default]\n    end\n  end\n\n  def test_shorthand_for_setting_value_to_block\n    manager = create_manager\n\n    manager[:text_block] = 'value of text block1'\n    assert_equal 'value of text block1', manager.item(:text_block).value\n\n    manager[:image_block] = '/path/to/image.png'\n    assert_equal '/path/to/image.png', manager.item(:image_block).src\n\n    assert_raises(NoMethodError) { manager[:rect_with_id] = 'value' }\n    assert_raises(Thinreports::BasicReport::Errors::UnknownItemId) { manager[:default] = 'value' }\n  end\n\n  def test_manager_should_return_instance_of_ManagerInternal\n    assert_instance_of Shape::Manager::Internal, create_manager.manager\n  end\n\n  def test_item_should_properly_return_shape_with_the_specified_Symbol_id\n    assert_equal create_manager.item(:text_block).id, 'text_block'\n  end\n\n  def test_item_should_properly_return_shape_with_the_specified_String_id\n    assert_equal create_manager.item('text_block').id, 'text_block'\n  end\n\n  def test_item_should_raise_when_the_shape_with_the_specified_id_is_not_found\n    assert_raises Thinreports::BasicReport::Errors::UnknownItemId do\n      create_manager.item(:unknown)\n    end\n  end\n\n  def test_item_should_set_an_shape_as_argument_when_a_block_is_given\n    id = nil\n    create_manager.item(:text_block) {|s| id = s.id }\n    assert_equal id, 'text_block'\n  end\n\n  def test_item_should_raise_when_type_of_shape_with_the_specified_id_is_list\n    assert_raises Thinreports::BasicReport::Errors::UnknownItemId do\n      create_manager.item(:default)\n    end\n  end\n\n  def test_list_should_properly_return_list_with_the_specified_Symbol_id\n    assert_equal create_manager.list(:default).id, 'default'\n  end\n\n  def test_list_should_properly_return_list_with_the_specified_String_id\n    assert_equal create_manager.list('default').id, 'default'\n  end\n\n  def test_list_should_raise_when_type_of_shape_with_the_specified_id_is_not_list\n    assert_raises Thinreports::BasicReport::Errors::UnknownItemId do\n      create_manager.list(:text_block)\n    end\n  end\n\n  def test_list_should_use_default_as_id_when_id_is_omitted\n    assert_equal create_manager.list.id, 'default'\n  end\n\n  def test_values_should_properly_set_values_to_shapes_with_specified_id\n    manager = create_manager\n    manager.values(text_block: 1000)\n\n    assert_equal manager.item(:text_block).value, 1000\n  end\n\n  def test_item_exists_asker_should_return_true_when_shape_with_specified_Symbol_id_is_found\n    assert_equal create_manager.item_exists?(:text_block), true\n  end\n\n  def test_item_exists_asker_should_return_true_when_shape_with_specified_String_id_is_found\n    assert_equal create_manager.item_exists?('text_block'), true\n  end\n\n  def test_item_exists_asker_should_return_false_when_shape_with_specified_id_not_found\n    assert_equal create_manager.item_exists?('unknown'), false\n  end\n\n  def test_exists_asker_should_operate_like_as_item_exists_asker\n    manager = create_manager\n    assert_equal manager.exists?(:unknown), manager.item_exists?(:unknown)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/page_number/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::PageNumber::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  PAGE_NUMBER_FORMAT = {\n    'id' => '',\n    'type' => 'page-number',\n    'display' => true,\n    'x' => 100.0,\n    'y' => 200.0,\n    'width' => 300.0,\n    'height' => 400.0,\n    'format' => '{page} / {total}',\n    'target' => '',\n    'style' => {\n      'overflow' => 'truncate',\n      'letter-spacing' => 'normal',\n      'color' => '#000000',\n      'font-size' => 18,\n      'font-family' => ['Helvetica'],\n      'line-height' => 60,\n      'line-height-ratio' => 1.5,\n      'text-align' => 'left'\n    }\n  }\n\n  PageNumber = Thinreports::BasicReport::Core::Shape::PageNumber\n\n  def test_attribute_readers\n    format = PageNumber::Format.new(PAGE_NUMBER_FORMAT)\n\n    assert_equal 'truncate', format.overflow\n    assert_equal '', format.target\n    assert_equal '{page} / {total}', format.default_format\n  end\n\n  def test_id\n    format = PageNumber::Format.new(PAGE_NUMBER_FORMAT)\n    assert_match(/^__pageno\\d+$/, format.id)\n\n    format = PageNumber::Format.new(PAGE_NUMBER_FORMAT.merge('id' => 'foo'))\n    assert_equal 'foo', format.id\n  end\n\n  def test_for_report?\n    format_for_report = PageNumber::Format.new(PAGE_NUMBER_FORMAT)\n    assert_equal true, format_for_report.for_report?\n\n    format_for_list = PageNumber::Format.new(PAGE_NUMBER_FORMAT.merge('target' => 'target_list_id'))\n    assert_equal false, format_for_list.for_report?\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/page_number/test_interface.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::PageNumber::TestInterface < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  PageNumber = Thinreports::BasicReport::Core::Shape::PageNumber\n\n  def create_pageno(format = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    parent = report.start_new_page\n\n    PageNumber::Interface.new parent, PageNumber::Format.new(format)\n  end\n\n  def test_format\n    pageno = create_pageno 'format' => '{page}'\n\n    assert_equal pageno.format, '{page}'\n    pageno.format('{page} / {total}')\n    assert_equal pageno.format, '{page} / {total}'\n  end\n\n  def test_reset_format\n    pageno = create_pageno 'format' => '{page}'\n\n    pageno.format('-- {page} --')\n    pageno.reset_format\n\n    assert_equal pageno.format, '{page}'\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/page_number/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::PageNumber::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  PageNumber = Thinreports::BasicReport::Core::Shape::PageNumber\n\n  def setup\n    @report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    @report.start_new_page\n  end\n\n  def init_pageno(format = {})\n    PageNumber::Internal.new(@report.page, PageNumber::Format.new(format))\n  end\n\n  def test_read_format\n    pageno = init_pageno('format' => 'Page {page}')\n\n    assert_equal pageno.read_format, 'Page {page}'\n  end\n\n  def test_write_format\n    pageno = init_pageno('format' => 'Page {page}')\n    pageno.write_format('{page}')\n\n    assert_equal pageno.read_format, '{page}'\n  end\n\n  def test_reset_format\n    pageno = init_pageno('format' => '{page}')\n    pageno.write_format('Page {page}')\n    pageno.reset_format\n\n    assert_equal pageno.read_format, '{page}'\n  end\n\n  def test_build_format\n    pageno = init_pageno('format' => '{page} / {total}')\n    assert_equal pageno.build_format(1, 100), '1 / 100'\n\n    pageno.write_format('{page}')\n    assert_equal pageno.build_format(1, 100), '1'\n\n    @report.start_page_number_from 5\n    pageno = init_pageno('format' => '{page} / {total}')\n    assert_equal pageno.build_format(1, 100), '5 / 104'\n\n    # if counted target is a List shape\n    pageno = init_pageno('format' => '{page} / {total}',\n                         'target' => 'list-id')\n    assert_equal pageno.build_format(1, 100), '1 / 100'\n  end\n\n  def test_type_of\n    pageno = init_pageno\n    assert pageno.type_of?('page-number')\n  end\n\n  def test_style\n    pageno = init_pageno\n    style = pageno.style\n\n    assert_instance_of PageNumber::Style, style\n    assert_same pageno.style, style\n  end\n\n  def test_for_report\n    pageno = init_pageno('target' => '')\n    assert_equal pageno.for_report?, true\n\n    pageno = init_pageno('target' => 'list-id')\n    assert_equal pageno.for_report?, false\n  end\n\n  def test_Style_class\n    refute_includes PageNumber::Style.accessible_styles, :valign\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/styles/test_base.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Style::TestBase < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Style = Thinreports::BasicReport::Core::Shape::Style::Base\n\n  def create_basic_format(base_style = {})\n    Thinreports::BasicReport::Core::Shape::Basic::Format.new('style' => base_style)\n  end\n\n  def create_style(base_style = {})\n    Style.new(create_basic_format(base_style))\n  end\n\n  def create_new_style(base_style = {}, &block)\n    klass = ::Class.new(Style, &block)\n    klass.new(create_basic_format(base_style))\n  end\n\n  def test_self_style_reader_should_properly_define_a_reading_method\n    style = create_new_style {\n      style_reader :hoge, 'foo'\n    }\n    assert_respond_to style, :hoge\n  end\n\n  def test_self_style_writer_should_properly_define_a_writing_method\n    style = create_new_style {\n      style_writer :hoge, 'foo'\n    }\n    assert_respond_to style, :hoge=\n  end\n\n  def test_self_style_accessor_should_properly_defines_reading_and_writing_methods\n    style = create_new_style {\n      style_accessor :hoge, 'foo'\n    }\n    assert_respond_to style, :hoge\n    assert_respond_to style, :hoge=\n  end\n\n  def test_self_style_accessible_should_add_specified_styles_to_the_accessible_styles_variable\n    style = create_new_style {\n      style_accessible :hoge\n      style_accessible :foo, :bar\n    }\n    assert_equal style.class.accessible_styles, [:hoge, :foo, :bar]\n  end\n\n  def test_self_accessible_styles_variable_should_not_be_shared_each_SubClasses\n    style1 = create_new_style {\n      style_accessible :hoge, :foo\n    }\n    assert_equal style1.class.accessible_styles, [:hoge, :foo]\n  end\n\n  def test_self_accessible_styles_variable_should_be_inherited_to_SubClass\n    super_klass = ::Class.new(Style) {\n      style_accessible :hoge, :foo\n    }\n    sub_klass = ::Class.new(super_klass)\n\n    assert_equal sub_klass.accessible_styles, super_klass.accessible_styles\n  end\n\n  def test_self_accessible_styles_variables_of_SubClass_should_not_interfere_mutually\n    super_klass = ::Class.new(Style) {\n      style_accessible :foo, :bar\n    }\n    sub_klass1 = ::Class.new(super_klass)\n    sub_klass2 = ::Class.new(super_klass)\n\n    refute_same sub_klass1.accessible_styles, sub_klass2.accessible_styles\n  end\n\n  def test_read_internal_style_should_return_style_of_styles_when_style_is_found_in_styles\n    style = create_style('hoge' => 'base_style')\n    style.write_internal_style('hoge', 'new_style')\n\n    assert_equal style.read_internal_style('hoge'), 'new_style'\n  end\n\n  def test_read_internal_style_should_return_style_of_base_when_style_is_not_found_in_styles\n    style = create_style('hoge' => 'base_style')\n    assert_equal style.read_internal_style('hoge'), 'base_style'\n  end\n\n  def test_write_internal_style_should_properly_set_style_to_the_styles\n    style = create_style({})\n    style.write_internal_style('hoge', 'hoge_style')\n\n    assert_equal style.styles['hoge'], 'hoge_style'\n  end\n\n  def test_has_style_asker_should_return_true_when_specified_style_method_is_accessible\n    style = create_new_style {\n      style_accessible :hoge, :foo\n    }\n    assert_equal style.has_style?(:foo), true\n  end\n\n  def test_has_style_asker_should_return_false_when_specified_style_method_is_not_accessible\n    style = create_new_style {\n      style_accessible :foo\n    }\n    assert_equal style.has_style?(:hoge), false\n  end\n\n  def test_verify_style_value_should_raise_when_value_is_not_included_in_list\n    assert_raises ArgumentError do\n      create_style.send(:verify_style_value, :invalid, [:hoge, :foo, :bar])\n    end\n  end\n\n  def test_verify_style_value_should_not_raise_when_value_is_found_in_list\n    create_style.send(:verify_style_value, :valid, [:hoge, :valid, :foo])\n  rescue ArgumentError\n    flunk\n  end\n\n  def test_reader_method_caller_should_properly_delegate_to_real_method\n    style = create_new_style('hoge_style' => 'hoge_style_value') {\n      style_accessible :hoge\n      style_reader :hoge, 'hoge_style'\n    }\n    assert_equal style[:hoge], 'hoge_style_value'\n  end\n\n  def test_writer_method_caller_should_properly_delegate_to_real_method\n    style = create_new_style {\n      style_accessible :hoge\n      style_accessor :hoge, 'hoge_style'\n    }\n    style[:hoge] = 'hoge_style_value'\n    assert_equal style.hoge, 'hoge_style_value'\n  end\n\n  def test_reader_method_caller_should_raise_when_style_is_not_accessible\n    assert_raises Thinreports::BasicReport::Errors::UnknownShapeStyleName do\n      create_new_style[:unknown]\n    end\n  end\n\n  def test_writer_method_caller_should_raise_when_style_is_not_accessible\n    assert_raises Thinreports::BasicReport::Errors::UnknownShapeStyleName do\n      create_new_style[:unknown] = 'value'\n    end\n  end\n\n  def test_copy_should_return_the_instance_of_the_same_class_as_itself\n    style = create_style\n    assert_instance_of Style, style.copy\n  end\n\n  def test_styles_of_copied_style_should_not_same_the_styles_of_original\n    style = create_style\n    refute_same style.styles, style.copy.styles\n  end\n\n  def test_styles_of_copied_style_should_equal_the_style_of_original\n    style = create_style\n    style.write_internal_style('foo', 'foo_value')\n    assert_equal style.styles['foo'], style.copy.styles['foo']\n  end\n\n  def test_identifier_should_return_empty_string_when_the_style_is_not_set\n    style = create_style\n    assert_equal style.identifier, ''\n  end\n\n  def test_identifier_should_return_the_same_as_hash_value_of_styles_when_style_is_set_something\n    style = create_style\n    style.write_internal_style('foo', 'foo_value')\n\n    assert_equal style.identifier, style.styles.hash.to_s\n  end\n\n  def test_finalized_styles\n    base_styles = { 'foo' => 'default foo', 'bar' => 'default bar' }\n\n    style = create_style(base_styles)\n    style.write_internal_style('foo', 'new foo')\n\n    assert_equal({ 'foo' => 'new foo', 'bar' => 'default bar' }, style.finalized_styles)\n    assert_same style.finalized_styles, style.finalized_styles\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/styles/test_basic.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Style::TestBasic < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def create_basic_style(format_config = {})\n    format = Thinreports::BasicReport::Core::Shape::Basic::Format.new(format_config)\n    Thinreports::BasicReport::Core::Shape::Style::Basic.new(format)\n  end\n\n  def test_visible_should_return_visibility_of_format_as_default\n    style = create_basic_style('display' => false)\n    assert_equal style.visible, false\n  end\n\n  def test_visible_should_properly_set_visibility\n    style = create_basic_style('display' => false)\n    style.visible = true\n\n    assert_equal style.visible, true\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/styles/test_graphic.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Style::TestGraphic < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def test_border_color\n    style = create_graphic_style('border-color' => 'red')\n    assert_equal 'red', style.border_color\n\n    style.border_color = '#ff0000'\n    assert_equal '#ff0000', style.styles['border-color']\n    assert_equal '#ff0000', style.border_color\n  end\n\n  def test_border_width\n    style = create_graphic_style('border-width' => 2.0)\n    assert_equal 2.0, style.border_width\n\n    style.border_width = 10.9\n    assert_equal 10.9, style.styles['border-width']\n    assert_equal 10.9, style.border_width\n  end\n\n  def test_fill_color\n    style = create_graphic_style('fill-color' => '#0000ff')\n    assert_equal '#0000ff', style.fill_color\n\n    style.fill_color = 'blue'\n    assert_equal 'blue', style.styles['fill-color']\n    assert_equal 'blue', style.fill_color\n  end\n\n  def test_border\n    style = create_graphic_style('border-color' => 'red', 'border-width' => 1)\n    assert_equal [1, 'red'], style.border\n\n    style.border = [2.0, '#ff0000']\n    assert_equal 2.0, style.styles['border-width']\n    assert_equal '#ff0000', style.styles['border-color']\n  end\n\n  private\n\n  def create_graphic_style(default_style = {})\n    format = Thinreports::BasicReport::Core::Shape::Basic::Format.new('style' => default_style)\n    Thinreports::BasicReport::Core::Shape::Style::Graphic.new(format)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/styles/test_text.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Style::TestText < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def test_color\n    style = create_text_style('color' => 'red')\n    assert_equal 'red', style.color\n\n    style.color = 'blue'\n    assert_equal 'blue', style.styles['color']\n    assert_equal 'blue', style.color\n  end\n\n  def test_font_size\n    style = create_text_style('font-size' => 18.0)\n    assert_equal 18.0, style.font_size\n\n    style.font_size = 19\n    assert_equal 19, style.styles['font-size']\n    assert_equal 19, style.font_size\n  end\n\n  def test_initialize_font_style\n    default_font_style = ['bold', 'italic']\n    style = create_text_style('font-style' => default_font_style)\n\n    refute_same default_font_style, style.styles['font-style']\n    assert_equal default_font_style, style.styles['font-style']\n  end\n\n  def test_bold\n    style = create_text_style('font-style' => ['bold'])\n    assert_equal true, style.bold\n\n    style.bold = false\n    assert_equal [], style.styles['font-style']\n    assert_equal false, style.bold\n  end\n\n  def test_italic\n    style = create_text_style('font-style' => ['italic'])\n    assert_equal true, style.italic\n\n    style.italic = false\n    assert_equal [], style.styles['font-style']\n    assert_equal false, style.italic\n  end\n\n  def test_underline\n    style = create_text_style('font-style' => ['underline'])\n    assert_equal true, style.underline\n\n    style.underline = false\n    assert_equal [], style.styles['font-style']\n    assert_equal false, style.underline\n  end\n\n  def test_linethrough\n    style = create_text_style('font-style' => ['linethrough'])\n    assert_equal true, style.linethrough\n\n    style.linethrough = false\n    assert_equal [], style.styles['font-style']\n    assert_equal false, style.linethrough\n  end\n\n  def test_align\n    style = create_text_style('text-align' => 'center')\n    assert_equal :center, style.align\n\n    style.align = :right\n    assert_equal 'right', style.styles['text-align']\n    assert_equal :right, style.align\n  end\n\n  def test_valign\n    style = create_text_style('vertical-align' => '')\n    assert_equal :top, style.valign\n\n    style.valign = :middle\n    assert_equal 'middle', style.styles['vertical-align']\n    assert_equal :middle, style.valign\n\n    assert_deprecated { style.valign = :center }\n    assert_equal :middle, style.valign\n  end\n\n  private\n\n  def create_text_style(default_style = {})\n    format = Thinreports::BasicReport::Core::Shape::Text::Format.new('style' => default_style)\n    Thinreports::BasicReport::Core::Shape::Style::Text.new(format)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Text::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  TEXT_FORMAT = {\n    'id' => 'text_1',\n    'type' => 'text',\n    'x' => 100.0,\n    'y' => 200.0,\n    'width' => 300.0,\n    'height' => 400.0,\n    'description' => 'Description for item',\n    'display' => true,\n    'texts' => [\n      '1st text line',\n      '2nd text line'\n    ],\n    'valign' => 'top',\n    'style' => {\n      'font-family' => ['Arial'],\n      'font-size' => 12,\n      'color' => '#000000',\n      'font-style' => ['bold', 'italic', 'linethrough', 'underline'],\n      'text-align' => 'left',\n      'vertical-align' => 'top',\n      'line-height' => 60,\n      'line-height-ratio' => 1.5,\n      'letter-spacing' => 'normal'\n    }\n  }\n\n  Text = Thinreports::BasicReport::Core::Shape::Text\n\n  def test_attribute_readers\n    format = Text::Format.new(TEXT_FORMAT)\n\n    assert_equal TEXT_FORMAT['texts'], format.texts\n    assert_equal 'top', format.valign\n    assert_equal 60, format.line_height\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::Text::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Text = Thinreports::BasicReport::Core::Shape::Text\n\n  def create_internal(format_config = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    Text::Internal.new(report.start_new_page, Text::Format.new(format_config))\n  end\n\n  def test_type_of?\n    assert create_internal.type_of?('text'), true\n    refute create_internal.type_of?(:basic), false\n  end\n\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/formatter/test_basic.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::TestBasic < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Formatter = Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::Basic\n\n  def test_apply_simple_format\n    format = stub(format_base: 'Hello {value}!')\n\n    assert_equal Formatter.new(format).apply('Thinreports'),\n                 'Hello Thinreports!'\n  end\n\n  def test_apply_multiple_format\n    format = stub(format_base: 'Hello {value}! And good bye {value}.')\n\n    assert_equal Formatter.new(format).apply('Thinreports'),\n                 'Hello Thinreports! And good bye Thinreports.'\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/formatter/test_datetime.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::TestDatetime < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Aliases\n  TextBlock = Thinreports::BasicReport::Core::Shape::TextBlock\n  Formatter = TextBlock::Formatter::Datetime\n\n  def setup\n    @datetime_format = '%Y/%m/%d %H:%M:%S'\n    @time = Time.now\n  end\n\n  def text_block_format(format = {})\n    default = {'base' => '', 'datetime' => {'format' => '%Y/%m/%d %H:%M:%S'}}\n    TextBlock::Format.new('format' => default.merge(format))\n  end\n\n  def test_apply_datetime_format_without_basic_format\n    formatter = Formatter.new(text_block_format)\n\n    assert_equal @time.strftime(@datetime_format),\n                 formatter.apply(@time)\n  end\n\n  def test_apply_datetime_format_with_basic_format\n    formatter = Formatter.new(text_block_format('base' => 'Now: {value}'))\n\n    assert_equal \"Now: #{@time.strftime(@datetime_format)}\",\n                 formatter.apply(@time)\n\n  end\n\n  def test_not_apply_datetime_format_and_return_raw_value\n    # When value is invalid\n    formatter = Formatter.new(text_block_format)\n\n    assert_same formatter.apply(val = 'invalid value'), val\n    assert_same formatter.apply(val = 123456), val\n\n    # When format is empty\n    formatter = Formatter.new(text_block_format('datetime' => {'format' => ''}))\n\n    assert_same formatter.apply(@time), @time\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/formatter/test_number.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::TestNumber < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Formatter = Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::Number\n\n  def init_formatter(expect_formats)\n    format = stub({ format_base: '',\n                    format_number_precision: nil,\n                    format_number_delimiter: nil }.merge(expect_formats))\n    Formatter.new(format)\n  end\n\n  def test_apply_precision_formats\n    # When precision is 2\n    formatter = init_formatter(format_number_precision: 2)\n\n    assert_equal formatter.apply(1.005), '1.01'\n    assert_equal formatter.apply(1.004), '1.00'\n    assert_equal formatter.apply(1), '1.00'\n    # With String value\n    assert_equal formatter.apply('999.999'), '1000.00'\n    assert_equal formatter.apply('-999.999'), '-1000.00'\n    assert_equal formatter.apply('9'), '9.00'\n    # Cannot apply, Return the raw value\n    assert_equal formatter.apply('invalid value'), 'invalid value'\n\n    # When precision is 0\n    formatter = init_formatter(format_number_precision: 0)\n\n    assert_equal formatter.apply(1.5), '2'\n  end\n\n  def test_apply_precision_format_with_basic_format\n    formatter = init_formatter(format_base: '$ {value}',\n                               format_number_precision: 0)\n\n    assert_equal formatter.apply(199.5), '$ 200'\n  end\n\n  def test_apply_delimiter_formats\n    # When delimiter is ','\n    formatter = init_formatter(format_number_delimiter: ',')\n\n    assert_equal formatter.apply(1000000), '1,000,000'\n    assert_equal formatter.apply(-1000000), '-1,000,000'\n    assert_equal formatter.apply('1000.0'), '1,000.0'\n    assert_equal formatter.apply('-1000.0'), '-1,000.0'\n    assert_equal '1,000.1111', formatter.apply(1000.1111)\n    # Cannot apply, Return the raw value\n    assert_equal formatter.apply('invalid value'), 'invalid value'\n\n    # When delimiter is whitespace\n    formatter = init_formatter(format_number_delimiter: ' ')\n\n    assert_equal formatter.apply(99999), '99 999'\n  end\n\n  def test_apply_delimiter_format_with_basic_format\n    formatter = init_formatter(format_base: '￥{value}',\n                               format_number_delimiter: ',')\n\n    assert_equal formatter.apply(199800), '￥199,800'\n  end\n\n  def test_apply_all_format\n    formatter = init_formatter(format_base: '-- {value} --',\n                               format_number_delimiter: ',',\n                               format_number_precision: 2)\n\n    assert_equal formatter.apply(95618.88567), '-- 95,618.89 --'\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/formatter/test_padding.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::TestPadding < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Formatter = Thinreports::BasicReport::Core::Shape::TextBlock::Formatter::Padding\n\n  def init_formatter(expect_formats)\n    format = stub({ format_base: nil,\n                    format_padding_length: 0,\n                    format_padding_char: nil,\n                    format_padding_rdir?: false }.merge(expect_formats))\n    Formatter.new(format)\n  end\n\n  def test_apply_padding_formats_with_left_direction\n    formatter = init_formatter(format_padding_length: 5,\n                               format_padding_char: '0')\n\n    assert_equal formatter.apply(1), '00001'\n    assert_equal formatter.apply('日本語'), '00日本語'\n  end\n\n  def test_apply_padding_formats_should_not_apply_when_character_length_is_short\n    formatter = init_formatter(format_padding_length: 5,\n                               format_padding_char: '0')\n\n    assert_equal formatter.apply('1234567'), '1234567'\n  end\n\n  def test_apply_padding_formats_with_right_direction\n    formatter = init_formatter(format_padding_length: 5,\n                               format_padding_char: '0',\n                               :format_padding_rdir? => true)\n\n    assert_equal formatter.apply(123), '12300'\n  end\n\n  def test_apply_padding_format_with_basic_format\n    formatter = init_formatter(format_base: '[{value}]',\n                               format_padding_length: 10,\n                               format_padding_char: ' ')\n\n    assert_equal formatter.apply('ABC'), '[       ABC]'\n  end\n\n  def test_return_raw_value_when_length_is_0\n    formatter = init_formatter(format_padding_length: 0,\n                               format_padding_char: '0')\n\n    assert_same formatter.apply(v = 123), v\n\n    # But apply only basic format if have basic-format.\n    formatter = init_formatter(format_base: '<{value}>',\n                               format_padding_length: 0,\n                               format_padding_char: '0')\n\n    assert_equal formatter.apply(123), '<123>'\n  end\n\n  def test_return_raw_value_when_char_is_empty\n    formatter = init_formatter(format_padding_length: 10,\n                               format_padding_char: '')\n\n    assert_same formatter.apply(v = '1'), v\n\n    # But apply only basic format if have basic-format.\n    formatter = init_formatter(format_base: '<{value}>',\n                               format_padding_length: 0,\n                               format_padding_char: '0')\n\n    assert_equal formatter.apply('1'), '<1>'\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  TEXT_BLOCK_FORMAT = {\n    'id' => 'text_block',\n    'reference-id' => 'referenced_text_block',\n    'type' => 'text-block',\n    'display' => true,\n    'multiple-line' => false,\n    'x' => 100.0,\n    'y' => 200.0,\n    'width' => 300.0,\n    'height' => 400.0,\n    'value' => 'default value',\n    'format' => {\n      'base' => 'Price: {value}',\n      'type' => 'number',\n      'number' => {\n        'delimiter' => ',',\n        'precision' => 1\n      }\n    },\n    'description' => 'Description for item',\n    'style' => {\n      'word-wrap' => 'break-word',\n      'overflow' => 'truncate',\n      'text-align' => 'right',\n      'vertical-align' => 'middle',\n      'color' => '#000000',\n      'font-size' => 12,\n      'font-family' => ['Helvetica'],\n      'font-style' => ['bold', 'italic', 'linethrough', 'underline'],\n      'letter-spacing' => 'normal',\n      'line-height' => 30,\n      'line-height-ratio' => 1.5\n    }\n  }\n\n  TextBlock = Thinreports::BasicReport::Core::Shape::TextBlock\n\n  def test_attribute_readers\n    format = TextBlock::Format.new(TEXT_BLOCK_FORMAT)\n\n    assert_equal 'referenced_text_block', format.ref_id\n    assert_equal 'middle', format.valign\n    assert_equal 'truncate', format.overflow\n    assert_equal 30, format.line_height\n    assert_equal false, format.multiple?\n    assert_equal 'Price: {value}', format.format_base\n    assert_equal 'number', format.format_type\n  end\n\n  def test_has_reference?\n    format_has_reference = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge('reference-id' => 'other'))\n    assert_equal true, format_has_reference.has_reference?\n\n    format_has_no_reference = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge('reference-id' => ''))\n    assert_equal false, format_has_no_reference.has_reference?\n  end\n\n  def test_has_format?\n    format_has_text_format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => { 'type' => 'datetime' }\n    ))\n    assert_equal true, format_has_text_format.has_format?\n\n    format_has_no_text_format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => { 'type' => '' }\n    ))\n    assert_equal false, format_has_no_text_format.has_format?\n  end\n\n  def test_number_format_attribute_readers\n    format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'number',\n        'number' => {\n          'delimiter' => ',',\n          'precision' => 1\n        }\n      }\n    ))\n    assert_equal ',', format.format_number_delimiter\n    assert_equal 1, format.format_number_precision\n  end\n\n  def test_datetime_format_attribute_readers\n    format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'datetime',\n        'datetime' => {\n          'format' => '%Y-%m-%d'\n        }\n      }\n    ))\n    assert_equal '%Y-%m-%d', format.format_datetime_format\n  end\n\n  def test_padding_format_attribute_readers\n    format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'padding',\n        'padding' => {\n          'char' => '0',\n          'length' => 10,\n          'direction' => 'L'\n        }\n      }\n    ))\n    assert_equal '0', format.format_padding_char\n    assert_equal 'L', format.format_padding_dir\n  end\n\n  def test_format_padding_length\n    format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'padding',\n        'padding' => {\n          'char' => '0',\n          'length' => 10,\n          'direction' => 'L'\n        }\n      }\n    ))\n    assert_equal 10, format.format_padding_length\n\n    format = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'padding',\n        'padding' => {\n          'char' => '0',\n          'length' => '',\n          'direction' => 'L'\n        }\n      }\n    ))\n    assert_equal 0, format.format_padding_length\n  end\n\n  def test_format_padding_rdir?\n    format_direction_left = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'padding',\n        'padding' => {\n          'char' => '0',\n          'length' => 10,\n          'direction' => 'L'\n        }\n      }\n    ))\n    assert_equal false, format_direction_left.format_padding_rdir?\n\n    format_direction_right = TextBlock::Format.new(TEXT_BLOCK_FORMAT.merge(\n      'format' => {\n        'type' => 'padding',\n        'padding' => {\n          'char' => '0',\n          'length' => 10,\n          'direction' => 'R'\n        }\n      }\n    ))\n    assert_equal true, format_direction_right.format_padding_rdir?\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/test_formatter.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::TestFormatter < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Formatter = Thinreports::BasicReport::Core::Shape::TextBlock::Formatter\n\n  def test_initialize_formatter_by_type\n    assert_instance_of Formatter::Basic,\n      Formatter.setup( stub(format_type: '') )\n\n    assert_instance_of Formatter::Number,\n      Formatter.setup( stub(format_type: 'number') )\n\n    assert_instance_of Formatter::Datetime,\n      Formatter.setup( stub(format_type: 'datetime') )\n\n    assert_instance_of Formatter::Padding,\n      Formatter.setup( stub(format_type: 'padding') )\n\n    assert_raises Thinreports::BasicReport::Errors::UnknownFormatterType do\n      Formatter.setup( stub(format_type: 'unknown') )\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/test_interface.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::TestInterface < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  TextBlock = Thinreports::BasicReport::Core::Shape::TextBlock\n\n  def create_interface(format_config = {})\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    parent = report.start_new_page\n\n    TextBlock::Interface.new parent, TextBlock::Format.new(format_config)\n  end\n\n  def test_format_enabled_asker_should_operate_as_delegator_of_internal\n    tblock = create_interface('format' => {'type' => 'datetime'})\n    assert_equal tblock.format_enabled?, tblock.internal.format_enabled?\n  end\n\n  def test_format_enabled_should_properly_set_value_to_internal\n    tblock = create_interface('format' => {'type' => 'number'})\n    tblock.format_enabled(false)\n\n    assert_equal tblock.internal.format_enabled?, false\n  end\n\n  def test_set_should_properly_set_a_value\n    tblock = create_interface\n    tblock.set(1000, visible: false)\n\n    assert_equal tblock.value, 1000\n  end\n\n  def test_set_should_properly_set_styles\n    tblock = create_interface\n    tblock.set(1000, color: '#ff0000',\n                     bold: true,\n                     italic: true)\n\n    assert_equal [tblock.style(:color),\n                  tblock.style(:bold),\n                  tblock.style(:italic)],\n                 ['#ff0000', true, true]\n  end\n\n  def test_value=\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    page = report.start_new_page\n\n    page.item(:text_block).value = 'foo'\n    assert_equal 'foo', page.item(:text_block).value\n\n    page.item(:text_block).value += 'bar'\n    assert_equal 'foobar', page.item(:text_block).value\n\n    page.item(:text_block).value = 1000\n    page.item(:text_block).value += 999\n    assert_equal 1999, page.item(:text_block).value\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/shape/text_block/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::Shape::TextBlock::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  TextBlock = Thinreports::BasicReport::Core::Shape::TextBlock\n\n  def create_parent\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    report.start_new_page do |page|\n      # Add to force TextBlock shape.\n      page.manager.format.shapes[:foo] = TextBlock::Format.new('type' => 'text-block',\n                                                               'id' => 'foo')\n      # Set value to TextBlock.\n      page.item(:foo).value('foo value')\n    end\n  end\n\n  def create_internal(format_config = {})\n    TextBlock::Internal.new(create_parent, TextBlock::Format.new(format_config))\n  end\n\n  def test_multiple_asker_should_operate_as_delegator_of_format\n    tblock = create_internal('multiple-line' => true)\n    assert_equal tblock.multiple?, tblock.format.multiple?\n  end\n\n  def test_style_should_return_the_instance_of_Style_Text\n    assert_instance_of Thinreports::BasicReport::Core::Shape::Style::Text, create_internal.style\n  end\n\n  def test_read_value_should_return_the_format_value_as_default\n    tblock = create_internal('value' => 'default value')\n    assert_equal tblock.read_value, 'default value'\n  end\n\n  def test_read_value_should_return_the_value_of_referenced_shape\n    tblock = create_internal('reference-id' => 'foo', 'value' => '')\n    assert_equal tblock.read_value, 'foo value'\n  end\n\n  def test_read_value_should_return_the_value_stored_in_states\n    tblock = create_internal\n    tblock.states[:value] = 'value in states'\n\n    assert_equal tblock.read_value, 'value in states'\n  end\n\n  def test_write_value_should_properly_set_the_specified_value_to_states\n    tblock = create_internal\n    tblock.write_value(1000)\n\n    assert_equal tblock.states[:value], 1000\n  end\n\n  def test_write_value_should_show_warnings_when_tblock_has_reference\n    tblock = create_internal('id' => 'bar', 'reference-id' => 'foo')\n    _out, err = capture_io do\n      tblock.write_value('value')\n    end\n    assert_equal err.chomp, 'The set value was not saved, ' +\n                            \"Because 'bar' has reference to 'foo'.\"\n  end\n\n  def test_real_value_should_return_the_formatted_value_when_tblock_has_any_format\n    tblock = create_internal('format' => {'type' => 'datetime',\n                                          'datetime' => {'format' => '%Y/%m/%d'}})\n    tblock.write_value(value = Time.now)\n\n    assert_equal tblock.real_value, value.strftime('%Y/%m/%d')\n  end\n\n  def test_real_value_should_return_the_raw_value_when_tblock_has_no_format\n    tblock = create_internal\n    tblock.write_value('any value')\n\n    assert_equal tblock.real_value, 'any value'\n  end\n\n  def test_format_enabled_should_properly_set_value_to_states_as_format_enabled\n    tblock = create_internal\n    tblock.format_enabled(false)\n\n    assert_equal tblock.states[:format_enabled], false\n  end\n\n  def test_format_enabled_asker_should_return_true_when_format_has_any_type\n    tblock = create_internal('format' => {'type' => 'datetime'})\n\n    assert_equal tblock.format_enabled?, true\n  end\n\n  def test_format_enabled_asker_should_return_true_when_base_of_format_has_any_value\n    tblock = create_internal('format' => {'base' => '{value}'})\n\n    assert_equal tblock.format_enabled?, true\n  end\n\n  def test_format_enabled_asker_should_return_false_when_format_has_no_type_and_base_has_not_value\n    assert_equal create_internal.format_enabled?, false\n  end\n\n  def test_format_enabled_asker_should_return_true_constantly_when_tblock_is_multiple_mode\n    tblock = create_internal('multiple-line' => true,\n                             'format' => {'base' => '{value}',\n                                          'type' => 'number'})\n    tblock.format_enabled(true)\n\n    assert tblock.format_enabled?\n  end\n\n  def test_type_of_asker_should_return_true_when_value_is_tblock\n    assert_equal create_internal.type_of?('text-block'), true\n  end\n\n  def test_type_of_asker_should_return_true_when_value_is_block\n    assert_equal create_internal.type_of?(:block), true\n  end\n\n  def test_formatter_should_return_instance_of_FormatterBasic_when_format_is_enable\n    tblock = create_internal('format' => {'type' => 'datetime'})\n\n    assert_kind_of TextBlock::Formatter::Basic, tblock.send(:formatter)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/test_shape.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::TestShape < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  ShapeModule = Thinreports::BasicReport::Core::Shape\n\n  def test_find_by_type_should_return_PageNumber\n    assert_same ShapeModule.find_by_type('page-number'), ShapeModule::PageNumber\n  end\n\n  def test_find_by_type_should_return_ImageBlock\n    assert_same ShapeModule.find_by_type('image-block'), ShapeModule::ImageBlock\n  end\n\n  def test_find_by_type_should_return_TextBlock\n    assert_same ShapeModule.find_by_type('text-block'), ShapeModule::TextBlock\n  end\n\n  def test_find_by_type_should_return_List\n    assert_same ShapeModule.find_by_type('list'), ShapeModule::List\n  end\n\n  def test_find_by_type_should_return_Text\n    assert_same ShapeModule.find_by_type('text'), ShapeModule::Text\n  end\n\n  def test_find_by_type_should_return_Basic_as_Image\n    assert_same ShapeModule.find_by_type('image'), ShapeModule::Basic\n  end\n\n  def test_find_by_type_should_return_Basic_as_Line\n    assert_same ShapeModule.find_by_type('line'), ShapeModule::Basic\n  end\n\n  def test_find_by_type_should_return_Basic_as_Rect\n    assert_same ShapeModule.find_by_type('rect'), ShapeModule::Basic\n  end\n\n  def test_find_by_type_should_return_Basic_as_Ellipse\n    assert_same ShapeModule.find_by_type('ellipse'), ShapeModule::Basic\n  end\n\n  def test_find_by_type_should_raise\n    assert_raises Thinreports::BasicReport::Errors::UnknownShapeType do\n      ShapeModule.find_by_type('unknown')\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/core/test_utils.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Core::TestShape < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n  include Thinreports::BasicReport::Utils\n\n  def test_call_block_in\n    expected = '123'\n    assert_same expected, call_block_in(expected)\n\n    assert_equal [1, 2, 3], call_block_in([2, 1, 3], &proc { sort! })\n    assert_equal [1, 2, 3], call_block_in([2, 1, 3], &proc { |a| a.sort! })\n  end\n\n  def test_deep_copy_in_unsupported_object\n    [123, nil, Struct.new(:foo).new].each do |unsupported_value|\n      assert_raises ArgumentError do\n        deep_copy(unsupported_value)\n      end\n    end\n  end\n\n  def test_deep_copy_in_Array\n    src = ['string', Time.now]\n    dup = deep_copy(src)\n\n    refute_same dup, src\n\n    src.each_with_index do |e, i|\n      assert_equal dup[i], e\n      refute_same dup[i], e\n    end\n  end\n\n  def test_deep_copy_in_Hash\n    src = { a: 'string', b: Time.now }\n    dup = deep_copy(src)\n\n    refute_same dup, src\n\n    src.each do |k, v|\n      assert_equal dup[k], v\n      refute_same dup[k], v\n    end\n  end\n\n  def test_blank_value_in_String\n    [\"\", ''].each do |val|\n      assert_equal true, blank_value?(val)\n    end\n\n    [' ', '　', 'abc', 'あいう'].each do |val|\n      assert_equal false, blank_value?(val)\n    end\n  end\n\n  def test_blank_value_in_NilClass\n    assert_equal true, blank_value?(nil)\n  end\n\n  def test_blank_value_in_other_classes\n    [0, 1, -1, 9.99, true, false, Time.now].each do |val|\n      assert_equal false, blank_value?(val)\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/graphics/test_attributes.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::Graphics::TestAttributes < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def setup\n    @pdf = Thinreports::BasicReport::Generator::PDF::Document.new\n  end\n\n  def test_build_graphic_attributes\n    graphic_styles = {\n      'border-color' => '#ff0000',\n      'border-width' => 2.0,\n      'border-style' => 'solid',\n      'fill-color' => '#000000'\n    }\n\n    assert_equal(\n      {\n        stroke: '#ff0000',\n        stroke_width: 2.0,\n        stroke_type: 'solid',\n        fill: '#000000'\n      },\n      @pdf.build_graphic_attributes(graphic_styles)\n    )\n\n    customized_attributes = @pdf.build_graphic_attributes(graphic_styles) { |attrs| attrs[:stroke] = 'blue' }\n    assert_equal 'blue', customized_attributes[:stroke]\n  end\n\n  def test_build_text_attributes\n    text_styles_without_overflow_wrap = {\n      'font-family' => %w( Helvetica IPAMincho ),\n      'font-size' => 18.0,\n      'color' => 'red',\n      'text-align' => 'right',\n      'vertical-align' => 'bottom',\n      'font-style' => %w( bold italic ),\n      'letter-spacing' => 2.0,\n      'line-height' => 20.0,\n      'overflow' => 'expand',\n      'word-wrap' => 'break-word'\n    }\n    assert_equal(\n      {\n        font: 'Helvetica',\n        size: 18.0,\n        color: 'red',\n        align: :right,\n        valign: :bottom,\n        styles: [:bold, :italic],\n        letter_spacing: 2.0,\n        line_height: 20.0,\n        overflow: :expand,\n        word_wrap: :break_word,\n        overflow_wrap: :normal\n      },\n      @pdf.build_text_attributes(text_styles_without_overflow_wrap)\n    )\n\n    text_styles_with_overflow_wrap = text_styles_without_overflow_wrap.merge(\n      'overflow-wrap' => 'anywhere'\n    )\n    assert_equal(\n      {\n        font: 'Helvetica',\n        size: 18.0,\n        color: 'red',\n        align: :right,\n        valign: :bottom,\n        styles: [:bold, :italic],\n        letter_spacing: 2.0,\n        line_height: 20.0,\n        overflow: :expand,\n        word_wrap: :break_word,\n        overflow_wrap: :anywhere\n      },\n      @pdf.build_text_attributes(text_styles_with_overflow_wrap)\n    )\n\n    customized_attributes = @pdf.build_text_attributes(text_styles_without_overflow_wrap) { |attrs|\n      attrs[:color] = 'blue'\n    }\n    assert_equal 'blue', customized_attributes[:color]\n  end\n\n  def test_font_family\n    assert_equal 'IPAGothic', @pdf.font_family(%w( IPAGothic Helvetica ))\n    assert_equal 'Helvetica', @pdf.font_family(%w( Unknown IPAMincho ))\n  end\n\n  def test_font_styles\n    assert_equal [:bold, :italic, :underline, :strikethrough],\n      @pdf.font_styles(%w( bold italic underline linethrough ))\n  end\n\n  def test_letter_spacing\n    assert_equal 2.0, @pdf.letter_spacing(2.0)\n    assert_nil @pdf.letter_spacing('')\n    assert_nil @pdf.letter_spacing(nil)\n  end\n\n  def test_text_align\n    assert_equal :left, @pdf.text_align('left')\n    assert_equal :center, @pdf.text_align('center')\n    assert_equal :right, @pdf.text_align('right')\n    assert_equal :left, @pdf.text_align('')\n    assert_equal :left, @pdf.text_align(nil)\n  end\n\n  def test_text_valign\n    assert_equal :top, @pdf.text_valign('top')\n    assert_equal :center, @pdf.text_valign('middle')\n    assert_equal :bottom, @pdf.text_valign('bottom')\n    assert_equal :top, @pdf.text_valign('')\n    assert_equal :top, @pdf.text_valign(nil)\n  end\n\n  def test_text_overflow\n    assert_equal :truncate, @pdf.text_overflow('truncate')\n    assert_equal :shrink_to_fit, @pdf.text_overflow('fit')\n    assert_equal :expand, @pdf.text_overflow('expand')\n    assert_equal :truncate, @pdf.text_overflow('')\n    assert_equal :truncate, @pdf.text_overflow(nil)\n  end\n\n  def test_word_wrap\n    assert_equal :break_word, @pdf.word_wrap('break-word')\n    assert_equal :none, @pdf.word_wrap('none')\n    assert_equal :none, @pdf.word_wrap(nil)\n  end\n\n  def test_line_height\n    assert_equal 20.9, @pdf.line_height(20.9)\n    assert_nil @pdf.line_height('')\n    assert_nil @pdf.line_height(nil)\n  end\n\n  def test_image_position_x\n    assert_equal :left, @pdf.image_position_x('left')\n    assert_equal :center, @pdf.image_position_x('center')\n    assert_equal :right, @pdf.image_position_x('right')\n    assert_equal :left, @pdf.image_position_x('')\n    assert_equal :left, @pdf.image_position_x(nil)\n  end\n\n  def test_image_position_y\n    assert_equal :top, @pdf.image_position_y('top')\n    assert_equal :center, @pdf.image_position_y('middle')\n    assert_equal :bottom, @pdf.image_position_y('bottom')\n    assert_equal :top, @pdf.image_position_y('')\n    assert_equal :top, @pdf.image_position_y(nil)\n  end\n\n  def test_overflow_wrap\n    assert_equal :anywhere, @pdf.overflow_wrap('anywhere', :none)\n    assert_equal :disable_break_word_by_space, @pdf.overflow_wrap('disable-break-word-by-space', :break_word)\n    assert_equal :normal, @pdf.overflow_wrap('normal', :none)\n\n    # When value is unexpected value\n    assert_equal :normal, @pdf.overflow_wrap('', :none)\n  end\n\n  def text_overflow_wrap_fallback_to_word_wrap\n    # word_wrap: none fallbacks to :disable_break_word_by_space\n    assert_equal :disable_break_word_by_space, @pdf.overflow_wrap(nil, :none)\n    # word_wrap: break_word fallbacks to :normal\n    assert_equal :normal, @pdf.overflow_wrap(nil, :break_word)\n  end\n\n  def test_migrate_overflow_wrap_from_word_wrap\n    assert_equal 'normal', @pdf.migrate_overflow_wrap_from_word_wrap(:break_word)\n    assert_equal 'disable-break-word-by-space', @pdf.migrate_overflow_wrap_from_word_wrap(:none)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/graphics/test_basic.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::Graphics::TestBasic < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def setup\n    @pdf = Thinreports::BasicReport::Generator::PDF::Document.new\n  end\n\n  def test_build_stroke_styles\n    style = {\n      stroke: 'red',\n      stroke_width: 2.0,\n      stroke_type: 'solid'\n    }\n\n    assert_equal(\n      {\n        color: 'ff0000',\n        width: 2.0,\n        dash: nil\n      },\n      @pdf.build_stroke_styles(style)\n    )\n\n    style_stroke_dashed = style.merge(stroke_type: 'dashed')\n    assert_equal [2, 2], @pdf.build_stroke_styles(style_stroke_dashed)[:dash]\n\n    style_stroke_dotted = style.merge(stroke_type: 'dotted')\n    assert_equal [1, 2], @pdf.build_stroke_styles(style_stroke_dotted)[:dash]\n\n    assert_nil @pdf.build_stroke_styles(stroke: nil, stroke_width: 1)\n    assert_nil @pdf.build_stroke_styles(stroke: 'none', stroke_width: 1)\n\n    assert_nil @pdf.build_stroke_styles(stroke_width: nil, stroke: 'red')\n    assert_nil @pdf.build_stroke_styles(stroke_width: 0, stroke: 'red')\n  end\n\n  def test_build_fill_styles\n    assert_equal({ color: 'ff0000' }, @pdf.build_fill_styles(fill: 'red'))\n    assert_nil @pdf.build_fill_styles(fill: nil)\n    assert_nil @pdf.build_fill_styles(fill: 'none')\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/graphics/test_image.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\nrequire 'base64'\n\nclass Thinreports::BasicReport::Generator::PDF::Graphics::TestImage < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def setup\n    format = Thinreports::BasicReport::Layout::Format.build(self.layout_file.path)\n    @document = Thinreports::BasicReport::Generator::PDF::Document.new.tap { |doc|\n      doc.start_new_page(format)\n    }\n  end\n\n  def test_image\n    each_image do |image_filename|\n      @document.image(data_file(image_filename), 0, 0, 100, 100)\n      @document.image(StringIO.new(read_data_file(image_filename)), 0, 100, 100, 100)\n    end\n    assert_equal 6, analyze_pdf_images(@document.render).count\n  end\n\n  def test_base64image\n    each_image do |image_filename|\n      @document.base64image(Base64.encode64(read_data_file(image_filename)), 0, 0, 100, 100)\n    end\n    assert_equal 3, analyze_pdf_images(@document.render).count\n  end\n\n  def test_image_box\n    each_image do |image_filename|\n      @document.image_box(data_file(image_filename), 0, 0, 100, 100)\n      @document.image(StringIO.new(read_data_file(image_filename)), 0, 100, 100, 100)\n    end\n    assert_equal 6, analyze_pdf_images(@document.render).count\n  end\n\n  def test_clean_temp_images\n    @document.base64image(Base64.encode64(read_data_file('image_normal.png')), 0, 0, 100, 100)\n    @document.base64image(Base64.encode64(read_data_file('image_normal.jpg')), 0, 0, 100, 100)\n\n    assert_equal 2, @document.temp_image_registry.size\n\n    image_file_and_paths = @document.temp_image_registry.values.map { |image| [image, image.path] }\n\n    @document.clean_temp_images\n\n    assert_empty @document.temp_image_registry\n\n    image_file_and_paths.each do |file, path|\n      assert_nil file.path\n      refute File.exist?(path)\n    end\n  end\n\n  def each_image(&block)\n    %w(\n      image_normal.png\n      image_normal.jpg\n      image_pallete_based.png\n    ).each { |image_filename| block.call(image_filename) }\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/graphics/test_text.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::Graphics::TestText < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def setup\n    @pdf = Thinreports::BasicReport::Generator::PDF::Document.new\n    @pdf.internal.start_new_page\n  end\n\n  def exec_with_font_styles(attrs = nil, font = nil, &block)\n    attrs ||= {styles: [:bold]}\n    font  ||= {name: 'IPAMincho', size: 18, color: 'ff0000'}\n\n    @pdf.send(:with_font_styles, attrs, font, &block)\n  end\n\n  def exec_with_text_styles(attrs = {}, &block)\n    default_attrs = {font: 'Helvetica',\n                     color: 'ff0000',\n                     size: 18}\n    @pdf.send(:with_text_styles, default_attrs.merge(attrs), &block)\n  end\n\n  def test_with_text_styles_should_not_operate_when_color_is_none\n    exec_with_text_styles(color: 'none') do |_attrs, _styles|\n      flunk\n    end\n  end\n\n  def test_with_text_styles_should_set_leading_via_line_height_attribute\n    exec_with_text_styles(line_height: 30) do |attrs, _styles|\n      expected = @pdf.send(:text_line_leading,\n                           @pdf.send(:s2f, 30),\n                           name: 'Helvetica', size: 18)\n      assert_equal attrs[:leading], expected\n    end\n  end\n\n  def test_with_text_styles_should_not_set_leading_when_line_height_is_not_specified\n    exec_with_text_styles do |attrs, _styles|\n      refute_includes attrs.keys, :leading\n    end\n  end\n\n  def test_with_text_styles_should_set_character_spacing_via_letter_spacing_attribute\n    exec_with_text_styles(letter_spacing: 5) do |attrs, _styles|\n      assert_equal attrs[:character_spacing], @pdf.send(:s2f, 5)\n    end\n  end\n\n  def test_with_text_styles_should_not_set_character_spacing_when_letter_spacing_is_not_specified\n    exec_with_text_styles do |attrs, _styles|\n      refute_includes attrs.keys, :character_spacing\n    end\n  end\n\n  def test_with_text_styles_should_parse_color\n    exec_with_text_styles(color: '#ff0000') do |_attrs, _styles|\n      assert_equal @pdf.internal.fill_color, 'ff0000'\n    end\n  end\n\n  def test_with_font_styles_should_set_fill_color_using_color_of_font\n    exec_with_font_styles do |_attrs, _styles|\n      assert_equal @pdf.internal.fill_color, 'ff0000'\n    end\n  end\n\n  def test_with_font_styles_should_perform_manual_style_when_bold_style_cannot_be_applied\n    exec_with_font_styles do |_attrs, styles|\n      assert_empty styles\n    end\n  end\n\n  def test_with_font_styles_should_perform_manual_style_when_italic_style_cannot_be_applied\n    exec_with_font_styles do |_attrs, styles|\n      assert_empty styles\n    end\n  end\n\n  def test_with_font_styles_should_set_stroke_color_using_color_of_font_when_bold_style_cannot_be_applied\n    exec_with_font_styles do |_attrs, _styles|\n      assert_equal @pdf.internal.stroke_color, 'ff0000'\n    end\n  end\n\n  def test_with_font_styles_should_set_line_width_calculated_from_font_size_when_bold_style_cannot_be_applied\n    exec_with_font_styles do |_attrs, _styles|\n      assert_equal @pdf.internal.line_width, 18 * 0.025\n    end\n  end\n\n  def test_with_font_styles_should_set_mode_to_fill_stroke_when_bold_style_cannot_be_applied\n    exec_with_font_styles do |attrs, _styles|\n      assert_equal attrs[:mode], :fill_stroke\n    end\n  end\n\n  def test_with_font_styles_should_not_perform_a_manual_style_when_bold_style_can_be_applied\n    exec_with_font_styles(nil, name: 'Helvetica', size: 12, color: '0000ff') do |_attrs, styles|\n      assert_includes styles, :bold\n    end\n  end\n\n  def test_with_font_styles_should_not_perform_a_manual_style_when_italic_style_can_be_applied\n    exec_with_font_styles({styles: [:italic]}, name: 'Helvetica', size: 12, color: 'ff0000') do |_attrs, styles|\n      assert_includes styles, :italic\n    end\n  end\n\n  def test_text_line_leading_should_return_a_specified_leading_value_minus_the_font_height\n    font = {name: 'IPAMincho', size: 36}\n    font_height = @pdf.internal.font(font[:name], size: font[:size]).height\n\n    assert_equal @pdf.send(:text_line_leading, 100, font), 100 - font_height\n  end\n\n  def test_replace_space_to_nbsp_should_replace_the_spaces_NBSP\n    assert_equal @pdf.send(:replace_space_to_nbsp, ' ' * 2), Prawn::Text::NBSP * 2\n  end\n\n  def test_text_box_should_not_raise_PrawnCannotFitError\n    @pdf.text_box('foo', 0, 0, 1, 1, font: 'IPAMincho',\n                                     size: 100,\n                                     color: '000000')\n  rescue Prawn::Errors::CannotFit\n    flunk('Raise Prawn::Errors::CannotFit.')\n  end\n\n  def test_text_box_attrs_should_return_a_Hash_containing_a_at_and_width_options\n    attrs = @pdf.send(:text_box_attrs, 0, 0, 50, 100)\n\n    assert_equal attrs.values_at(:at, :width),\n                 [@pdf.send(:pos, 0, 0), @pdf.send(:s2f, 50)]\n  end\n\n  def test_text_box_attrs_should_return_a_Hash_which_doesnt_contain_the_single_line_option_when_single_is_true_but_overflow_is_expand\n    attrs = @pdf.send(:text_box_attrs, 0, 0, 100, 100, single: true, overflow: :expand)\n    refute attrs.key?(:single_line)\n  end\n\n  def test_text_box_attrs_should_return_a_Hash_containing_a_single_line_option_when_single_is_true_and_overflow_isnot_expand\n    attrs = @pdf.send(:text_box_attrs, 0, 0, 100, 100, single: true, overflow: :truncate)\n    assert_equal attrs[:single_line], true\n  end\n\n  def test_text_box_attrs_should_return_a_Hash_which_does_not_contain_a_height_option_when_single_is_true\n    attrs = @pdf.send(:text_box_attrs, 0, 0, 100, 100, single: true)\n    refute attrs.key?(:height)\n  end\n\n  def test_text_box_attrs_should_return_a_Hash_which_does_not_contain_a_single_line_option_when_single_is_not_specified\n    attrs = @pdf.send(:text_box_attrs, 0, 0, 100, 100)\n    refute attrs.key?(:single_line)\n  end\n\n  def test_text_box_attrs_should_return_a_Hash_containing_a_height_optin_when_single_is_not_specified\n    attrs = @pdf.send(:text_box_attrs, 0, 0, 100, 200)\n    assert_equal attrs[:height], 200\n  end\n\n  def test_text\n    @pdf.expects(:text_box).\n      with('contents', 100, 200, 150, 250, { overflow: :shirink_to_fit }).once\n\n    @pdf.text('contents', 100, 200, 150, 250)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/test_font.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::TestFont < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Font = Thinreports::BasicReport::Generator::PDF::Font\n\n  def teardown\n    # Reset font settings\n    Thinreports.configure do |c|\n      c.fallback_fonts = []\n    end\n  end\n\n  def test_setup_fonts\n    pdf = document.pdf\n\n    Font::BUILTIN_FONTS.each do |name, path|\n      expected_font = {\n        normal: path,\n        bold: path,\n        italic: path,\n        bold_italic: path\n      }\n      assert_equal expected_font, pdf.font_families[name]\n    end\n\n    Font::PRAWN_BUINTIN_FONT_ALIASES.each do |alias_font, original_font|\n      assert_equal pdf.font_families[alias_font],\n                   pdf.font_families[original_font]\n    end\n\n    assert_equal Font::DEFAULT_FALLBACK_FONTS, %w[IPAMincho]\n  end\n\n  def test_setup_fonts_with_custom_fallback_fonts\n    Thinreports.configure do |c|\n      c.fallback_fonts = []\n    end\n    assert_equal Font::DEFAULT_FALLBACK_FONTS,\n                 document.pdf.fallback_fonts\n\n    Thinreports.configure do |c|\n      c.fallback_fonts = 'IPAGothic'\n    end\n    assert_equal ['IPAGothic'] + Font::DEFAULT_FALLBACK_FONTS,\n                 document.pdf.fallback_fonts\n\n    Thinreports.configure do |c|\n      c.fallback_fonts = ['IPAMincho']\n    end\n    assert_equal ['IPAMincho'] + Font::DEFAULT_FALLBACK_FONTS,\n                 document.pdf.fallback_fonts\n\n    Thinreports.configure do |c|\n      c.fallback_fonts = ['IPAMincho', data_file('font.ttf')]\n    end\n    assert_equal ['IPAMincho', 'Custom-fallback-font1'] + Font::DEFAULT_FALLBACK_FONTS,\n                 document.pdf.fallback_fonts\n  end\n\n  def test_setup_fonts_with_unknown_custom_fallback_fonts\n    Thinreports.configure do |c|\n      c.fallback_fonts = ['/path/to/unknown.ttf']\n    end\n\n    assert_raises Thinreports::BasicReport::Errors::FontFileNotFound do\n      create_document\n    end\n  end\n\n  def test_default_family\n    assert_equal 'Helvetica', document.default_family\n  end\n\n  def test_default_family_if_mmissing\n    assert_equal 'Helvetica', document.default_family_if_missing('unknown')\n    assert_equal 'IPAMincho', document.default_family_if_missing('IPAMincho')\n  end\n\n  def test_font_has_style?\n    doc = create_document\n\n    assert_equal false, doc.font_has_style?('unknown', :bold)\n\n    doc.pdf.font_families['font_foo'] = {\n      normal: '/path/to/foo.ttf'\n    }\n    assert_equal false, doc.font_has_style?('font_foo', :italic)\n\n    doc.pdf.font_families['font_foo'] = {\n      normal: '/path/to/foo.ttf',\n      bold: '/path/to/foo.ttf'\n    }\n    assert_equal false, doc.font_has_style?('font_foo', :bold)\n\n    doc.pdf.font_families['font_foo'] = {\n      normal: '/path/to/foo.ttf',\n      bold: '/path/to/foo_bold.ttf'\n    }\n    assert_equal true, doc.font_has_style?('font_foo', :bold)\n  end\n\n  def document\n    Thinreports::BasicReport::Generator::PDF::Document.new\n  end\n  alias_method :create_document, :document\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/test_graphics.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::TestGraphics < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  class TestGraphics\n    attr_accessor :pdf\n    include Thinreports::BasicReport::Generator::PDF::Graphics\n  end\n\n  def setup\n    @g = TestGraphics.new\n    @g.pdf = mock('pdf')\n  end\n\n  def test_setup_custom_graphic_states\n    @g.pdf.expects(:line_width).\n      with(TestGraphics::BASE_LINE_WIDTH).once\n\n    @g.send(:setup_custom_graphic_states)\n  end\n\n  def test_line_width\n    @g.pdf.\n      expects(:line_width).\n      with(10 * TestGraphics::BASE_LINE_WIDTH).once\n\n    @g.send(:line_width, 10)\n  end\n\n  def test_save_graphics_state\n    @g.pdf.expects(:save_graphics_state).once\n    @g.send(:save_graphics_state)\n  end\n\n  def test_restore_graphics_state\n    @g.pdf.expects(:restore_graphics_state).once\n    @g.send(:restore_graphics_state)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/test_page.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::Document::TestPage < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def create_pdf\n    @pdf = Thinreports::BasicReport::Generator::PDF::Document.new\n  end\n\n  def test_JIS_page_size\n    sizes = Thinreports::BasicReport::Generator::PDF::Document::JIS_SIZES\n    assert_equal sizes['B4'], [728.5, 1031.8]\n    assert_equal sizes['B5'], [515.9, 728.5]\n  end\n\n  def test_B4_paper_size_should_returns_size_as_B4_JIS\n    create_pdf\n\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    format.stubs(page_paper_type: 'B4')\n\n    @pdf.start_new_page(format)\n    assert_equal @pdf.internal.page.size, [728.5, 1031.8]\n  end\n\n  def test_B4_ISO_paper_size_should_be_converted_to_B4\n    create_pdf\n\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    format.stubs(page_paper_type: 'B4_ISO')\n\n    @pdf.start_new_page(format)\n    assert_equal @pdf.internal.page.size, 'B4'\n  end\n\n  def test_change_page_format_should_return_true_at_first_time\n    create_pdf\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n\n    assert_equal @pdf.send(:change_page_format?, format), true\n  end\n\n  def test_change_page_format_should_return_false_when_given_the_same_format\n    create_pdf\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n\n    @pdf.instance_variable_set(:@current_page_format, format)\n    assert_equal @pdf.send(:change_page_format?, format), false\n  end\n\n  def test_change_page_format_should_return_true_when_given_the_other_format\n    create_pdf\n    format1 = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    format2 = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n\n    @pdf.instance_variable_set(:@current_page_format, format1)\n    assert_equal @pdf.send(:change_page_format?, format2), true\n  end\n\n  def test_new_basic_page_options\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    options = create_pdf.send(:new_basic_page_options, format)\n\n    assert_equal options[:layout], format.page_orientation.to_sym\n    assert_equal options[:size], format.page_paper_type\n  end\n\n  def test_new_basic_page_options_when_the_layout_has_customize_size\n    format = stub user_paper_type?: true,\n                  page_width: 100,\n                  page_height: 100,\n                  page_orientation: 'portrait'\n\n    options = create_pdf.send(:new_basic_page_options, format)\n    assert_equal options[:size], [100, 100]\n  end\n\n  def test_start_new_page_should_create_stamp\n    create_pdf\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    @pdf.start_new_page(format)\n\n    assert_includes @pdf.send(:format_stamp_registry), format.identifier\n  end\n\n  def test_start_new_page_should_not_create_stamp\n    create_pdf\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    @pdf.start_new_page(format)\n    @pdf.start_new_page(format)\n\n    assert_equal @pdf.send(:format_stamp_registry).size, 1\n  end\n\n  def test_start_new_page_should_stamp_constantly\n    create_pdf\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n    @pdf.expects(:stamp).with(format.identifier.to_s).times(2)\n\n    @pdf.start_new_page(format)\n    @pdf.start_new_page(format)\n  end\n\n  def test_add_blank_page_should_create_an_A4_size_page_in_first_page\n    create_pdf\n    @pdf.internal.expects(:start_new_page).with({size: 'A4'}).once\n\n    @pdf.add_blank_page\n  end\n\n  def test_add_blank_page_should_call_with_no_arguments_since_second_page\n    create_pdf\n    format = Thinreports::BasicReport::Layout::Format.build(layout_file.path)\n\n    @pdf.start_new_page(format)\n    @pdf.internal.expects(:start_new_page).with({}).once\n\n    @pdf.add_blank_page\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/document/test_parse_color.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::TestParseColor < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  class TestColorParser\n    include Thinreports::BasicReport::Generator::PDF::ParseColor\n  end\n\n  def setup\n    @parser = TestColorParser.new\n  end\n\n  def test_parse_color_with_hexcolor\n    assert_equal @parser.parse_color('#ff0000'), 'ff0000'\n    assert_equal @parser.parse_color('000000'), '000000'\n  end\n\n  def test_parse_color_with_colorname\n    assert_equal @parser.parse_color('red'), 'ff0000'\n  end\n\n  def test_parse_color_with_colorname_raise_when_unknown_name_given\n    assert_raises Thinreports::BasicReport::Errors::UnsupportedColorName do\n      @parser.parse_color('whitesmoke')\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/prawn_ext/test_calc_image_dimensions.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PrawnExt::TestCalcImageDimensions < Minitest::Test\n  class Klass\n    prepend Thinreports::BasicReport::Generator::PrawnExt::CalcImageDimensions\n\n    def calc_image_dimensions(options)\n      options\n    end\n  end\n\n  def setup\n    @klass = Klass.new\n  end\n\n  def test_calc_image_dimensions\n    res_options = @klass.calc_image_dimensions(\n      auto_fit: [100, 200],\n      width: 101,\n      height: 199\n    )\n    assert_equal [100, 200], res_options[:fit]\n    refute_includes res_options.keys, :auto_fit\n\n    res_options = @klass.calc_image_dimensions(\n      auto_fit: [100, 200],\n      width: 99,\n      height: 201\n    )\n    assert_equal [100, 200], res_options[:fit]\n\n    res_options = @klass.calc_image_dimensions(\n      auto_fit: [100, 200],\n      width: 99,\n      height: 199\n    )\n    refute_includes res_options.keys, :fit\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/prawn_ext/test_width_of.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PrawnExt::TestWidthOf < Minitest::Test\n  def setup\n    @pdf = Prawn::Document.new\n  end\n\n  def test_width_of\n    text_width = @pdf.width_of('abcd')\n\n    @pdf.character_spacing(1) do\n      expected_character_space_width = 1 * 3\n      assert_equal text_width + expected_character_space_width, @pdf.width_of('abcd')\n    end\n\n    @pdf.character_spacing(1) do\n      assert_equal 0, @pdf.width_of('')\n    end\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/pdf/test_document.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::PDF::TestDocument < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Document = Thinreports::BasicReport::Generator::PDF::Document\n\n  def test_new\n    pdf = Document.new\n    assert_equal pdf.internal.page_count, 0\n    assert_equal pdf.internal.page.margins.values, [0, 0, 0, 0]\n\n    pdf = Document.new(security: { owner_password: 'abc' })\n    assert_equal true, pdf.internal.state.encrypt\n\n    pdf = Document.new(title: 'Title')\n    assert_equal 'Title', pdf.internal.state.store.info.data[:Title]\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/generator/test_pdf.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Generator::TestPDF < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  PDF = Thinreports::BasicReport::Generator::PDF\n\n  def test_default_layout\n    layout_filename = layout_file.path\n    report = Thinreports::BasicReport::Report.new layout: layout_filename\n\n    generator = PDF.new report\n    assert_equal layout_filename, generator.default_layout.filename\n  end\n\n  def test_initialize\n    report = Thinreports::BasicReport::Report.new layout: layout_file.path\n    report.start_new_page\n\n    PDF.new(report)\n\n    assert_equal true, report.finalized?\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/layout/test_base.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Layout::TestBase < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Layout = Thinreports::BasicReport::Layout\n\n  def test_load_format\n    assert_instance_of Layout::Format, Layout::Base.load_format(layout_file.path)\n    assert_raises Thinreports::BasicReport::Errors::LayoutFileNotFound do\n      Layout::Base.load_format 'unknown.tlf'\n    end\n  end\n\n  def test_new\n    layout_filename = layout_file.path\n    layout = Layout::Base.new(layout_filename)\n\n    assert_nil layout.id\n    assert_equal layout_filename, layout.filename\n    assert_instance_of Layout::Format, layout.format\n  end\n\n  def test_id\n    layout_without_id = Layout::Base.new(layout_file.path)\n    assert_nil layout_without_id.id\n\n    layout_with_id = Layout::Base.new(layout_file.path, id: 'foo')\n    assert_equal 'foo', layout_with_id.id\n  end\n\n  def test_default?\n    layout_without_id = Layout::Base.new(layout_file.path)\n    assert_equal true, layout_without_id.default?\n\n    layout_with_id = Layout::Base.new(layout_file.path, id: 'bar')\n    assert_equal false, layout_with_id.default?\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/layout/test_format.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Layout::TestFormat < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  LAYOUT_SCHEMA = {\n    'version' => '0.9.0',\n    'title' => 'Report Title',\n    'report' => {\n      'paper-type' => 'A4',\n      'width' => 100.0,\n      'height' => 200.0,\n      'orientation' => 'landscape',\n      'margin' => [100.0, 200.0, 300.0, 999.9]\n    },\n    'state' => {\n      'layout-guides' => [\n        { 'type' => 'x', 'position' => 0.1 }\n      ]\n    },\n    'items' => [\n      { 'type'=> 'rect', 'id'=> '', 'x'=> 100.0, 'y'=> 100.0, 'width'=> 100.0, 'height'=> 100.0, 'style'=> {'stroke-width'=> 1}},\n      { 'type'=> 'text-block', 'id'=> 'text_block', 'x'=> 100.0, 'y'=> 100.0 },\n      { 'type'=> 'page-number', 'id'=> '', 'x'=> 100.0, 'y'=> 100.0 }\n    ]\n  }\n\n  Shape = Thinreports::BasicReport::Core::Shape\n  Layout = Thinreports::BasicReport::Layout\n\n  def test_attribute_readers\n    format = Layout::Format.new(layout_schema)\n\n    assert_equal 'Report Title', format.report_title\n    assert_equal Thinreports::VERSION, format.last_version\n    assert_equal 'A4', format.page_paper_type\n    assert_equal 100.0, format.page_width\n    assert_equal 200.0, format.page_height\n    assert_equal 'landscape', format.page_orientation\n  end\n\n  def test_user_paper_type?\n    format_paper_type_is_not_user = Layout::Format.new(layout_schema)\n    assert_equal false, format_paper_type_is_not_user.user_paper_type?\n\n    format_paper_type_is_user = Layout::Format.new(layout_schema.merge(\n      {\n        'report' => {\n          'paper-type' => 'user'\n        }\n      }\n    ))\n    assert_equal true, format_paper_type_is_user.user_paper_type?\n  end\n\n  def test_build\n    compatible_layout_file = layout_file\n    assert_instance_of Layout::Format, Layout::Format.build(compatible_layout_file.path)\n\n    incompatible_layout_file = layout_file(version: '0.0.1')\n    assert_raises Thinreports::BasicReport::Errors::IncompatibleLayoutFormat do\n      Layout::Format.build(incompatible_layout_file.path)\n    end\n  end\n\n  def test_build_legacy_layout\n    format = nil\n\n    assert_deprecated { format = Layout::Format.build(data_file('legacy_layout', 'all-items.tlf')) }\n\n    assert_equal 'Report Title', format.report_title\n    assert_equal '0.8.2', format.last_version\n    assert_equal 'A4', format.page_paper_type\n    assert_equal 'portrait', format.page_orientation\n\n    item_types = format.attributes['items'].map { |items| items['type'] }\n\n    assert_equal 9, item_types.count\n    assert_equal %w( rect ellipse line image image-block text-block list page-number text ).sort,\n      item_types.sort\n  end\n\n  def test_initialize_items\n    format = Layout::Format.new(layout_schema)\n\n    assert_equal 2, format.shapes.count\n\n    shape_classes = format.shapes.values.map(&:class)\n    assert_includes shape_classes, Shape::TextBlock::Format\n    assert_includes shape_classes, Shape::PageNumber::Format\n  end\n\n  private\n\n  def layout_schema(version = Thinreports::VERSION)\n    LAYOUT_SCHEMA.merge('version' => version)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/layout/test_legacy_schema.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Layout::TestLegacySchema < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Layout = Thinreports::BasicReport::Layout\n\n  def test_upgrade\n    legacy_schema = {\n      'version' => '0.8.2',\n      'finger-print' => 'abcd',\n      'config' => {\n        'title' => 'Report Title',\n        'page' => {\n          'paper-type' => 'A4',\n          'width' => '100.0',\n          'height' => '200.0',\n          'orientation' => 'landscape',\n          'margin-top' => '0.1',\n          'margin-right' => '0.2',\n          'margin-bottom' => '0.3',\n          'margin-left' => '0.4'\n        }\n      },\n      'svg' => '<svg><g class=\"canvas\"></g></svg>',\n      'state' => {\n        'layout-guide' => []\n      }\n    }\n\n    assert_equal(\n      {\n        'version' => '0.8.2',\n        'title' => 'Report Title',\n        'report' => {\n          'paper-type' => 'A4',\n          'width' => 100.0,\n          'height' => 200.0,\n          'orientation' => 'landscape',\n          'margin' => [0.1, 0.2, 0.3, 0.4]\n        },\n        'items' => []\n      },\n      Layout::LegacySchema.new(legacy_schema).upgrade\n    )\n  end\n\n  def test_text_item_schema\n    legacy_attributes = {\n      'x-id' => 'text_id',\n      'x-left' => '100.1',\n      'x-top' => '200.1',\n      'x-width' => '300.1',\n      'x-height' => '400.1',\n      'x-display' => 'true',\n      'font-family' => 'Helvetica',\n      'font-size' => '18',\n      'font-weight' => 'normal',\n      'font-style' => 'normal',\n      'text-decoration' => 'underline line-through',\n      'fill' => 'red',\n      'text-anchor' => 'start',\n      'x-valign' => 'top',\n      'x-line-height' => '20.1',\n      'kerning' => '2.1'\n    }\n    legacy_texts = %w( line1 line2 )\n\n    assert_equal(\n      {\n        'id' => 'text_id',\n        'type' => 'text',\n        'x' => 100.1,\n        'y' => 200.1,\n        'width' => 300.1,\n        'height' => 400.1,\n        'display' => true,\n        'texts' => %w( line1 line2 ),\n        'style' => {\n          'font-family' => %w( Helvetica ),\n          'font-size' => 18.0,\n          'color' => 'red',\n          'font-style' => %w( underline linethrough ),\n          'text-align' => 'left',\n          'vertical-align' => 'top',\n          'line-height' => 20.1,\n          'letter-spacing' => 2.1\n        }\n      },\n      layout_legacy_schema.text_item_schema(legacy_attributes, legacy_texts)\n    )\n  end\n\n  def test_rect_item_schema\n    legacy_attributes = {\n      'x-id' => 'rect_id',\n      'x' => '100.1',\n      'y' => '200.1',\n      'width' => '300.1',\n      'height' => '400.1',\n      'x-display' => 'false',\n      'stroke-width' => '2.5',\n      'stroke' => '#ff0000',\n      'x-stroke-type' => 'dotted',\n      'fill' => 'red',\n      'rx' => '2'\n    }\n    assert_equal(\n      {\n        'id' => 'rect_id',\n        'type' => 'rect',\n        'x' => 100.1,\n        'y' => 200.1,\n        'width' => 300.1,\n        'height' => 400.1,\n        'display' => false,\n        'border-radius' => 2,\n        'style' => {\n          'border-width' => 2.5,\n          'border-color' => '#ff0000',\n          'border-style' => 'dotted',\n          'fill-color' => 'red'\n        }\n      },\n      layout_legacy_schema.rect_item_schema(legacy_attributes)\n    )\n  end\n\n  def test_line_item_schema\n    legacy_attributes = {\n      'x-id' => 'line_id',\n      'x1' => '100.1',\n      'y1' => '200.1',\n      'x2' => '300.1',\n      'y2' => '400.1',\n      'x-display' => 'true',\n      'stroke-width' => '1',\n      'stroke' => 'red',\n      'x-stroke-type' => 'solid'\n    }\n    assert_equal(\n      {\n        'id' => 'line_id',\n        'type' => 'line',\n        'x1' => 100.1,\n        'y1' => 200.1,\n        'x2' => 300.1,\n        'y2' => 400.1,\n        'display' => true,\n        'style' => {\n          'border-width' => 1.0,\n          'border-color' => 'red',\n          'border-style' => 'solid'\n        }\n      },\n      layout_legacy_schema.line_item_schema(legacy_attributes)\n    )\n  end\n\n  def test_ellipse_item_schema\n    legacy_attributes = {\n      'x-id' => 'ellipse_id',\n      'cx' => '100.1',\n      'cy' => '200.1',\n      'rx' => '300.1',\n      'ry' => '400.1',\n      'x-display' => 'true',\n      'stroke-width' => '1',\n      'stroke' => 'red',\n      'x-stroke-type' => 'solid',\n      'fill' => 'blue'\n    }\n    assert_equal(\n      {\n        'id' => 'ellipse_id',\n        'type' => 'ellipse',\n        'cx' => 100.1,\n        'cy' => 200.1,\n        'rx' => 300.1,\n        'ry' => 400.1,\n        'display' => true,\n        'style' => {\n          'border-width' => 1.0,\n          'border-color' => 'red',\n          'border-style' => 'solid',\n          'fill-color' => 'blue'\n        }\n      },\n      layout_legacy_schema.ellipse_item_schema(legacy_attributes)\n    )\n  end\n\n  def test_image_item_schema\n    legacy_attributes = {\n      'x-id' => 'image_id',\n      'x' => '100.1',\n      'y' => '200.1',\n      'width' => '300.1',\n      'height' => '400.1',\n      'x-display' => 'true',\n      'xlink:href' => 'data:image/png;base64,xxxxxxxxxxxxx'\n    }\n    assert_equal(\n      {\n        'id' => 'image_id',\n        'type' => 'image',\n        'x' => 100.1,\n        'y' => 200.1,\n        'width' => 300.1,\n        'height' => 400.1,\n        'display' => true,\n        'data' => {\n          'mime-type' => 'image/png',\n          'base64' => 'xxxxxxxxxxxxx'\n        }\n      },\n      layout_legacy_schema.image_item_schema(legacy_attributes)\n    )\n  end\n\n  def test_page_number_item_schema\n    legacy_attributes = {\n      'x-id' => 'page_number_id',\n      'x-left' => '100.1',\n      'x-top' => '200.1',\n      'x-width' => '300.1',\n      'x-height' => '400.1',\n      'x-format' => '{page}',\n      'x-target' => 'report',\n      'x-display' => 'true',\n      'font-family' => 'IPAMincho',\n      'font-size' => '18.5',\n      'fill' => 'red',\n      'font-weight' => 'bold',\n      'font-style' => 'italic',\n      'text-decoration' => '',\n      'text-anchor' => 'end',\n      'x-overflow' => 'fit'\n    }\n    assert_equal(\n      {\n        'id' => 'page_number_id',\n        'type' => 'page-number',\n        'x' => 100.1,\n        'y' => 200.1,\n        'width' => 300.1,\n        'height' => 400.1,\n        'format' => '{page}',\n        'target' => 'report',\n        'display' => true,\n        'style' => {\n          'font-family' => %w( IPAMincho ),\n          'font-size' => 18.5,\n          'color' => 'red',\n          'font-style' => %w( bold italic ),\n          'text-align' => 'right',\n          'overflow' => 'fit'\n        }\n      },\n      layout_legacy_schema.page_number_item_schema(legacy_attributes)\n    )\n  end\n\n  def test_image_block_item_schema\n    legacy_attributes = {\n      'x-id' => 'image_block_id',\n      'x-left' => '100.1',\n      'x-top' => '200.1',\n      'x-width' => '300.1',\n      'x-height' => '400.1',\n      'x-display' => 'false',\n      'x-position-x' => 'right',\n      'x-position-y' => 'bottom'\n    }\n    assert_equal(\n      {\n        'id' => 'image_block_id',\n        'type' => 'image-block',\n        'x' => 100.1,\n        'y' => 200.1,\n        'width' => 300.1,\n        'height' => 400.1,\n        'display' => false,\n        'style' => {\n          'position-x' => 'right',\n          'position-y' => 'bottom'\n        }\n      },\n      layout_legacy_schema.image_block_item_schema(legacy_attributes)\n    )\n  end\n\n  def test_text_block_schema\n    base_legacy_attributes = {\n      'x-id' => 'text_block_id',\n      'x-left' => '100.1',\n      'x-top' => '200.1',\n      'x-width' => '300.1',\n      'x-height' => '400.1',\n      'x-display' => 'true',\n      'x-value' => 'default value',\n      'x-multiple' => 'true',\n      'font-family' => 'Helvetica',\n      'font-size' => '18',\n      'font-weight' => 'bold',\n      'font-style' => 'normal',\n      'text-decoration' => 'line-through',\n      'fill' => 'red',\n      'text-anchor' => 'start',\n      'x-valign' => 'top',\n      'x-line-height' => '20.1',\n      'kerning' => '2.1',\n      'x-overflow' => 'expand',\n      'x-word-wrap' => 'break-word',\n      'x-format-base' => '$ {value}',\n      'x-format-type' => '',\n      'x-ref-id' => 'other_text_block_id'\n    }\n    assert_equal(\n      {\n        'id' => 'text_block_id',\n        'type' => 'text-block',\n        'x' => 100.1,\n        'y' => 200.1,\n        'width' => 300.1,\n        'height' => 400.1,\n        'display' => true,\n        'value' => 'default value',\n        'multiple-line' => true,\n        'reference-id' => 'other_text_block_id',\n        'format' => {\n          'base' => '$ {value}',\n          'type' => ''\n        },\n        'style' => {\n          'font-family' => %w( Helvetica ),\n          'font-size' => 18.0,\n          'color' => 'red',\n          'font-style' => %w( bold linethrough ),\n          'text-align' => 'left',\n          'vertical-align' => 'top',\n          'line-height' => 20.1,\n          'letter-spacing' => 2.1,\n          'overflow' => 'expand',\n          'word-wrap' => 'break-word'\n        }\n      },\n      layout_legacy_schema.text_block_item_schema(base_legacy_attributes)\n    )\n\n    schema_with_datetime_format = layout_legacy_schema.text_block_item_schema(base_legacy_attributes.merge(\n      'x-format-type' => 'datetime',\n      'x-format-datetime-format' => '%Y'\n    ))\n    assert_equal(\n      {\n        'base' => '$ {value}',\n        'type' => 'datetime',\n        'datetime' => {\n          'format' => '%Y'\n        }\n      },\n      schema_with_datetime_format['format']\n    )\n\n    schema_with_number_format = layout_legacy_schema.text_block_item_schema(base_legacy_attributes.merge(\n      'x-format-type' => 'number',\n      'x-format-number-precision' => '1',\n      'x-format-number-delimiter' => ','\n    ))\n    assert_equal(\n      {\n        'base' => '$ {value}',\n        'type' => 'number',\n        'number' => {\n          'delimiter' => ',',\n          'precision' => 1\n        }\n      },\n      schema_with_number_format['format']\n    )\n\n    schema_with_padding_format = layout_legacy_schema.text_block_item_schema(base_legacy_attributes.merge(\n      'x-format-type' => 'padding',\n      'x-format-padding-char' => '0',\n      'x-format-padding-length' => '10',\n      'x-format-padding-direction' => 'L'\n    ))\n    assert_equal(\n      {\n        'base' => '$ {value}',\n        'type' => 'padding',\n        'padding' => {\n          'length' => 10,\n          'char' => '0',\n          'direction' => 'L'\n        }\n      },\n      schema_with_padding_format['format']\n    )\n  end\n\n  def test_list_item_schema\n    legacy_schema = {\n      'id' => 'default',\n      'type' => 's-list',\n      'content-height' => '300',\n      'page-break' => 'true',\n      'display' => 'false',\n      'header-enabled' => 'false',\n      'page-footer-enabled' => 'true',\n      'footer-enabled' => 'true',\n      'header' => {\n        'height' => '100.1',\n        'translate' => {\n          'x' => '100',\n          'y' => '200'\n        },\n        'svg' => { 'content' => '' }\n      },\n      'detail' => {\n        'height' => '200.1',\n        'translate' => {\n          'x' => '300',\n          'y' => '400'\n        },\n        'svg' => { 'content' => '' }\n      },\n      'page-footer' => {\n        'height' => '300.1',\n        'translate' => {\n          'x' => '500',\n          'y' => '600'\n        },\n        'svg' => { 'content' => '' }\n      },\n      'footer' => {\n        'height' => '400.1',\n        'translate' => {\n          'x' => '700',\n          'y' => '800'\n        },\n        'svg' => { 'content' => '' }\n      }\n    }\n\n    layout_legacy_schema.stubs(:legacy_item_schemas).returns({ 'default' => legacy_schema })\n\n    legacy_element = mock()\n    legacy_element.stubs(:attributes).returns({ 'x-id' => 'default' })\n    legacy_element.stubs(:elements).returns({})\n\n    assert_equal(\n      {\n        'id' => 'default',\n        'type' => 'list',\n        'content-height' => 300.0,\n        'auto-page-break' => true,\n        'display' => false,\n        'header' => {\n          'height' => 100.1,\n          'translate' => {\n            'x' => 100.0,\n            'y' => 200.0\n          },\n          'items' => [],\n          'enabled' => false\n        },\n        'detail' => {\n          'height' => 200.1,\n          'translate' => {\n            'x' => 300.0,\n            'y' => 400.0\n          },\n          'items' => []\n        },\n        'page-footer' => {\n          'height' => 300.1,\n          'translate' => {\n            'x' => 500.0,\n            'y' => 800.1\n          },\n          'items' => [],\n          'enabled' => true\n        },\n        'footer' => {\n          'height' => 400.1,\n          'translate' => {\n            'x' => 700.0,\n            'y' => 1300.2\n          },\n          'items' => [],\n          'enabled' => true\n        }\n      },\n      layout_legacy_schema.list_item_schema(legacy_element)\n    )\n  end\n\n  def test_image_position_y\n    assert_equal 'top', layout_legacy_schema.image_position_y('top')\n    assert_equal 'middle', layout_legacy_schema.image_position_y('center')\n    assert_equal 'bottom', layout_legacy_schema.image_position_y('bottom')\n  end\n\n  def test_display\n    assert_equal true, layout_legacy_schema.display('true')\n    assert_equal false, layout_legacy_schema.display('false')\n  end\n\n  def test_font_style\n    no_style = {\n      'font-weight' => 'normal',\n      'font-style' => 'normal',\n      'text-decoration' => 'none'\n    }\n    assert_equal [], layout_legacy_schema.font_style(no_style)\n    assert_equal %w( bold ), layout_legacy_schema.font_style(no_style.merge('font-weight' => 'bold'))\n    assert_equal %w( italic ), layout_legacy_schema.font_style(no_style.merge('font-style' => 'italic'))\n    assert_equal %w( underline ), layout_legacy_schema.font_style(no_style.merge('text-decoration' => 'underline'))\n    assert_equal %w( linethrough ), layout_legacy_schema.font_style(no_style.merge('text-decoration' => 'line-through'))\n    assert_equal %w( underline linethrough ), layout_legacy_schema.font_style(no_style.merge('text-decoration' => 'line-through underline'))\n  end\n\n  def test_text_align\n    assert_equal 'left', layout_legacy_schema.text_align('start')\n    assert_equal 'center', layout_legacy_schema.text_align('middle')\n    assert_equal 'right', layout_legacy_schema.text_align('end')\n  end\n\n  def test_vertical_align\n    assert_equal '', layout_legacy_schema.vertical_align(nil)\n    assert_equal 'top', layout_legacy_schema.vertical_align('top')\n    assert_equal 'middle', layout_legacy_schema.vertical_align('center')\n    assert_equal 'bottom', layout_legacy_schema.vertical_align('bottom')\n    assert_equal 'top', layout_legacy_schema.vertical_align('')\n  end\n\n  def test_line_height\n    assert_equal '', layout_legacy_schema.line_height('')\n    assert_equal '', layout_legacy_schema.line_height(nil)\n    assert_equal 20.1, layout_legacy_schema.line_height('20.1')\n  end\n\n  def test_letter_spacing\n    assert_equal '', layout_legacy_schema.letter_spacing('')\n    assert_equal '', layout_legacy_schema.letter_spacing('auto')\n    assert_equal 2.5, layout_legacy_schema.letter_spacing('2.5')\n  end\n\n  def test_extract_item_schemas\n    svg = <<-SVG\n<!--SHAPE{\"id\":\"item1\"}SHAPE-->\n<!--LAYOUT<rect id=\"item2\"/>LAYOUT-->\n<!--SHAPE{\"id\":\"item3\"}SHAPE-->\nSVG\n    assert_equal(\n      { 'item1' => { 'id' => 'item1' }, 'item3' => { 'id' => 'item3' } },\n      layout_legacy_schema.extract_legacy_item_schemas(svg)\n    )\n  end\n\n  def test_cleanup_svg\n    svg = '<!--SHAPE{\"id\":\"item1\"}SHAPE--><!--LAYOUT<rect id=\"item2\"/>LAYOUT--><!--SHAPE{\"id\":\"item2\"}SHAPE-->'\n\n    assert_equal '<rect id=\"item2\"/>', layout_legacy_schema.cleanup_svg(svg)\n  end\n\n  private\n\n  def layout_legacy_schema\n    @layout_legacy_schema ||= Layout::LegacySchema.new({ 'svg' => '' })\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/layout/test_version.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Layout::TestVersion < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Version = Thinreports::BasicReport::Layout::Version\n\n  def test_compatible?\n    Version.stubs(:compatible_rules).returns(['>= 0.8.0', '< 1.0.0'])\n\n    assert Version.new('0.8.0').compatible?\n    assert Version.new('0.9.9').compatible?\n    assert Version.new('0.10.0').compatible?\n\n    refute Version.new('0.7.9').compatible?\n    refute Version.new('1.0.0').compatible?\n  end\n\n  def test_legacy?\n    assert Version.new('0.8.9').legacy?\n    refute Version.new('0.9.0').legacy?\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/report/test_base.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Report::TestBase < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Report = Thinreports::BasicReport::Report\n\n  def setup\n    @report = Report::Base.new\n    @layout_file = layout_file\n  end\n\n  def test_on_page_create_callback\n    report = Report::Base.new layout: @layout_file.path\n\n    counter = 0\n    callback = -> page {\n      assert_instance_of Report::Page, page\n      counter += 1\n    }\n\n    report.on_page_create(&callback)\n\n    2.times { report.start_new_page }\n    assert_equal counter, 2\n  end\n\n  def test_initialize_should_register_layout_as_default_when_layout_is_specified_as_the_option\n    report = Report::Base.new layout: @layout_file.path\n    assert_equal report.default_layout.filename, @layout_file.path\n  end\n\n  def test_initialize_should_initialize_new_Report_without_default_layout\n    assert_nil @report.default_layout\n  end\n\n  def test_use_layout_should_register_default_layout_when_default_property_is_omitted\n    @report.use_layout(@layout_file.path)\n\n    assert_equal @report.default_layout.filename, @layout_file.path\n  end\n\n  def test_use_layout_should_register_default_layout_when_default_property_is_true\n    @report.use_layout(@layout_file.path, default: true)\n\n    assert_equal @report.default_layout.filename, @layout_file.path\n  end\n\n  def test_start_new_page_should_properly_create_a_new_Page_and_return\n    @report.use_layout(@layout_file.path)\n\n    assert_instance_of Thinreports::BasicReport::Report::Page, @report.start_new_page\n  end\n\n  def test_start_new_page_should_raise_when_the_layout_has_not_been_registered_yet\n    assert_raises Thinreports::BasicReport::Errors::NoRegisteredLayoutFound do\n      @report.start_new_page(layout: :unknown)\n    end\n  end\n\n  def test_start_new_page_should_create_a_new_page_using_a_default_layout\n    @report.use_layout(@layout_file.path, default: true)\n\n    assert_equal @report.start_new_page.layout.filename, @layout_file.path\n  end\n\n  def test_start_new_page_should_create_a_new_page_using_a_layout_with_specified_id\n    @report.use_layout(@layout_file.path, id: :foo)\n\n    assert_equal @report.start_new_page(layout: :foo).layout.filename,\n                 @layout_file.path\n  end\n\n  def test_start_new_page_should_create_a_new_page_using_a_specified_layoutfile\n    new_page = @report.start_new_page(layout: @layout_file.path)\n    assert_equal new_page.layout.filename, @layout_file.path\n  end\n\n  def test_start_new_page_with_count_option\n    @report.use_layout @layout_file.path, default: true\n\n    new_page = @report.start_new_page count: false\n    assert_nil new_page.no\n    assert_equal @report.page_count, 0\n\n    new_page = @report.start_new_page count: true\n    assert_equal new_page.no, 1\n    assert_equal @report.page_count, 1\n\n    new_page = @report.start_new_page\n    assert_equal new_page.no, 2\n    assert_equal @report.page_count, 2\n  end\n\n  def test_add_blank_page_should_properly_create_a_new_blank_page\n    @report.use_layout(@layout_file.path)\n\n    assert_instance_of Thinreports::BasicReport::Report::BlankPage, @report.add_blank_page\n  end\n\n  def test_layout_should_return_the_default_layout_with_no_arguments\n    @report.use_layout(@layout_file.path, default: true)\n\n    assert_equal @report.layout.filename, @layout_file.path\n  end\n\n  def test_layout_should_raise_when_the_specified_layout_is_not_found\n    assert_raises Thinreports::BasicReport::Errors::UnknownLayoutId do\n      @report.layout(:unknown_layout_id)\n    end\n  end\n\n  def test_layout_should_return_the_layout_with_specified_id\n    @report.use_layout(@layout_file.path, id: :foo)\n\n    assert_equal @report.layout(:foo).filename, @layout_file.path\n  end\n\n  def test_generate\n    report = Report::Base.new(layout: @layout_file.path)\n\n    generator = mock('generator')\n    generator.expects(:generate).with('result.pdf')\n\n    Thinreports::BasicReport::Generator::PDF.expects(:new)\n      .with(report, security: { owner_password: 'pass' }, title: nil)\n      .returns(generator)\n\n    report.generate(\n      filename: 'result.pdf',\n      security: { owner_password: 'pass' }\n    )\n  end\n\n  def test_generate_when_title_argument_is_specified\n    report = Report::Base.new layout: @layout_file.path\n    pdf = report.generate(title: 'Custom title')\n\n    assert_equal 'Custom title', PDF::Reader.new(StringIO.new(pdf)).info[:Title]\n  end\n\n  def test_page_should_return_the_current_page\n    @report.use_layout(@layout_file.path)\n    @report.start_new_page\n\n    assert_instance_of Thinreports::BasicReport::Report::Page, @report.page\n  end\n\n  def test_page_count_should_return_total_page_count\n    @report.use_layout(@layout_file.path)\n    2.times { @report.start_new_page }\n\n    assert_equal @report.page_count, 2\n  end\n\n  def test_finalize_should_finalize_report\n    @report.finalize\n    assert_equal @report.finalized?, true\n  end\n\n  def test_finalized_asker_should_return_false_when_report_has_not_been_finalized_yet\n    assert_equal @report.finalized?, false\n  end\n\n  def test_finalized_asker_should_return_true_when_report_is_already_finalized\n    @report.finalize\n    assert_equal @report.finalized?, true\n  end\n\n  def test_list_should_create_new_page_when_page_is_not_created\n    @report.use_layout(@layout_file.path)\n    @report.list\n\n    refute_nil @report.page\n  end\n\n  def test_list_should_create_new_page_when_page_is_finalized\n    @report.tap do |r|\n      r.use_layout(@layout_file.path)\n      r.start_new_page\n      r.page.finalize\n    end\n    @report.list\n\n    assert_equal @report.page.finalized?, false\n  end\n\n  def test_list_should_properly_return_shape_with_the_specified_id\n    @report.use_layout(@layout_file.path)\n\n    assert_equal @report.list.id, 'default'\n  end\n\n  def test_start_page_number\n    assert_equal @report.start_page_number, 1\n    @report.start_page_number_from 10\n    assert_equal @report.start_page_number, 10\n  end\n\n  def test_Base_create_should_finalize_report\n    report = Report::Base.create do |r|\n      assert_instance_of Report::Base, r\n    end\n    assert_equal report.finalized?, true\n  end\n\n  def test_Base_create_should_raise_when_no_block_given\n    assert_raises ArgumentError do\n      Report::Base.create\n    end\n  end\n\n  def test_Base_generate_should_raise_when_no_block_given\n    assert_raises ArgumentError do\n      Report::Base.generate(:pdf)\n    end\n  end\n\n  def test_Base_generate_with_deprecated_arguments\n    Report::Base.expects(:create).with(layout: '/path/to/layout.tlf').returns(@report)\n    @report.expects(:generate).with(\n      filename: 'result.pdf',\n      security: { owner_password: 'pass' },\n      title: nil\n    )\n\n    Report::Base.generate(\n      report: { layout: '/path/to/layout.tlf' },\n      generator: {\n        filename: 'result.pdf',\n        security: { owner_password: 'pass' }\n      }\n    ) { |_| }\n  end\n\n  def test_Base_generate_argument_priority\n    Report::Base.expects(:create).with(layout: '/path/to/layout.tlf').returns(@report)\n    @report.expects(:generate).with(\n      filename: 'result.pdf',\n      security: { owner_password: 'pass' },\n      title: nil\n    )\n\n    Report::Base.generate(\n      layout: '/path/to/layout.tlf',\n      filename: 'result.pdf',\n      security: { owner_password: 'pass' },\n      report: { layout: '/path/to/deprecated.tlf' },\n      generator: {\n        filename: 'deprecated.pdf',\n        security: { owner_password: 'deprecated' }\n      }\n    ) { |_| }\n  end\n\n  def test_Base_generate_when_title_argument_is_specified\n    pdf = Report::Base.generate(layout: @layout_file.path, title: 'Custom title') { start_new_page }\n\n    assert_equal 'Custom title', PDF::Reader.new(StringIO.new(pdf)).info[:Title]\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/report/test_internal.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::Report::TestInternal < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  Report = Thinreports::BasicReport::Report\n\n  def setup\n    @layout_file = layout_file\n  end\n\n  def report\n    Report::Base.new\n  end\n\n  def test_layout_specified_in_new_method_should_be_defined_as_default_layout\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    assert_equal internal.default_layout.filename, @layout_file.path\n  end\n\n  def test_pathname_layout_specified_in_new_method_should_be_defined_as_default_layout\n    internal = Report::Internal.new(report, layout: Pathname(@layout_file.path))\n    assert_equal internal.default_layout.filename, @layout_file.path\n  end\n\n  def test_register_layout_should_be_set_as_default_layout_when_options_are_omitted\n    internal = Report::Internal.new(report, {})\n    internal.register_layout(@layout_file.path)\n\n    assert_equal internal.default_layout.filename, @layout_file.path\n  end\n\n  def test_register_layout_should_be_set_as_default_layout_when_default_option_is_true\n    internal = Report::Internal.new(report, {})\n    internal.register_layout(@layout_file.path, default: true)\n\n    assert_equal internal.default_layout.filename, @layout_file.path\n  end\n\n  def test_register_layout_should_be_able_to_change_the_default_layout\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.register_layout(@layout_file.path, default: true)\n\n    assert_equal internal.default_layout.filename, @layout_file.path\n  end\n\n  def test_register_layout_should_be_set_as_with_id_when_id_option_is_set\n    internal = Report::Internal.new(report, {})\n    internal.register_layout(@layout_file.path, id: :foo)\n\n    assert_equal internal.layout_registry[:foo].filename, @layout_file.path\n  end\n\n  def test_register_layout_should_raise_an_error_when_id_is_already_registered\n    internal = Report::Internal.new(report, {})\n    internal.register_layout(@layout_file.path, id: :foo)\n\n    assert_raises ArgumentError do\n      internal.register_layout(@layout_file.path, id: :foo)\n    end\n  end\n\n  def test_add_page_should_finalize_the_current_page\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    page = internal.add_page(Thinreports::BasicReport::Report::Page.new(report, layout))\n    internal.add_page(Thinreports::BasicReport::Report::Page.new(report, layout))\n\n    assert_equal page.finalized?, true\n  end\n\n  def test_add_page_should_return_the_current_page\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n    new_page = Thinreports::BasicReport::Report::Page.new(report, layout)\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n\n    assert_same new_page, internal.add_page(new_page)\n  end\n\n  def test_add_page_should_add_the_initialized_page\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n    new_page = Thinreports::BasicReport::Report::Page.new(report, layout)\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(new_page)\n\n    assert_same new_page, internal.pages.last\n  end\n\n  def test_add_page_should_count_up_the_total_page_count\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(Thinreports::BasicReport::Report::Page.new(report, layout))\n\n    assert_equal internal.page_count, 1\n  end\n\n  def test_add_page_should_switch_to_a_reference_to_the_current_page\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n    new_pages = (1..2).inject([]) do |pages|\n      pages << Thinreports::BasicReport::Report::Page.new(report, layout)\n    end\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(new_pages[0])\n\n    assert_same internal.page, new_pages[0]\n\n    internal.add_page(new_pages[1])\n\n    assert_same internal.page, new_pages[1]\n  end\n\n  def test_add_blank_page_should_not_count_up_the_total_page_count_when_count_is_disabled\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(Thinreports::BasicReport::Report::BlankPage.new(false))\n\n    assert_equal internal.page_count, 0\n  end\n\n  def test_add_blank_page_should_count_up_the_total_page_count_when_count_is_enabled\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(Thinreports::BasicReport::Report::BlankPage.new)\n\n    assert_equal internal.page_count, 1\n  end\n\n  def test_finalize_should_finalize_the_report\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.finalize\n\n    assert internal.finalized?\n  end\n\n  def test_finalize_should_not_work_when_report_is_already_finalized\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.finalize\n\n    # #finalize_current_page must never be called\n    internal.expects(:finalize_current_page).never\n    internal.finalize\n  end\n\n  def test_finalized_should_return_true_when_report_is_already_finalized\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.finalize\n\n    assert internal.finalized?\n  end\n\n  def test_load_layout_with_String\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n\n    assert_equal internal.load_layout(@layout_file.path).filename,\n                 @layout_file.path\n  end\n\n  def test_load_layout_with_id\n    internal = Report::Internal.new(report, {})\n    internal.register_layout(@layout_file.path, id: :sample)\n\n    assert_equal internal.load_layout(:sample).filename,\n                 @layout_file.path\n  end\n\n  def test_load_layout_with_unknown_id\n    internal = Report::Internal.new(report, {})\n    assert_nil internal.load_layout(:unknown)\n  end\n\n  def test_load_layout_should_set_default_layout_when_default_layout_is_nil\n    internal = Report::Internal.new(report, {})\n    internal.load_layout(@layout_file.path)\n\n    assert_equal internal.default_layout.filename,\n                 @layout_file.path\n  end\n\n  def test_load_layout_should_raise_error_when_invalid_value_set\n    internal = Report::Internal.new(report, {})\n\n    assert_raises Thinreports::BasicReport::Errors::LayoutFileNotFound do\n      internal.load_layout('/path/to/unkown.tlf')\n    end\n  end\n\n  def test_copy_page_should_finalize_current_page\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(page = Thinreports::BasicReport::Report::Page.new(report, layout))\n    internal.copy_page\n\n    assert page.finalized?\n  end\n\n  def test_copy_page_should_add_the_copied_page\n    layout = Thinreports::BasicReport::Layout.new(@layout_file.path)\n\n    internal = Report::Internal.new(report, layout: @layout_file.path)\n    internal.add_page(Thinreports::BasicReport::Report::Page.new(report, layout))\n    internal.copy_page\n\n    assert_equal internal.page_count, 2\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/test_layout.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestLayout < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  def test_new\n    assert_instance_of Thinreports::BasicReport::Layout::Base,\n                       Thinreports::BasicReport::Layout.new(layout_file.path)\n  end\nend\n"
  },
  {
    "path": "test/basic_report/units/test_report.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::BasicReport::TestReport < Minitest::Test\n  include Thinreports::BasicReport::TestHelper\n\n  # Alias\n  Report = Thinreports::BasicReport::Report\n\n  def test_new\n    report = Report.new(layout: layout_file.path)\n    assert_instance_of Report::Base, report\n  end\n\n  def test_create\n    report = Report.create(layout: layout_file.path, &:start_new_page)\n    assert_instance_of Report::Base, report\n  end\n\n  def test_generate\n    result = Report.generate(layout: layout_file.path, &:start_new_page)\n    assert_pdf_data result\n\n    assert_raises Thinreports::BasicReport::Errors::LayoutFileNotFound do\n      Report.generate(layout: '') { |_| }\n    end\n  end\nend\n"
  },
  {
    "path": "test/feature_test.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'pdf_matcher/testing/minitest_adapter'\n\nPdfMatcher.config.diff_pdf_opts = %w(\n  --mark-differences\n  --channel-tolerance=40\n)\n\nmodule Thinreports\n  module FeatureTest\n    def self.[](base_dir)\n      k = Class.new(Base)\n      k.class_eval %Q{\n        def dir\n          Pathname.new('#{base_dir}')\n        end\n      }\n      k\n    end\n\n    class Base < Minitest::Test\n      class << self\n        def feature(&block)\n          define_method(:test_feature, &block)\n        end\n      end\n\n      def dir\n        raise NotImplementedError\n      end\n\n      def path_of(filename)\n        dir.join(filename).to_path\n      end\n\n      def assert_pdf(actual)\n        actual_pdf.binwrite(actual)\n\n        if expect_pdf.exist?\n          assert_match_pdf expect_pdf, actual_pdf, output_diff: path_of('diff.pdf')\n        else\n          flunk 'expect.pdf does not exist.'\n        end\n      rescue PdfMatcher::DiffPdf::CommandNotAvailable\n        skip 'The feature test was skipped because the diff-pdf command is not available; please install diff-pdf (https://github.com/vslavik/diff-pdf) and try again.'\n      end\n\n      def template_path(filename = 'template.tlf')\n        dir.join(filename).to_path\n      end\n\n      private\n\n      def actual_pdf\n        dir.join('actual.pdf')\n      end\n\n      def expect_pdf\n        dir.join('expect.pdf')\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "test/main/test_config.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::TestConfig < Minitest::Test\n  def test_config_should_return_configuration_of_thinreports\n    assert_instance_of Thinreports::Configuration, Thinreports.config\n  end\n\n  def test_configure_should_exec_an_given_block_with_config_which_instance_of_Configuration\n    Thinreports.configure do |config|\n      assert_instance_of Thinreports::Configuration, config\n    end\n  end\n\n  def test_fallback_fonts\n    config = Thinreports::Configuration.new\n\n    # should be empty by default\n    assert_empty config.fallback_fonts\n\n    config.fallback_fonts = 'Helvetica'\n    assert_equal config.fallback_fonts, ['Helvetica']\n\n    config.fallback_fonts = ['/path/to/font.ttf', 'Courier New']\n    assert_equal config.fallback_fonts, ['/path/to/font.ttf', 'Courier New']\n\n    config.fallback_fonts = []\n    config.fallback_fonts << 'Helvetica'\n    config.fallback_fonts << 'IPAMincho'\n    config.fallback_fonts.unshift 'Times New Roman'\n    assert_equal config.fallback_fonts, ['Times New Roman', 'Helvetica', 'IPAMincho']\n  end\nend\n"
  },
  {
    "path": "test/main/test_helper.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'minitest/autorun'\nrequire 'minitest/spec'\nrequire 'minitest/unit'\n\nrequire 'thinreports'\n"
  },
  {
    "path": "test/section_report/features/basic/README.md",
    "content": "# Basic Usage\n\nIn the section-format, multiple sections of three types can be defined (header, footer, and repeatable section), and PDFs can be generated by combining them.\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n## Section types\n\nHeader `headers`\n\n- Multiple definitions possible\n- Draw in the order defined in the template\n- Can be hidden by a parameter\n- If \"show every page\" is enabled, it will be drawn on every page, otherwise it will be drawn on the first page of each parameter group\n\nFooter `footers`\n\n- Muliple definitions possible\n- Draw in the order defined in the template\n- Can be hidden by a parameter\n\nDetail `details`\n\n- Multiple definitions possible\n- Draw in the order added by the parameter\n- Multiple definitions can be combined and drawn\n\n## Page break\n\nSections overflowing the page are drawn on the next page.\n\n## Generating a PDF\n\nGenerate a PDF by passing the following parameters to `Thinreports.generate`.\n\n```ruby\nparams = {\n  type: :section,\n  layout_file: '/path/to/template.tlf',\n  params: {\n    groups: [\n      {\n        headers: {\n          any_header_id: {\n            items: {\n              logo_image: '/path/to/logo.jpg'\n            }\n          }\n        },\n        details: [\n          {\n            id: 'detail_id',\n            items: {\n              name_field_id: 'field value'\n            }\n          }\n        ],\n        footers: {\n          any_footer_id: {\n            display: false\n          }\n        }\n      }\n    ]\n  }\n}\n\nThinreports.generate(params, filename: '/path/to/output.pdf')\n```\n\nWhen getting PDF data, omit the `filename` argument.\n\n```ruby\nThinreports.generate(params) #=> PDF data\n```\n"
  },
  {
    "path": "test/section_report/features/basic/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"title\",\n      \"type\": \"header\",\n      \"height\": 100,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 25,\n          \"y\": 37.5,\n          \"width\": 124.2,\n          \"height\": 31.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Item List\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [\n              \"bold\"\n            ],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 30,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 33\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"header\",\n      \"height\": 50,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 29.3,\n          \"y\": 18.33,\n          \"width\": 49.84,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Name\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [\n              \"bold\"\n            ],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 373.47,\n          \"y\": 20.82,\n          \"width\": 84.84,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Unit Price\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [\n              \"bold\"\n            ],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20,\n          \"y1\": 49,\n          \"x2\": 580,\n          \"y2\": 49,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"item_detail\",\n      \"type\": \"detail\",\n      \"height\": 50,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text-block\",\n          \"id\": \"item_name\",\n          \"x\": 26.81,\n          \"y\": 15,\n          \"width\": 300,\n          \"height\": 22,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"item_unit_price\",\n          \"x\": 346.81,\n          \"y\": 15,\n          \"width\": 114.17,\n          \"height\": 22,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"item_category\",\n      \"type\": \"detail\",\n      \"height\": 50,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 20.89,\n          \"y\": 10,\n          \"width\": 551.5,\n          \"height\": 32.5,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-color\": \"\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#dddddd\",\n            \"border-width\": 0\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"category_name\",\n          \"x\": 26.81,\n          \"y\": 15,\n          \"width\": 295,\n          \"height\": 22.5,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [\n              \"bold\"\n            ],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"overall\",\n      \"type\": \"footer\",\n      \"height\": 80,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 306.81,\n          \"y\": 8.33,\n          \"width\": 124.03,\n          \"height\": 25,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Number of Items\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"number_of_items\",\n          \"x\": 442.64,\n          \"y\": 8.33,\n          \"width\": 95.83,\n          \"height\": 25,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 294.83,\n          \"y\": 41.66,\n          \"width\": 137.45,\n          \"height\": 25,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Number of Categories\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"number_of_categories\",\n          \"x\": 442.64,\n          \"y\": 43.33,\n          \"width\": 95.83,\n          \"height\": 25,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20,\n          \"y1\": 1,\n          \"x2\": 580,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/basic/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestBasicFeature < Thinreports::FeatureTest[__dir__]\n  def setup\n    initialize_data\n  end\n\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: build_details,\n            footers: {\n              overall: {\n                items: {\n                  number_of_items: @categories.sum { |category| category.items.count },\n                  number_of_categories: @categories.count\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\n\n  private\n\n  def build_details\n    @categories.each_with_object([]) do |category, details|\n      # Add category row\n      details << {\n        id: 'item_category',\n        items: {\n          category_name: category.name\n        }\n      }\n      category.items.each do |item|\n        # Add item row\n        details << {\n          id: 'item_detail',\n          items: {\n            item_name: item.name,\n            item_unit_price: item.unit_price\n          }\n        }\n      end\n    end\n  end\n\n  Category = Struct.new(:name, :items)\n  Item = Struct.new(:name, :unit_price)\n\n  def initialize_data\n    @categories = [\n      Category.new('Beauty', [\n        Item.new('Synergistic Rubber Bag', '1654.0'),\n        Item.new('Incredible Bronze Shirt', '4369.0'),\n        Item.new('Aerodynamic Wool Gloves', '9254.0'),\n        Item.new('Fantastic Iron Pants', '597.0'),\n        Item.new('Fantastic Marble Clock', '3489.0'),\n        Item.new('Mediocre Steel Watch', '5147.0'),\n        Item.new('Gorgeous Granite Plate', '792.0')\n      ]),\n      Category.new('Garden', [\n        Item.new('Intelligent Linen Coat', '8706.0'),\n        Item.new('Sleek Copper Chair', '6810.0')\n      ]),\n      Category.new('Tools & Games', [\n        Item.new('Small Granite Clock', '6731.0'),\n        Item.new('Aerodynamic Leather Bag', '6238.0'),\n        Item.new('Fantastic Rubber Hat', '6198.0'),\n        Item.new('Aerodynamic Marble Shoes', '9603.0')\n      ])\n    ]\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/item_follow_stretch/README.md",
    "content": "# Item Follow Stretch\n\n領域伸縮に追従を有効にすることで、配置された section 又は stack-view-row の伸縮に応じて、item の高さや位置を自動的に変化させることができる。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n\nそれぞれのオプションと伸縮による変化は次の通り。\n\n## 領域伸縮に追従: 高さ `follow-stretch: height`\n\n領域の伸縮によって、item の高さが伸縮する。\n\n以下の item をサポート:\n\n- text-block\n- text\n- rect\n- line\n\n## 領域伸縮に追従: 上位置 `follow-stretch: y`\n\n領域の伸縮によって、item の上位置が移動する。\n\n以下の item をサポート:\n\n- line\n\n## 領域伸縮に追従: なし (デフォルト) `follow-stretch: none`\n\n領域の伸縮の影響を受けない\n"
  },
  {
    "path": "test/section_report/features/item_follow_stretch/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      0,\n      0,\n      0,\n      0\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header1\",\n      \"type\": \"header\",\n      \"height\": 80,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_expand\",\n          \"x\": 10,\n          \"y\": 30,\n          \"width\": 50,\n          \"height\": 30,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_block\",\n          \"x\": 130,\n          \"y\": 30,\n          \"width\": 120,\n          \"height\": 30,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"center\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 270,\n          \"y\": 30,\n          \"width\": 50,\n          \"height\": 30,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"texts\": [\n            \"Text\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"center\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 340,\n          \"y\": 30,\n          \"width\": 50,\n          \"height\": 30,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 410,\n          \"y1\": 30,\n          \"x2\": 410,\n          \"y2\": 60,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 535.83,\n          \"y\": 10,\n          \"width\": 46.86,\n          \"height\": 12,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Header1\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 10,\n          \"y\": 10,\n          \"width\": 111,\n          \"height\": 12,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"follow stretch: height\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"header2\",\n      \"type\": \"header\",\n      \"height\": 80,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_expand\",\n          \"x\": 10,\n          \"y\": 30,\n          \"width\": 50,\n          \"height\": 30,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 130,\n          \"y1\": 70,\n          \"x2\": 410,\n          \"y2\": 70,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"y\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 10,\n          \"y1\": 1,\n          \"x2\": 584.17,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"dashed\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 535.83,\n          \"y\": 10,\n          \"width\": 46.86,\n          \"height\": 12,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Header2\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 10,\n          \"y\": 10,\n          \"width\": 111,\n          \"height\": 12,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"follow stretch: y\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"header3\",\n      \"type\": \"header\",\n      \"height\": 180,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 10,\n          \"y\": 30,\n          \"width\": 575.28,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 70,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_expand\",\n                  \"x\": 10,\n                  \"y\": 30,\n                  \"width\": 50,\n                  \"height\": 30,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_block\",\n                  \"x\": 130,\n                  \"y\": 30,\n                  \"width\": 120,\n                  \"height\": 30,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"height\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"center\",\n                    \"vertical-align\": \"middle\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"truncate\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 270,\n                  \"y\": 30,\n                  \"width\": 50,\n                  \"height\": 30,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"height\",\n                  \"texts\": [\n                    \"Text\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"center\",\n                    \"vertical-align\": \"middle\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 340,\n                  \"y\": 30,\n                  \"width\": 50,\n                  \"height\": 30,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"height\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 410,\n                  \"y1\": 30,\n                  \"x2\": 410,\n                  \"y2\": 60,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"height\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 405,\n                  \"y\": 10,\n                  \"width\": 163.5,\n                  \"height\": 12,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1 (stack-view)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 10,\n                  \"y\": 10,\n                  \"width\": 111,\n                  \"height\": 12,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"follow stretch: height\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 70,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_expand\",\n                  \"x\": 10,\n                  \"y\": 30,\n                  \"width\": 50,\n                  \"height\": 30,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 130,\n                  \"y1\": 60,\n                  \"x2\": 410,\n                  \"y2\": 60,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"y\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 405,\n                  \"y\": 10,\n                  \"width\": 163.5,\n                  \"height\": 12,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2 (stack-view)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 10,\n                  \"y\": 10,\n                  \"width\": 111,\n                  \"height\": 12,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"follow stretch: y\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 10,\n                  \"y1\": 1,\n                  \"x2\": 570,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#aaaaaa\",\n                    \"border-style\": \"dashed\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 10,\n          \"y1\": 1,\n          \"x2\": 584.17,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"dashed\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 483.33,\n          \"y\": 10,\n          \"width\": 100,\n          \"height\": 12,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Header3\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"header4\",\n      \"type\": \"header\",\n      \"height\": 30,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"header4\",\n          \"x\": 489.16,\n          \"y\": 10,\n          \"width\": 96.83,\n          \"height\": 12,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Header4 (dummy)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 10,\n          \"y1\": 1,\n          \"x2\": 584.17,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"dashed\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/item_follow_stretch/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestItemFollowStretchFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header1: {\n                items: {\n                  text_expand: \"Expand\" * 10,\n                  text_block: 'Text Block'\n                }\n              },\n              header2: {\n                items: {\n                  text_expand: \"Expand\" * 10,\n                }\n              },\n              header3: {\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          text_expand: \"Expand\" * 10,\n                          text_block: 'Text Block'\n                        }\n                      },\n                      row2: {\n                        items: {\n                          text_expand: \"Expand\" * 10,\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/item_parameters/README.md",
    "content": "# Item Paramater\n\n各item の定義時のスタイルやプロパティはパラメータで変更することができる。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n変更できるスタイルやプロパティは item の種類によって異なる。\n\n## 共通\n\n```\nall_item: {\n  display: Boolean, # 表示状態を変更する\n}\n```\n\n## テキストスタイル\n\n```\ntext_block_and_text_item: {\n  styles: {\n    font_size: Number, # フォントサイズを変更する\n    align: :left | :center | :right, # 水平方向の位置揃えを変更する\n    valign: :top | :middle | :bottom, # 垂直方向の位置揃えを変更する\n    color: String, # テキストカラーを変更する\n    bold: Boolean, # 太字スタイルを変更する\n    italic: Boolean, # 斜体スタイルを変更する\n    linethrough: Boolean # 取消線スタイルを変更する\n  }\n}\n```\n\n## 位置の移動\n\n```\nimage_block_item: {\n  styles: {\n    offset_x: Number, # 水平方向に移動する\n    offset_y: Number # 垂直方向に移動する\n  }\n}\n```\n\n## 値をセットする\n\n```\ntext_block_item: {\n  value: 'text value'\n},\ntext_block_item: 'text value'\n```\n\n```\nimage_block_item: {\n  value: '/path/to/image.jpg'\n},\nimage_block_item: {\n  value: StringIO.new(File.binread('/path/to/image.jpg'))\n},\nimage_block_item: '/path/to/image.png',\nimage_block_item: StringIO.new(File.binread('/path/to/image.png'))\n```\n"
  },
  {
    "path": "test/section_report/features/item_parameters/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"detail1\",\n      \"type\": \"detail\",\n      \"height\": 160,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 285,\n          \"y\": 15,\n          \"width\": 140,\n          \"height\": 50,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"dashed\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          }\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"rect\",\n          \"x\": 33.5,\n          \"y\": 15,\n          \"width\": 80.04,\n          \"height\": 46.36,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          }\n        },\n        {\n          \"type\": \"ellipse\",\n          \"id\": \"ellipse\",\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\"\n          },\n          \"cx\": 190.635,\n          \"cy\": 46.99,\n          \"rx\": 40.285,\n          \"ry\": 31.99\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"text\",\n          \"x\": 285,\n          \"y\": 15,\n          \"width\": 140,\n          \"height\": 50,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"static text\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"line\",\n          \"x1\": 469.25,\n          \"y1\": 15,\n          \"x2\": 550.16,\n          \"y2\": 83.72,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_block\",\n          \"x\": 285,\n          \"y\": 90,\n          \"width\": 140,\n          \"height\": 50,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"text block\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#ff0000\",\n            \"font-style\": [\n              \"bold\",\n              \"italic\",\n              \"underline\",\n              \"linethrough\"\n            ],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image_block\",\n          \"x\": 146.59,\n          \"y\": 90,\n          \"width\": 112.62,\n          \"height\": 63.07,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          }\n        },\n        {\n          \"type\": \"image\",\n          \"id\": \"image\",\n          \"x\": 26.21,\n          \"y\": 90,\n          \"width\": 100,\n          \"height\": 50,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"data\": {\n            \"mime-type\": \"image/jpeg\",\n            \"base64\": \"/9j/4AAQSkZJRgABAQAASABIAAD/4QDIRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAPAAAAcgEyAAIAAAAUAAAAgodpAAQAAAABAAAAlgAAAAAAAABIAAAAAQAAAEgAAAABUGl4ZWxtYXRvciAzLjkAADIwMjA6MDY6MDggMTY6MDY6NzYAAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAGSgAwAEAAAAAQAAADIAAAAA/+EJkGh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iUGl4ZWxtYXRvciAzLjkiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTA2LTA4VDE2OjA2Ojc2Ii8+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPD94cGFja2V0IGVuZD0idyI/PgD/wAARCAAyAGQDAREAAhEBAxEB/8QAHwAAAQUB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\"\n          }\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 449.23,\n          \"y\": 90,\n          \"width\": 135.19,\n          \"description\": \"\",\n          \"display\": true,\n          \"affect-bottom-margin\": true,\n          \"follow-stretch\": \"none\",\n          \"rows\": [\n            {\n              \"id\": \"\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 25.33,\n                  \"y\": 6,\n                  \"width\": 86.5,\n                  \"height\": 18.96,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"StackViewRow1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 25.98,\n                  \"y\": 6,\n                  \"width\": 86.5,\n                  \"height\": 18.96,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"StackViewRow2\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  }\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 10,\n          \"y1\": 1,\n          \"x2\": 584.59,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 285,\n          \"y\": 90,\n          \"width\": 140,\n          \"height\": 50,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"dashed\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"detail2\",\n      \"type\": \"detail\",\n      \"height\": 120,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_block1\",\n          \"x\": 26,\n          \"y\": 14.34,\n          \"width\": 116.46,\n          \"height\": 44.32,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_block2\",\n          \"x\": 26,\n          \"y\": 65.13,\n          \"width\": 116.46,\n          \"height\": 44.32,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image_block1\",\n          \"x\": 152,\n          \"y\": 14.97,\n          \"width\": 100,\n          \"height\": 75,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          }\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image_block2\",\n          \"x\": 259.95,\n          \"y\": 15,\n          \"width\": 100,\n          \"height\": 75,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 10,\n          \"y1\": 1,\n          \"x2\": 584.59,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image_block3\",\n          \"x\": 366.37,\n          \"y\": 14.27,\n          \"width\": 100,\n          \"height\": 75,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          }\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image_block4\",\n          \"x\": 473.53,\n          \"y\": 14.64,\n          \"width\": 100,\n          \"height\": 75,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          }\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/item_parameters/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestItemParametersFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: [\n              {\n                id: :detail1,\n                items: {\n                  image_block: image_block_jpg.to_path\n                }\n              },\n              {\n                id: :detail1,\n                items: {\n                  text: {\n                    styles: {\n                      font_size: 24,\n                      align: :center,\n                      valign: :middle,\n                      color: '#ff0000',\n                      bold: true,\n                      italic: true,\n                      underline: true,\n                      linethrough: true\n                    }\n                  },\n                  text_block: {\n                    styles: {\n                      font_size: 24,\n                      align: :right,\n                      valign: :bottom,\n                      color: 'black',\n                      bold: false,\n                      italic: false,\n                      underline: false,\n                      linethrough: false\n                    }\n                  },\n                  image_block: image_block_jpg.to_path\n                }\n              },\n              {\n                id: :detail1,\n                items: {\n                  image_block: {\n                    value: image_block_jpg.to_path,\n                    styles: {\n                      offset_x: 20,\n                      offset_y: -20\n                    }\n                  }\n                }\n              },\n              {\n                id: :detail1,\n                items: {\n                  rect: {\n                    display: false\n                  },\n                  ellipse: {\n                    display: false\n                  },\n                  text: {\n                    display: false\n                  },\n                  line: {\n                    display: false\n                  },\n                  image: {\n                    display: false\n                  },\n                  text_block: {\n                    display: false\n                  },\n                  image_block: {\n                    display: false\n                  },\n                  stackview: {\n                    display: false\n                  }\n                }\n              },\n              {\n                id: :detail2,\n                items: {\n                  text_block1: 'text-block1',\n                  text_block2: {\n                    value: 'text-block2'\n                  },\n                  image_block1: image_block_jpg.to_path,\n                  image_block2: StringIO.new(image_block_jpg.binread),\n                  image_block3: {\n                    value: image_block_jpg.to_path,\n                  },\n                  image_block4: {\n                    value: StringIO.new(image_block_jpg.binread)\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\n\n  private\n\n  def image_block_jpg\n    dir.join('image-block.jpg')\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/multiple_groups/README.md",
    "content": "# Multiple Groups\n\nMultiple parameter sets can be passed as a group and drawn into a single PDF.\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\nThe main functions of groups are as follows:\n\n- Page break for each group\n- Headers and footers for which the \"show every page\" is disabled will be drawn only once per group\n"
  },
  {
    "path": "test/section_report/features/multiple_groups/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header\",\n      \"type\": \"header\",\n      \"height\": 60,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 20,\n          \"y\": 20,\n          \"width\": 550,\n          \"height\": 20,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"detail\",\n      \"type\": \"detail\",\n      \"height\": 60,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 20,\n          \"y\": 20,\n          \"width\": 550,\n          \"height\": 20,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"footer\",\n      \"type\": \"footer\",\n      \"height\": 60,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 20,\n          \"y\": 20,\n          \"width\": 200,\n          \"height\": 20,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Footer\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/multiple_groups/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestMultipleGroupsFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header: {\n                items: {\n                  text: 'Header of Group 1'\n                }\n              }\n            },\n            details: 20.times.map {\n              {\n                id: :detail,\n                items: {\n                  text: 'Detail of Group 1'\n                }\n              }\n            },\n            footers: {\n              footer: {\n                display: false\n              }\n            }\n          },\n          {\n            headers: {\n              header: {\n                items: {\n                  text: 'Header of Group 2'\n                }\n              }\n            },\n            details: 10.times.map {\n              {\n                id: :detail,\n                items: {\n                  text: 'Detail of Group 2'\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/nonexistent_id/README.md",
    "content": "# Nonexistent Id\n\n存在しない section や item、stack-view-row の id がパラメータに含まれる場合、それらは無視される。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\ntemplate に存在しない section や item、stack-view-row は描画されず、エラーも発生しない。\n"
  },
  {
    "path": "test/section_report/features/nonexistent_id/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header\",\n      \"type\": \"header\",\n      \"height\": 100,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 30,\n          \"width\": 87.31,\n          \"height\": 51.18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"header\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 136.53,\n          \"y\": 30,\n          \"width\": 86.81,\n          \"height\": 34.69,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20,\n          \"y1\": 1,\n          \"x2\": 570,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"detail\",\n      \"type\": \"detail\",\n      \"height\": 100,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 30,\n          \"width\": 87.31,\n          \"height\": 51.18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"detail\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 136.53,\n          \"y\": 30,\n          \"width\": 86.81,\n          \"height\": 34.69,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 284.82,\n          \"y\": 17.66,\n          \"width\": 224.05,\n          \"description\": \"\",\n          \"display\": true,\n          \"affect-bottom-margin\": true,\n          \"follow-stretch\": \"none\",\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 46.77,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"row1\",\n                  \"x\": 13.66,\n                  \"y\": 12.27,\n                  \"width\": 47.73,\n                  \"height\": 21.65,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"row1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text\",\n                  \"x\": 77.42,\n                  \"y\": 12.27,\n                  \"width\": 75.15,\n                  \"height\": 22.63,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"truncate\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20,\n          \"y1\": 1,\n          \"x2\": 570,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"footer\",\n      \"type\": \"footer\",\n      \"height\": 100,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 30,\n          \"width\": 87.31,\n          \"height\": 51.18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"footer\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 136.53,\n          \"y\": 30,\n          \"width\": 86.81,\n          \"height\": 34.69,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"truncate\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20,\n          \"y1\": 1,\n          \"x2\": 570,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/nonexistent_id/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestNonExistentIdFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header: {\n                items: {\n                  text: 'text',\n                  nonexistent_item: 'nonexistent items are ignored'\n                }\n              },\n              nonexistent_header: {\n                items: {\n                  any_item: 'nonexistent sections and items within them are ignored'\n                }\n              }\n            },\n            details: [\n              {\n                id: 'detail',\n                items: {\n                  text: 'text',\n                  nonexistent_item: 'nonexistent items are ignored',\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          text: 'text',\n                          nonexistent_item: 'nonexistent items are ignored',\n                        }\n                      },\n                      nonexistent_row: {\n                        items: {\n                          any_item: 'nonexistent rows and items within them are ignored'\n                        }\n                      }\n                    }\n                  }\n                }\n              },\n              {\n                id: 'nonexistent_detail',\n                items: {\n                  any_item: 'nonexistent sections and items within them are ignored'\n                }\n              }\n            ],\n            footers: {\n              footer: {\n                items: {\n                  text: 'text',\n                  nonexistent_item: 'nonexistent items are ignored'\n                }\n              },\n              nonexistent_footer: {\n                items: {\n                  any_item: 'nonexistent sections and items within them are ignored'\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/section_auto_stretch/README.md",
    "content": "# Section Auto Stretch\n\nBy enabling auto-stretch, the height of the section can be automatically stretched according to the content after drawing.\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n## Calculating the height when stretching\n\n### Bottom margin and bottom position of content\n\nThe height of the section after it is stretched is determined by the bottom margin and the bottom position of the content.\n\nBottom Position of Content\n\n- The bottom position of the item in the section (except for items for which \"Affect bottom margin\" is disabled)\n- Varies depending on the drawing result\n\nBottom Margin\n\n- The height or area between the bottom position of the content and the bottom position of the section\n- Determined and fixed by the content of the template definition\n\nSee [Section Bottom Margin](../section_report_section_bottom_margin/README.md) for details.\n\n### Calculating the height\n\nThe height of the section is defined as follows:\n\n```\nheight of section = bottom of content + height of bottom margin\n```\n\nWhen an item such as text-block or stack-view is stretched, the bottom position of the content may change, and if auto-stretch of the section is enabled, the height of the section will be changed based on the changed bottom position of the content.\n\n## Expanding the height\n\nExpanding the height occurs in the following cases:\n\n- When the height of the text-block after drawing becomes higher than the defined height, and as a result, the bottom position of the section content becomes larger\n- When the height of stack-view becomes higher than the defined height, and as a result, the bottom position of the section content becomes larger\n\nIn these cases, the height of the section is expanded as follows:\n\n![](images/auto-stretch-expand.png)\n\n## Shrinking the height\n\nShrinking the height occurs in the following cases:\n\n- When the height of the stack-view becomes smaller than the defined height, and as a result, the bottom position of the section content becomes smaller\n- When the image of an image-block whose vertical position is top becomes smaller than the height of the defined area, and as a result, the bottom position of the section content becomes smaller\n\nIn these cases, the height of the section is shrinked as follows:\n\n![](images/auto-stretch-shrink.png)\n"
  },
  {
    "path": "test/section_report/features/section_auto_stretch/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header1\",\n      \"type\": \"header\",\n      \"height\": 70,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 10,\n          \"width\": 336.69,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Expand height by text-block whose overflow is expand\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_overflow_expand\",\n          \"x\": 45.97,\n          \"y\": 35,\n          \"width\": 330,\n          \"height\": 24.17,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 15,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 16.5\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 434.32,\n          \"y\": 10,\n          \"width\": 140.83,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Header1 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"header2\",\n      \"type\": \"header\",\n      \"height\": 70,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 10,\n          \"width\": 353.03,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Does not expand by text-block whose overflow is expand\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 440.15,\n          \"y\": 10,\n          \"width\": 140.83,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Header2 (auto-stretch: off)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_overflow_expand\",\n          \"x\": 45.97,\n          \"y\": 35,\n          \"width\": 330,\n          \"height\": 24.17,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 15,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 16.5\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"detail1\",\n      \"type\": \"detail\",\n      \"height\": 110,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 15,\n          \"width\": 178.97,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Expand height by stack-view\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 33.47,\n          \"y\": 40,\n          \"width\": 400,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.01,\n                  \"y\": 5,\n                  \"width\": 71.67,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 30,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_overflow_expand\",\n                  \"x\": 240,\n                  \"y\": 5,\n                  \"width\": 140,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 16,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 17.6\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.84,\n                  \"y\": 5,\n                  \"width\": 188.05,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2 (auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 449.31,\n          \"y\": 10,\n          \"width\": 132.17,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Detail1 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"detail2\",\n      \"type\": \"detail\",\n      \"height\": 90,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 449.31,\n          \"y\": 13.33,\n          \"width\": 132.17,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Detail2 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_overflow_expand\",\n          \"x\": 45.97,\n          \"y\": 35,\n          \"width\": 200,\n          \"height\": 24.17,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 15,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 16.5\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 15,\n          \"width\": 208.25,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Expand height with multiple items\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 296.81,\n          \"y\": 35.84,\n          \"width\": 105.83,\n          \"height\": 45,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"detail3\",\n      \"type\": \"detail\",\n      \"height\": 150,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 13.33,\n          \"width\": 179.73,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Reduce height by stack-view\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 33.47,\n          \"y\": 40,\n          \"width\": 280,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 70,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.01,\n                  \"y\": 5,\n                  \"width\": 213.06,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1 (hide when drawing)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.84,\n                  \"y\": 5,\n                  \"width\": 71.67,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 449.31,\n          \"y\": 13.33,\n          \"width\": 132.17,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Detail3 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"footer1\",\n      \"type\": \"footer\",\n      \"height\": 140,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 10,\n          \"width\": 334.34,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Reduce height by image-block whose position-y is top\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 445.15,\n          \"y\": 14.16,\n          \"width\": 136.17,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Footer1 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image200x100\",\n          \"x\": 50.98,\n          \"y\": 35,\n          \"width\": 200,\n          \"height\": 100,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"footer2\",\n      \"type\": \"footer\",\n      \"height\": 140,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 10,\n          \"width\": 356.45,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Does not reduce by image-block whose position-y is top\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 386.81,\n          \"y\": 13.33,\n          \"width\": 193.7,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Footer2 (auto-stretch: off)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image200x100\",\n          \"x\": 50.98,\n          \"y\": 35,\n          \"width\": 200,\n          \"height\": 100,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"footer3\",\n      \"type\": \"footer\",\n      \"height\": 140,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 10,\n          \"width\": 370.13,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Does not reduce by image-block whose position-y is not top\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 386.81,\n          \"y\": 13.33,\n          \"width\": 193.7,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Footer3 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image200x100\",\n          \"x\": 50.98,\n          \"y\": 35,\n          \"width\": 200,\n          \"height\": 100,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"middle\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"footer4\",\n      \"type\": \"footer\",\n      \"height\": 150,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 31.8,\n          \"y\": 13.33,\n          \"width\": 209.02,\n          \"height\": 14,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Reduce height with multiple items\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 14,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 15.4\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 386.81,\n          \"y\": 13.33,\n          \"width\": 193.7,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Footer4 (auto-stretch: on)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 33.47,\n          \"y\": 40,\n          \"width\": 150,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.01,\n                  \"y\": 5,\n                  \"width\": 71.67,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.84,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 245.97,\n          \"y\": 41.67,\n          \"width\": 114.17,\n          \"height\": 80,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"footer5\",\n      \"type\": \"footer\",\n      \"height\": 30,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 386.81,\n          \"y\": 5,\n          \"width\": 193.7,\n          \"height\": 21.67,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"dummy\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 17.64,\n          \"y1\": 1,\n          \"x2\": 581.81,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/section_auto_stretch/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestSectionAutoStretchFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header1: {\n                items: {\n                  text_overflow_expand: 'Extended text box height with long text. ' * 3\n                }\n              },\n              header2: {\n                items: {\n                  text_overflow_expand: 'Extended text box height with long text. ' * 3\n                }\n              }\n            },\n            details: [\n              {\n                id: 'detail1',\n                items: {\n                  stackview: {\n                    rows: {\n                      row2: {\n                        items: {\n                          text_overflow_expand: 'Extended text box height with long text. '\n                        }\n                      }\n                    }\n                  }\n                }\n              },\n              {\n                id: 'detail2',\n                items: {\n                  text_overflow_expand: 'Extended text box height with long text. ' * 3\n                }\n              },\n              {\n                id: 'detail3',\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        display: false\n                      }\n                    }\n                  }\n                }\n              }\n            ],\n            footers: {\n              footer1: {\n                items: {\n                  image200x100: image50x50\n                }\n              },\n              footer2: {\n                items: {\n                  image200x100: image50x50\n                }\n              },\n              footer3: {\n                items: {\n                  image200x100: image50x50\n                }\n              },\n              footer4: {\n                items: {\n                  stackview: {\n                    rows: {\n                      row2: {\n                        display: false\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\n\n  def image50x50\n    StringIO.new(dir.join('50x50.jpg').binread)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/section_bottom_margin/README.md",
    "content": "# Section Bottom Margin\n\nThe bottom margin of a section is the distance between the bottom position of the section content and the bottom position of the section.\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\nAn item whose affect-bottom-margin is disabled does not affect the calculation of the bottom margin.\n\n![](images/bottom-margin-diagram-1.png)\n\nIn the example above, item3 does not affect the bottom margin because affect-bottom-margin is disabled.\n\nSince the bottom position of item2 is the bottom position of the section content, the space between the bottoom position of item2 and the bottom position of the section (the gray shaded area) is the bottom margin of this section.\n\nWhen auto-stretch is enabled, the section will be automatically stretched while keepking the bottom margin of the section. See [Section Auto Stretch](../section_report_section_auto_stretch/README.md) for details.\n"
  },
  {
    "path": "test/section_report/features/section_bottom_margin/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"detail\",\n      \"type\": \"detail\",\n      \"height\": 200,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 0,\n          \"y1\": 0,\n          \"x2\": 595.28,\n          \"y2\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"textblock\",\n          \"x\": 40,\n          \"y\": 40,\n          \"width\": 100,\n          \"height\": 20,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 200,\n          \"y\": 20,\n          \"width\": 100,\n          \"height\": 120,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 360,\n          \"y\": 40,\n          \"width\": 160,\n          \"height\": 150,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"dashed\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 370,\n          \"y\": 50,\n          \"width\": 112.2,\n          \"height\": 37.8,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"affect-bottom-\",\n            \"margin: false\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"\",\n      \"type\": \"footer\",\n      \"height\": 50,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 0,\n          \"y1\": 0,\n          \"x2\": 595.28,\n          \"y2\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/section_bottom_margin/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestSectionBottomMarginFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: [\n              {\n                id: :detail,\n                items: {\n                  textblock: 'short text'\n                }\n              },\n              {\n                id: :detail,\n                items: {\n                  textblock: 'long ' * 19 + 'text'\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/section_parameters/README.md",
    "content": "# Section Parameter\n\nSome properties in the definition of each section can be changed by parameters.\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n## Display\n\nHeaders and footers can be shown or hidden with the display property.\n\n```\nheader_and_footer: {\n  display: Boolean\n}\n```\n\n## Minimum height\n\nThe min_height property can be used to set the minimum height of a section.\n\n```\nheader_and_footer: {\n  min_height: Number\n}\n```\n\n```\n{\n  id: :detail,\n  min_height: Number\n}\n```\n"
  },
  {
    "path": "test/section_report/features/section_parameters/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header1\",\n      \"type\": \"header\",\n      \"height\": 50,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 23.13,\n          \"y\": 15,\n          \"width\": 303.92,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(header1) display: true in the template\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"header2\",\n      \"type\": \"header\",\n      \"height\": 50,\n      \"display\": false,\n      \"auto-stretch\": false,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 23.13,\n          \"y\": 15,\n          \"width\": 310.92,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(header2) display: false in the template\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"detail1_height80\",\n      \"type\": \"detail\",\n      \"height\": 80,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 23.81,\n          \"y\": 15,\n          \"width\": 266.16,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(detail1) auto-stretch: off\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 26.39,\n          \"y\": 45,\n          \"width\": 48.07,\n          \"height\": 35,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"detail2_height100\",\n      \"type\": \"detail\",\n      \"height\": 100,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"detail3\",\n          \"x\": 23.81,\n          \"y\": 15,\n          \"width\": 195.13,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(detail2) auto-stretch: on\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"image-block\",\n          \"id\": \"image_block\",\n          \"x\": 26.19,\n          \"y\": 40.25,\n          \"width\": 100,\n          \"height\": 60,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"position-x\": \"left\",\n            \"position-y\": \"top\"\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"detail3_height70\",\n      \"type\": \"detail\",\n      \"height\": 70,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"detail3\",\n          \"x\": 23.81,\n          \"y\": 15,\n          \"width\": 195.13,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(detail3) auto-stretch: on\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text_block\",\n          \"x\": 26.19,\n          \"y\": 42,\n          \"width\": 100,\n          \"height\": 22,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 16,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 17.6\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 137.84,\n          \"y\": 42,\n          \"width\": 44.69,\n          \"height\": 28,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"#ffffff\",\n            \"border-width\": 1\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"footer1\",\n      \"type\": \"footer\",\n      \"height\": 50,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"footer1\",\n          \"x\": 23.13,\n          \"y\": 15,\n          \"width\": 293.91,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(footer1) display: true in the template\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    },\n    {\n      \"id\": \"footer2\",\n      \"type\": \"footer\",\n      \"height\": 50,\n      \"display\": false,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"text\",\n          \"id\": \"footer2\",\n          \"x\": 23.13,\n          \"y\": 15,\n          \"width\": 300.91,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"texts\": [\n            \"(footer2) display: false in the template\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          }\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 20.31,\n          \"y1\": 1,\n          \"x2\": 573.04,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/section_parameters/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestSectionParametersFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header1: {\n                display: false\n              },\n              header2: {\n                display: true\n              }\n            },\n            details: [\n              {\n                id: :detail1_height80,\n                min_height: 40\n              },\n              {\n                id: :detail1_height80,\n                min_height: 160\n              },\n              {\n                id: :detail2_height100,\n                min_height: 100,\n                items: {\n                  image_block: dir.join('20x20.jpg').to_path\n                }\n              },\n              {\n                id: :detail2_height100,\n                min_height: 20,\n                items: {\n                  image_block: dir.join('20x20.jpg').to_path\n                }\n              },\n              {\n                id: :detail3_height70,\n                min_height: 140,\n                items: {\n                  text_block: 'text ' * 9\n                }\n              },\n              {\n                id: :detail3_height70,\n                min_height: 70,\n                items: {\n                  text_block: 'text ' * 12\n                }\n              }\n            ],\n            footers: {\n              footer1: {\n                display: false\n              },\n              footer2: {\n                display: true\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/stack_view/README.md",
    "content": "# StackView\n\nstack-view によって複数の row を縦に積み重ねたレイアウトを作ることができる。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\nstack-view の主な機能は以下の通り。\n\n- row は、section 同様、四角形やテキストなどの item をその中にを配置できる\n- row はパラメータで動的に非表示にすることも可能。非表示にした row に続く row は、上にスライドして表示される\n- stack-view の row の中に、さらに入れ子の stack-view を配置することはできない\n"
  },
  {
    "path": "test/section_report/features/stack_view/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"detail\",\n      \"type\": \"detail\",\n      \"height\": 250,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 0.5,\n          \"width\": 540,\n          \"height\": 250,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-color\": \"#aaaaaa\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview1\",\n          \"x\": 104.67,\n          \"y\": 47.17,\n          \"width\": 210,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 0,\n                  \"y\": 0,\n                  \"width\": 210,\n                  \"height\": 50,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"none\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 109.33,\n                  \"y\": 5.33,\n                  \"width\": 93.69,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"StackView1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [\n                      \"underline\"\n                    ],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 0,\n                  \"y\": 0,\n                  \"width\": 210,\n                  \"height\": 50,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"none\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text\",\n                  \"x\": 58.5,\n                  \"y\": 18,\n                  \"width\": 140,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#ff0000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"truncate\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row3\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 0,\n                  \"y\": 0,\n                  \"width\": 210,\n                  \"height\": 50,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"none\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row3\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 74.72,\n                  \"y\": 13.33,\n                  \"width\": 57,\n                  \"height\": 30,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"ellipse\",\n                  \"id\": \"\",\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"#ffffff\"\n                  },\n                  \"cx\": 140.97,\n                  \"cy\": 20.33,\n                  \"rx\": 17.25,\n                  \"ry\": 15.5,\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview2\",\n          \"x\": 362.67,\n          \"y\": 104,\n          \"width\": 150,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 51.33,\n                  \"y\": 4.33,\n                  \"width\": 93.69,\n                  \"height\": 18,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"StackView2\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [\n                      \"underline\"\n                    ],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row3\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row3\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row4\",\n              \"height\": 30,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 5,\n                  \"y\": 5,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row4\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 44.89,\n          \"y\": 9,\n          \"width\": 60.06,\n          \"height\": 18,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"Section\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/stack_view/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestStackViewFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: [\n              {\n                id: :detail,\n                items: {\n                  stackview1: {\n                    rows: {\n                      row2: {\n                        items: {\n                          text: 'text block'\n                        }\n                      }\n                    }\n                  },\n                  stackview2: {\n                    rows: {\n                      row2: {\n                        display: false\n                      },\n                      row3: {\n                        display: false\n                      }\n                    }\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/stack_view_row_auto_stretch/README.md",
    "content": "# StackViewRow Auto Stretch\n\n自動伸縮を有効にすることで、描画後の内容に応じて row の高さを自動的に伸縮させることができる。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\nrow の伸縮によって stack-view 自体の高さも伸縮する。\nrow の伸縮の仕様は section と同様である。詳細は [Section Auto Stretch](../section_report_section_auto_stretch/README.md) を参照。\nただし、stack-view は入れ子にすることはできないため、stack-view によるrowの伸縮は起こらない。\n"
  },
  {
    "path": "test/section_report/features/stack_view_row_auto_stretch/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"detail1\",\n      \"type\": \"detail\",\n      \"height\": 250,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 49.31,\n          \"y\": 10,\n          \"width\": 500,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 60,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 336.69,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Expand height by text-block whose overflow is expand\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.16,\n                  \"y\": 4.99,\n                  \"width\": 122.16,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1(auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_overflow_expand\",\n                  \"x\": 16.66,\n                  \"y\": 24.99,\n                  \"width\": 290,\n                  \"height\": 30,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 80,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 208.23,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Expand height with multiple items\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.16,\n                  \"y\": 5.83,\n                  \"width\": 121.94,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2(auto-stretch: off)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_overflow_expand\",\n                  \"x\": 16.66,\n                  \"y\": 24.99,\n                  \"width\": 200,\n                  \"height\": 24,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 255.83,\n                  \"y\": 32.5,\n                  \"width\": 102.5,\n                  \"height\": 43.33,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row3\",\n              \"height\": 60,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 353.02,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Does not expand by text-block whose overflow is expand\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.16,\n                  \"y\": 5.83,\n                  \"width\": 121.94,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row3(auto-stretch: off)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_overflow_expand\",\n                  \"x\": 16.66,\n                  \"y\": 24.99,\n                  \"width\": 290,\n                  \"height\": 30,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row4\",\n              \"height\": 20,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 396.66,\n                  \"y\": 4.16,\n                  \"width\": 98.97,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"dummy\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"detail2\",\n      \"type\": \"detail\",\n      \"height\": 550,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 49.31,\n          \"y\": 10,\n          \"width\": 500,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 130,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 334.34,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Reduce height by image-block whose position-y is top\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.99,\n                  \"y\": 5.83,\n                  \"width\": 122.16,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row1(auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"image-block\",\n                  \"id\": \"image200x100\",\n                  \"x\": 16.66,\n                  \"y\": 25,\n                  \"width\": 290,\n                  \"height\": 100,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"position-x\": \"left\",\n                    \"position-y\": \"top\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 130,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 346.78,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Does not reduce by image-block whose position-y is top\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.99,\n                  \"y\": 4.99,\n                  \"width\": 121.94,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row2(auto-stretch: off)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"image-block\",\n                  \"id\": \"image200x100\",\n                  \"x\": 16.66,\n                  \"y\": 25,\n                  \"width\": 290,\n                  \"height\": 100,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"position-x\": \"left\",\n                    \"position-y\": \"top\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row3\",\n              \"height\": 130,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 361.13,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Does not reduce by image-block whose position-y isn't top\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.16,\n                  \"y\": 4.99,\n                  \"width\": 122.16,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row3(auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"image-block\",\n                  \"id\": \"image200x100\",\n                  \"x\": 16.66,\n                  \"y\": 25,\n                  \"width\": 290,\n                  \"height\": 100,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"position-x\": \"left\",\n                    \"position-y\": \"middle\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row4\",\n              \"height\": 130,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 209.02,\n                  \"height\": 14,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Reduce height with multiple items\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 374.16,\n                  \"y\": 4.99,\n                  \"width\": 122.16,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"Row4(auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"image-block\",\n                  \"id\": \"image200x100\",\n                  \"x\": 16.66,\n                  \"y\": 25,\n                  \"width\": 200,\n                  \"height\": 100,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"position-x\": \"left\",\n                    \"position-y\": \"top\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 260,\n                  \"y\": 25.83,\n                  \"width\": 118.33,\n                  \"height\": 80,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row5\",\n              \"height\": 20,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"row4\",\n                  \"x\": 396.66,\n                  \"y\": 4.16,\n                  \"width\": 98.97,\n                  \"height\": 15.83,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"dummy\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 1.84,\n                  \"x2\": 500,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/stack_view_row_auto_stretch/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestStackViewRowAutoStretchFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: [\n              {\n                id: 'detail1',\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          text_overflow_expand: 'Extended text box height with long text. ' * 4\n                        }\n                      },\n                      row2: {\n                        items: {\n                          text_overflow_expand: 'Extended text box height with long text. ' * 4\n                        }\n                      },\n                      row3: {\n                        items: {\n                          text_overflow_expand: 'Extended text box height with long text. ' * 4\n                        }\n                      }\n                    }\n                  }\n                }\n              },\n              {\n                id: 'detail2',\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          image200x100: image50x50\n                        }\n                      },\n                      row2: {\n                        items: {\n                          image200x100: image50x50\n                        }\n                      },\n                      row3: {\n                        items: {\n                          image200x100: image50x50\n                        }\n                      },\n                      row4: {\n                        items: {\n                          image200x100: image50x50\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\n\n  def image50x50\n    StringIO.new(dir.join('50x50.jpg').binread)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/stack_view_row_bottom_margin/README.md",
    "content": "# StackViewRow Bottom Margin\n\nrow の下余白とは、row のコンテンツの下位置と、row の下位置との間の距離である。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\nrow の下余白の仕様は section の下余白と同様である。詳細は [Section Bottom Margin](../section_report_section_bottom_margin/README.md) を参照。\n"
  },
  {
    "path": "test/section_report/features/stack_view_row_bottom_margin/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header\",\n      \"type\": \"header\",\n      \"height\": 240,\n      \"display\": true,\n      \"auto-stretch\": true,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 20,\n          \"y\": 10,\n          \"width\": 555,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 200,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 0,\n                  \"x2\": 555,\n                  \"y2\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"textblock\",\n                  \"x\": 40,\n                  \"y\": 40,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 200,\n                  \"y\": 20,\n                  \"width\": 100,\n                  \"height\": 120,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 360,\n                  \"y\": 40,\n                  \"width\": 160,\n                  \"height\": 150,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"dashed\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": false\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 370,\n                  \"y\": 50,\n                  \"width\": 112.2,\n                  \"height\": 37.8,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"affect-bottom-\",\n                    \"margin: false\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 20,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 0,\n                  \"x2\": 555,\n                  \"y2\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/stack_view_row_bottom_margin/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestStackViewRowBottomMarginFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header: {\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          textblock: 'long ' * 19 + 'text'\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/stack_view_row_parameters/README.md",
    "content": "# StackViewRow Parameter\n\nrow の定義時のプロパティの一部はパラメータで変更することができる。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n## 表示\n\n`display` プロパティで表示または非表示にすることができる。\n\n```\nrow_id: {\n  display: Boolean\n}\n```\n\n## 最小の高さ\n\n`min_height` プロパティで row の描画時の最小の高さを指定することができる。\n\n```\nrow_id: {\n  min_height: Number\n}\n"
  },
  {
    "path": "test/section_report/features/stack_view_row_parameters/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"header\",\n      \"type\": \"header\",\n      \"height\": 120,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"every-page\": false,\n      \"items\": [\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview1\",\n          \"x\": 43.38,\n          \"y\": 9.5,\n          \"width\": 359.99,\n          \"description\": \"\",\n          \"display\": true,\n          \"affect-bottom-margin\": true,\n          \"follow-stretch\": \"none\",\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 15,\n                  \"width\": 283.06,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row1 (display: true in the template)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 50,\n              \"auto-stretch\": false,\n              \"display\": false,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 15,\n                  \"width\": 290.06,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row2 (display: false in the template)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                }\n              ]\n            }\n          ]\n        }\n      ]\n    },\n    {\n      \"id\": \"detail\",\n      \"type\": \"detail\",\n      \"height\": 500,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview2\",\n          \"x\": 42.02,\n          \"y\": 10.2,\n          \"width\": 359.99,\n          \"description\": \"\",\n          \"display\": true,\n          \"affect-bottom-margin\": true,\n          \"follow-stretch\": \"none\",\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 35,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 187.77,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row1 (auto-stretch: off)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 35,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15.68,\n                  \"y\": 5,\n                  \"width\": 187.77,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row2 (auto-stretch: off)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 6.8,\n                  \"y1\": 1,\n                  \"x2\": 350.16,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"row3\",\n              \"height\": 90,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 188.08,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row3 (auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                },\n                {\n                  \"type\": \"image-block\",\n                  \"id\": \"image_block\",\n                  \"x\": 14.86,\n                  \"y\": 28.13,\n                  \"width\": 100,\n                  \"height\": 60,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"position-x\": \"left\",\n                    \"position-y\": \"top\"\n                  }\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 6.8,\n                  \"y1\": 1,\n                  \"x2\": 350.16,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"row4\",\n              \"height\": 90,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 188.08,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row4 (auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                },\n                {\n                  \"type\": \"image-block\",\n                  \"id\": \"image_block\",\n                  \"x\": 14.86,\n                  \"y\": 28.13,\n                  \"width\": 100,\n                  \"height\": 60,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"position-x\": \"left\",\n                    \"position-y\": \"top\"\n                  }\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 6.8,\n                  \"y1\": 1,\n                  \"x2\": 350.16,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"row5\",\n              \"height\": 55,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 188.08,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row5 (auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_block\",\n                  \"x\": 14.54,\n                  \"y\": 29.33,\n                  \"width\": 117.47,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  }\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 6.8,\n                  \"y1\": 1,\n                  \"x2\": 350.16,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"row6\",\n              \"height\": 55,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 188.08,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row6 (auto-stretch: on)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"text_block\",\n                  \"x\": 14.54,\n                  \"y\": 29.33,\n                  \"width\": 117.47,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 14,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 15.4\n                  }\n                },\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 6.8,\n                  \"y1\": 1,\n                  \"x2\": 350.16,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  }\n                }\n              ]\n            },\n            {\n              \"id\": \"\",\n              \"height\": 35,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 6.8,\n                  \"y1\": 1,\n                  \"x2\": 350.16,\n                  \"y2\": 1,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 15,\n                  \"y\": 5,\n                  \"width\": 46.03,\n                  \"height\": 23.7,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"affect-bottom-margin\": true,\n                  \"texts\": [\n                    \"Row7\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  }\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 12.07,\n          \"y1\": 1,\n          \"x2\": 581.54,\n          \"y2\": 1,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          }\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/stack_view_row_parameters/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestStackViewRowParametersFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            headers: {\n              header: {\n                items: {\n                  stackview1: {\n                    rows: {\n                      row1: {\n                        display: false\n                      },\n                      row2: {\n                        display: true\n                      }\n                    }\n                  }\n                }\n              }\n            },\n            details: [\n              {\n                id: :detail,\n                items: {\n                  stackview2: {\n                    rows: {\n                      row1: {\n                        min_height: 10\n                      },\n                      row2: {\n                        min_height: 70\n                      },\n                      row3: {\n                        min_height: 90,\n                        items: {\n                          image_block: dir.join('20x20.jpg').to_path\n                        }\n                      },\n                      row4: {\n                        min_height: 20,\n                        items: {\n                          image_block: dir.join('20x20.jpg').to_path\n                        }\n                      },\n                      row5: {\n                        min_height: 140,\n                        items: {\n                          text_block: 'text ' * 9\n                        }\n                      },\n                      row6: {\n                        min_height: 55,\n                        items: {\n                          text_block: 'text ' * 16\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/stack_view_with_floating_item/README.md",
    "content": "# StackView With Floating Item\n\nitem を stack-view の row から下にはみ出して配置することができる。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\nstack-view の row からはみ出して配置した場合でも、その状態を保って描画することができる。\nただし、はみ出す item は「下余白に影響」を無効にしておく必要がある。\n\n「下余白に影響」が有効の場合、row の下余白が負の値となり、意図しない結果となる場合がある。\n\nまた、下図の通り、stack-view の高さは、はみ出した item 全体を含んだ高さとなる。\n\n![](images/stack-view-height-with-floting-item.png)\n"
  },
  {
    "path": "test/section_report/features/stack_view_with_floating_item/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"detail\",\n      \"type\": \"detail\",\n      \"height\": 130,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 0,\n          \"y1\": 0,\n          \"x2\": 595.28,\n          \"y2\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"stack-view\",\n          \"id\": \"stackview\",\n          \"x\": 20,\n          \"y\": 30,\n          \"width\": 500,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"affect-bottom-margin\": true,\n          \"rows\": [\n            {\n              \"id\": \"row1\",\n              \"height\": 70,\n              \"auto-stretch\": true,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 0,\n                  \"x2\": 500,\n                  \"y2\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text-block\",\n                  \"id\": \"textblock\",\n                  \"x\": 40,\n                  \"y\": 30,\n                  \"width\": 100,\n                  \"height\": 20,\n                  \"description\": \"\",\n                  \"reference-id\": \"\",\n                  \"value\": \"\",\n                  \"multiple-line\": true,\n                  \"display\": true,\n                  \"format\": {\n                    \"base\": \"\",\n                    \"type\": \"\"\n                  },\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"overflow\": \"expand\",\n                    \"word-wrap\": \"break-word\",\n                    \"font-size\": 18,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 19.8\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"rect\",\n                  \"id\": \"\",\n                  \"x\": 200,\n                  \"y\": 20,\n                  \"width\": 170,\n                  \"height\": 150,\n                  \"border-radius\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"dashed\",\n                    \"fill-color\": \"#ffffff\",\n                    \"border-width\": 1\n                  },\n                  \"affect-bottom-margin\": false\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 210,\n                  \"y\": 30,\n                  \"width\": 150,\n                  \"height\": 37.8,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"affect-bottom-\",\n                    \"margin: false\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#000000\",\n                    \"font-style\": [],\n                    \"text-align\": \"left\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 16,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 17.6\n                  },\n                  \"affect-bottom-margin\": false\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 400,\n                  \"y\": 3,\n                  \"width\": 90,\n                  \"height\": 15,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"row1\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            },\n            {\n              \"id\": \"row2\",\n              \"height\": 20,\n              \"auto-stretch\": false,\n              \"display\": true,\n              \"items\": [\n                {\n                  \"type\": \"line\",\n                  \"id\": \"\",\n                  \"x1\": 0,\n                  \"y1\": 0,\n                  \"x2\": 500,\n                  \"y2\": 0,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"style\": {\n                    \"border-width\": 1,\n                    \"border-color\": \"#000000\",\n                    \"border-style\": \"solid\"\n                  },\n                  \"affect-bottom-margin\": true\n                },\n                {\n                  \"type\": \"text\",\n                  \"id\": \"\",\n                  \"x\": 400,\n                  \"y\": 3,\n                  \"width\": 90,\n                  \"height\": 15,\n                  \"description\": \"\",\n                  \"display\": true,\n                  \"follow-stretch\": \"none\",\n                  \"texts\": [\n                    \"row2 (dummy)\"\n                  ],\n                  \"style\": {\n                    \"font-family\": [\n                      \"Helvetica\"\n                    ],\n                    \"color\": \"#aaaaaa\",\n                    \"font-style\": [],\n                    \"text-align\": \"right\",\n                    \"vertical-align\": \"top\",\n                    \"letter-spacing\": \"\",\n                    \"font-size\": 12,\n                    \"line-height-ratio\": \"\",\n                    \"line-height\": 13.2\n                  },\n                  \"affect-bottom-margin\": true\n                }\n              ]\n            }\n          ]\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 495,\n          \"y\": 3,\n          \"width\": 90,\n          \"height\": 15,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"detail\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"fotter\",\n      \"type\": \"footer\",\n      \"height\": 20,\n      \"display\": true,\n      \"auto-stretch\": false,\n      \"items\": [\n        {\n          \"type\": \"line\",\n          \"id\": \"\",\n          \"x1\": 0,\n          \"y1\": 0,\n          \"x2\": 595.28,\n          \"y2\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"border-width\": 1,\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\"\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 495,\n          \"y\": 3,\n          \"width\": 90,\n          \"height\": 15,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"footer (dummy)\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#aaaaaa\",\n            \"font-style\": [],\n            \"text-align\": \"right\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 12,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 13.2\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/stack_view_with_floating_item/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestStackViewWithFloatingItemFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: [\n              {\n                id: 'detail',\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          textblock: 'short text'\n                        }\n                      }\n                    }\n                  }\n                }\n              },\n              {\n                id: 'detail',\n                items: {\n                  stackview: {\n                    rows: {\n                      row1: {\n                        items: {\n                          textblock: 'long ' * 19 + 'text'\n                        }\n                      }\n                    }\n                  }\n                }\n              }\n            ]\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\n\n  def image50x50\n    StringIO.new(dir.join('50x50.jpg').binread)\n  end\nend\n"
  },
  {
    "path": "test/section_report/features/text_block_vertical_align/README.md",
    "content": "# TextBlock Vertical-align Support\n\nsection-report 形式の text-block は `overflow: expand` のときの縦揃え(中央、下揃え)をサポートする。\n\n- [Example code](test_feature.rb)\n- [Example template file](template.tlf)\n- [Example PDF](expect.pdf)\n\n通常の形式の text-block は、`overflow: expand` で縦位置が中央又は下揃えのとき意図通りに描画されない。これは prawn の仕様によるものである。\n\nsection-report 形式では、これを独自にサポートしている。\n"
  },
  {
    "path": "test/section_report/features/text_block_vertical_align/template.tlf",
    "content": "{\n  \"schema-version\": \"1.0\",\n  \"last-modified-by\": \"1.0.0-sectionreport.1\",\n  \"title\": \"\",\n  \"report\": {\n    \"orientation\": \"portrait\",\n    \"paper-type\": \"A4\",\n    \"width\": 0,\n    \"height\": 0,\n    \"margin\": [\n      20,\n      20,\n      20,\n      20\n    ]\n  },\n  \"sections\": [\n    {\n      \"id\": \"top\",\n      \"type\": \"detail\",\n      \"height\": 100,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 20,\n          \"y\": 0,\n          \"width\": 555.28,\n          \"height\": 100,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 40,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"dashed\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 30,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 40,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 250,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 20,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"vertical-align: top\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"middle\",\n      \"type\": \"detail\",\n      \"height\": 100,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 20,\n          \"y\": 0,\n          \"width\": 555.28,\n          \"height\": 100,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 40,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"dashed\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 30,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 40,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"middle\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 250,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 20,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"vertical-align: middle\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    },\n    {\n      \"id\": \"bottom\",\n      \"type\": \"detail\",\n      \"height\": 100,\n      \"auto-stretch\": true,\n      \"items\": [\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 20,\n          \"y\": 0,\n          \"width\": 555.28,\n          \"height\": 100,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"solid\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"rect\",\n          \"id\": \"\",\n          \"x\": 30,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 40,\n          \"border-radius\": 0,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"height\",\n          \"style\": {\n            \"border-color\": \"#000000\",\n            \"border-style\": \"dashed\",\n            \"fill-color\": \"none\",\n            \"border-width\": 1\n          },\n          \"affect-bottom-margin\": false\n        },\n        {\n          \"type\": \"text-block\",\n          \"id\": \"text\",\n          \"x\": 30,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 40,\n          \"description\": \"\",\n          \"reference-id\": \"\",\n          \"value\": \"\",\n          \"multiple-line\": true,\n          \"display\": true,\n          \"format\": {\n            \"base\": \"\",\n            \"type\": \"\"\n          },\n          \"follow-stretch\": \"none\",\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"bottom\",\n            \"letter-spacing\": \"\",\n            \"overflow\": \"expand\",\n            \"word-wrap\": \"break-word\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        },\n        {\n          \"type\": \"text\",\n          \"id\": \"\",\n          \"x\": 250,\n          \"y\": 10,\n          \"width\": 200,\n          \"height\": 20,\n          \"description\": \"\",\n          \"display\": true,\n          \"follow-stretch\": \"none\",\n          \"texts\": [\n            \"vertical-align: bottom\"\n          ],\n          \"style\": {\n            \"font-family\": [\n              \"Helvetica\"\n            ],\n            \"color\": \"#000000\",\n            \"font-style\": [],\n            \"text-align\": \"left\",\n            \"vertical-align\": \"top\",\n            \"letter-spacing\": \"\",\n            \"font-size\": 18,\n            \"line-height-ratio\": \"\",\n            \"line-height\": 19.8\n          },\n          \"affect-bottom-margin\": true\n        }\n      ]\n    }\n  ],\n  \"state\": {\n    \"layout-guides\": []\n  }\n}"
  },
  {
    "path": "test/section_report/features/text_block_vertical_align/test_feature.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'test_helper'\n\nclass Thinreports::SectionReport::TestTextBlockVerticalAlignFeature < Thinreports::FeatureTest[__dir__]\n  feature do\n    params = {\n      type: :section,\n      layout_file: template_path,\n      params: {\n        groups: [\n          {\n            details: %i(top middle bottom).flat_map { |id|\n              [\n                {\n                  id: id,\n                  items: {\n                    text: 'short'\n                  }\n                },\n                {\n                  id: id,\n                  items: {\n                    text: 'long' * 20\n                  }\n                }\n              ]\n            }\n          }\n        ]\n      }\n    }\n    assert_pdf Thinreports.generate(params)\n  end\nend\n"
  },
  {
    "path": "test/section_report/test_helper.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'minitest/autorun'\nrequire 'minitest/unit'\nrequire 'mocha/minitest'\n\nrequire 'thinreports'\nrequire 'feature_test'\n\nMocha.configure do |c|\n  c.strict_keyword_argument_matching = true\nend\n"
  },
  {
    "path": "thinreports.gemspec",
    "content": "# frozen_string_literal: true\n\nrootdir = File.expand_path(File.dirname(__FILE__))\n\nrequire \"#{rootdir}/lib/thinreports/version\"\n\nGem::Specification.new do |s|\n  s.name        = 'thinreports'\n  s.version     = Thinreports::VERSION\n  s.author      = 'Matsukei Co.,Ltd.'\n  s.email       = 'thinreports@gmail.com'\n  s.summary     = 'An open source report generation tool for Ruby.'\n  s.description = 'Thinreports is an open source report generation tool for Ruby.'\n  s.homepage    = 'http://www.thinreports.org'\n  s.license     = 'MIT'\n  s.metadata    = { 'rubygems_mfa_required' => 'true' }\n\n  s.required_ruby_version = Gem::Requirement.new('>= 3.0.0')\n\n  s.files = Dir.chdir(File.expand_path('..', __FILE__)) do\n    `git ls-files -z`.split(\"\\x0\").reject { |f| f.match(%r{^test/}) }\n  end\n  s.require_paths = ['lib']\n\n  s.add_dependency 'prawn', '>= 2.4.0'\n  s.add_dependency 'prawn-disable_word_break', '>= 2.3.1'\n  s.add_dependency 'base64'\n  s.add_dependency 'bigdecimal'\n  s.add_dependency 'matrix'\n  s.add_dependency 'rexml'\nend\n"
  }
]