[
  {
    "path": ".dockerignore",
    "content": "node_modules/\nspec/dummy/db/*.sqlite3\nspec/dummy/db/*.sqlite3-journal\nspec/dummy/log/*.log\nspec/dummy/node_modules/\nspec/dummy/public/packs/\nspec/dummy/public/packs-test/\nspec/dummy/yarn-error.log\nspec/dummy/storage/\nspec/dummy/tmp/\nbuilder/db/*.sqlite3\nbuilder/db/*.sqlite3-journal\nbuilder/log/*.log\nbuilder/node_modules/\nbuilder/yarn-error.log\nbuilder/storage/\nbuilder/tmp/\nbuilder/public/packs\n.idea/\n.vscode\n.byebug_history\n\n/coverage\n"
  },
  {
    "path": ".gitattributes",
    "content": "docs/* linguist-documentation\n"
  },
  {
    "path": ".gitbook.yaml",
    "content": "root: ./docs/\n\nstructure:\n  readme: README.md\n  summary: SUMMARY.md\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: [matestack]\n"
  },
  {
    "path": ".github/issue_template.md",
    "content": "<!-- This is a template only, remove/add sections below as appropriate (e.g. for a new feature, there might be no 'current behavior'.) -->\n\n<!-- First indicate whether you want to request an ENHANCEMENT or report a BUG by using the correct Github label in the side panel* -->\n\n**What is the current behavior?**\n\n<!-- add current behavior here -->\n\n**If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug might get fixed faster if we can run your code and it doesn't have extra dependencies. Add a link to a sample repo and/or any relevant code below:**\n\n<!-- add additional links/info here -->\n\n**What is the expected behavior?**\n\n<!-- add expected behavior here -->\n\n**Which versions of Matestack, and which browser/OS are affected by this issue? Did this work in previous versions of Matestack?**\n\n<!-- add version and browser(s) affected, where relevant -->\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "**Note:** If you submit a feature or bugfix PR, pick **develop** as target branch (and delete this line afterwards).\n\n## Issue https://github.com/matestack/matestack-ui-core/issues/XXX: Short description here\n\n### Changes\n\n- [ ] Describe the changes in one or more bulletpoints\n\n### Notes\n\n- Let the reviewers know something special\n"
  },
  {
    "path": ".github/workflows/dockerpush.yml",
    "content": "name: specs\n\non:\n  push:\n    paths-ignore:\n      - 'docs/**'\n      - 'README.md'\n      - 'CHANGELOG.md'\n\njobs:\n  test_7_0_ruby_3_0:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run tests\n        run: |\n          docker-compose -f ./ci/docker-compose.ci.yml run --rm test_7_0_ruby_3_0\n      - name: Upload lock files\n        uses: actions/upload-artifact@v2\n        with:\n          name: lockfiles_test_7_0_ruby_3_0\n          path: |\n            ./ci/artifacts/Gemfile.lock\n  test_6_1_ruby_3_0:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run tests\n        run: |\n          docker-compose -f ./ci/docker-compose.ci.yml run --rm test_6_1_ruby_3_0\n      - name: Upload lock files\n        uses: actions/upload-artifact@v2\n        with:\n          name: lockfiles_test_6_1_ruby_3_0\n          path: |\n            ./ci/artifacts/Gemfile.lock\n  test_6_1_ruby_2_7:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run tests\n        run: |\n          docker-compose -f ./ci/docker-compose.ci.yml run --rm test_6_1_ruby_2_7\n      - name: Upload lock files\n        uses: actions/upload-artifact@v2\n        with:\n          name: lockfiles_test_6_1_ruby_2_7\n          path: |\n            ./ci/artifacts/Gemfile.lock\n  test_6_0_ruby_2_6:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run tests\n        run: |\n          docker-compose -f ./ci/docker-compose.ci.yml run --rm test_6_0_ruby_2_6\n      - name: Upload lock files\n        uses: actions/upload-artifact@v2\n        with:\n          name: lockfiles_test_6_0_ruby_2_6\n          path: |\n            ./ci/artifacts/Gemfile.lock\n  test_5_2_ruby_2_6:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v2\n      - name: Run tests\n        run: |\n          docker-compose -f ./ci/docker-compose.ci.yml run --rm test_5_2_ruby_2_6\n      - name: Upload lock files\n        uses: actions/upload-artifact@v2\n        with:\n          name: lockfiles_test_5_2_ruby_2_6\n          path: |\n            ./ci/artifacts/Gemfile.lock\n"
  },
  {
    "path": ".gitignore",
    "content": ".bundle/\nlog/*.log\nnode_modules/\ncoverage/\nspec/dummy/db/*.sqlite3\nspec/dummy/db/*.sqlite3-journal\nspec/dummy/log/*.log\nspec/dummy/node_modules/\nspec/dummy/public/packs/\nspec/dummy/public/packs-test/\nspec/dummy/yarn-error.log\nspec/dummy/storage/\nspec/dummy/tmp/\n.idea/\n.vscode\n.byebug_history\n"
  },
  {
    "path": ".rspec",
    "content": "--require spec_helper\n"
  },
  {
    "path": ".ruby-version",
    "content": "2.6.5\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## v3.0.1 Release - 2022-04-29\n\n### Bugfixes\n\n- fixing layout resolving issue when using the `turbo-rails` gem (like seen in a fresh Rails 7 setup)\n\n## v3.0.0 Release - 2022-03-04\n\n- same as v3.0.0.rc2\n\n## v3.0.0.rc2 Release - 2022-02-15\n\n### Bugfixes\n\n- fixing ActionView integration when using Ruby 3.x\n\n## v3.0.0.rc1 Release - 2022-02-11\n\n- Please read the [migration guide](docs/migrate-from-2.x-to-3.0.md)\n\n## v2.1.1 Release - 2021-06-30\n\n### Bugfixes\n\n- Fixed clientside Data Access form new nested forms\n\n## v2.1.0 Release - 2021-06-28\n\n### Improvements\n\n- Nested Form Support #558\n- Component render? Method #553\n- Page Component Cleanup\n- Docs Cleanup\n\n### Bugfixes\n\n- Form Error Reset #539 via #558\n- Form File Upload Init File Value #550\n\n\n## v2.0.0 Release - 2021-04-12\n\nPlease refer to the [migration guide](./docs/migrate-from-1.x-to-2.0.md)\n\n## v1.5.0 Release - 2021-03-07\n\n### Improvements\n\n- NPM package usage\n\n## v1.4.0 Release - 2021-02-05\n\n### Improvements\n\n- Ruby 3 support\n- Vue update to 2.6.12\n- Vuex update to 3.6.2\n- Gemspec update clarifying that Rails below 5.2 is not supported (EOL versions anyway!)\n- CI test runs against multiple Rails/Ruby version combination\n\n### Bugfixes\n\n- Webpacker 6 support #500\n\n### Security bumps\n\n- Various version bumps triggered through dependabot\n\n## v1.3.2 Release - 2021-01-11\n\n### Bugfixes\n\n- Fixes #503 new vue-turbolinks v2.2.0 causes error on webpacker compile\n\n### Security bumps\n\n- Various version bumps triggered through dependabot\n\n## v1.3.1 Release - 2020-12-28\n\n### Bugfixes\n\n- Fixes #497 Cable component throws browser error when initial content contains form component\n\n## v1.3.0 Release - 2020-12-22\n\n### Potential breaking change\n\nIf you have used a `form_submit` component like this:\n\n```ruby\nform_submit do\n  button text: \"Submit me!\", attributes: { \"v-bind:disabled\": \"loading\" }\nend\n```\n\nin order to disable the the button during submission of the form, please turn `loading` into `loading()`:\n\n\n```ruby\nform_submit do\n  button text: \"Submit me!\", attributes: { \"v-bind:disabled\": \"loading()\" }\nend\n```\n\nIf you have implemented your own form components, please adjust them as described in the customize section of each form component. Most likely, you now have to provide exactly one root element per form component due to the reworked form components.\n\n### Improvements\n\n- Splitted form API docs into multiple files\n- Implements #474 Add HTML `<select>` tag to core components\n- Implements #492 Enable extendability of `form_*` components\n  - Reworked `form_*` components in order to provide a better API for custom form components\n  - `form_*` components are separate Vue.js components now\n  - Each `form_*` uses a Vue.js mixin and a Ruby base class. This mixin and base class can be used in custom components in order to easy create own form components\n\n## Bugfixes\n\n- Fixes #490 Custom classes for checkboxes\n- Fixes #494 true/false checkboxes are initialized incorrectly\n\n\n## v1.2.0 Release - 2020-11-20\n\n### Improvements\n\n* Enable usage of Rails view/route helpers on standalone components used via matestack_component helper #476\n\n## v1.1.0 Release - 2020-10-16\n\n### Improvements\n\n* added the `cable` component in order to use ActionCable to update the DOM\n\n## v1.0.1 Release - 2020-10-07\n\nThis release contains bugfixes.\n\n### Bugfixes\n\n*  Fixed javascript automatic scroll top on page transition for short pages #462\n*  Enable async components on app level, only usable in pages and components before #458\n*  Fixed duplicate directory error when using matestack-ui-core with webpacker #460\n\n\n## v1.0.0 Release - 2020-09-10\n\nPlease note that this release contains breaking changes and soft deprecations. To make things easy for users of the current `v0.7.*` version, we have provided **Migration TODOs** at the end of each chapter.\n\n### Migration guide for 0.7.x users\n\n#### 1. Using `render Pages::X` instead of `responder_for(Pages::X)` in controllers\n\nInstead of:\n\n```ruby\nclass SomeController < ApplicationController\n  include Matestack::Ui::Core::ApplicationHelper\n\n  def some_page\n    responder_for(Pages::SomePage)\n  end\n\nend\n```\n\nwrite now:\n\n```ruby\nclass SomeController < ApplicationController\n  include Matestack::Ui::Core::ApplicationHelper\n\n  def some_page\n    render Pages::SomePage\n  end\n\nend\n```\n\nPlease note that while the `responder_for` method is still being supported, it will be removed in a future release.\n\n**Migration TODOs:**\n\n- [ ] Replace `responder_for` with `render` in your controllers\n\n#### 2. App/Page structure and namespacing\n\nUntil `0.7.x`, matestack-ui-core enforced the user to keep apps and pages in a specific folder structure. An app like `Apps::MyApp` had to be stored in `app/matestack/apps/my_app.rb` and an associated page like `Pages::MyApp::MyPage` lived in `app/matestack/pages/my_app/my_page.rb`. The namespace `Pages::MyApp` determined that the page `MyPage` should be wrapped with the layout coming from `Apps::MyApp`.\n\nWe changed this behavior in favor of more intuitive namespacing and more control/flexibility on namespaces and folder structure:\n\n**Flexible folder structure and namespacing of apps and pages**\n\nApps and pages can now actually live anywhere within your project - but we still recommend sticking to some best practices, shown further below. The relation between apps and pages is no longer derived from the (folder) namespace.\n\n**Explicit app/page relation on controller level**\n\nWithin a controller, you can now set the desired `matestack_app` that then wraps all pages used in this controller. This definition is inheritable - therefore, you can set in on an `ApplicationController` to make it a default for all controllers and actions, and overwrite it if needed.\n\nBoth \"global\" and \"controller-level\" `matestack_app` settings can be overwritten on \"action-level\" using an additional parameter for the `render` method.\n\nThe code snippet below shows some common use cases:\n\n```ruby\nclass SomeController < ApplicationController\n  include Matestack::Ui::Core::ApplicationHelper\n\n  matestack_app MyApp #default for all action on this controller and inherited ones\n\n  def some_page\n    render SomePage\n  end\n\n  def some_page_with_other_app\n    render SomePage, matestack_app: SomeOtherApp #overwrite controller level matestack_app\n  end\n\n  def some_page_with_other_app\n    render SomePage, matestack_app: :none #overwrite controller level matestack_app and set to no app at all\n  end\n\nend\n```\n\n**Default App**\nIf no `matestack_app` is defined or it is deliberately set to `:none` as demonstrated above, matestack-ui-core will by default render the page wrapped by a minimal app. This happens in order to provide basic app-related matestack-ui-core features like `transition` and others.\n\nIt is possible to explicitly prevent this behavior by setting `matestack_app` to false:\n\n```ruby\nclass SomeController < ApplicationController\n  include Matestack::Ui::Core::ApplicationHelper\n\n\n  def some_page\n    render SomePage #will render with minimal default app if no app is specified on action or controller level\n  end\n\n  def some_page_with_no_app\n    render SomePage, matestack_app: false #set to no app at all\n  end\n\nend\n```\n\n**Recommended best practice for app/page folder structure and namespacing**\n\nImagine your project has two \"apps\". An \"admin\" area and a public \"website\" area. Your folder structure could look like this:\n\n```\napp/matestack/\n|\n└───admin/\n│   │   app.rb (`Admin::App < Matestack::Ui::App`)\n│   └───pages/\n│   │   │   dashboard.rb  (`Admin::Pages::Dashboard < Matestack::Ui::Page`)\n|\n└───website/\n│   │   app.rb (`Website::App < Matestack::Ui::App`)\n│   └───pages/\n│   │   │   home.rb  (`Website::Pages::Home < Matestack::Ui::Page`)\n```\n\nand your corresponding controllers could look like this:\n\n`app/controllers/admin_controller.rb`\n\n```ruby\nclass AdminController < ApplicationController\n  include Matestack::Ui::Core::ApplicationHelper\n\n  matestack_app Admin::App\n\n  before_action :authenticate_admin! # for example\n\n  def dashboard\n    render Admin::Pages::Dashboard\n  end\n\nend\n```\n\n`app/controllers/website_controller.rb`\n\n```ruby\nclass WebsiteController < ApplicationController\n  include Matestack::Ui::Core::ApplicationHelper\n\n  matestack_app Website::App\n\n  def home\n    render Website::Pages::Home\n  end\n\nend\n```\n\n**Migration TODOs:**\n\nYou can decide to either\n- [ ] keep the `0.7.x` folder structure if you want\n- [ ] and set the related app on your controllers via `matestack_app` (as it will no longer be derived automatically from the page namespace)\n\nor\n\n- [ ] refactor your app/page structure according to your needs, and set the related apps on a controller level\n\n#### 3. Base component class name adjustments\n\nWe decided to rename the base component class names in order to create a better understanding of what they are:\n\n* `Matestack::Ui::StaticComponent` --> `Matestack::Ui::Component`\n* `Matestack::Ui::DynamicComponent` --> `Matestack::Ui::VueJsComponent`\n\n**Migration TODOs:**\n\nYou can decide to either\n- [ ] we still keep the old class names, but we recommend to adjust the base class names as described above\n\n#### 3. Explicit component registration\n\nA major change happened to the component resolving approach. Until `0.7.x`, matestack-ui-core automatically translated core component calls like `some_component` to a class like `Matestack::Ui::Core::Some::Component`, which had to be defined within the core library at `CORE_ROOT/app/concepts/matestack/ui/core/some/component.rb`. The same applied for custom component calls like `custom_my_component` which resolved to a class `Components::My::Component` which had to be defined within the user's application at `APP_ROOT/app/matestack/components/my/component.rb`.\n\nThis auto resolving is being completely removed in the `1.0.0` release. All components (core, custom and add-on-engine) have to be registered explicitly as described below:\n\n*Core components*\n\n`CORE_ROOT/lib/matestack/ui/core/components.rb`\n\n```ruby\nmodule Matestack::Ui::Core::Components\n  #...\n  require_core_component \"some/new/component\"\n  #...\nend\n\nMatestack::Ui::Core::Component::Registry.register_components(\n  #...\n  some_new_component: Matestack::Ui::Core::Some::New::Component,\n  #...\n)\n```\n\nThe registered DSL method `some_new_component` does not have to match the components namespace structure.\n\n*Custom components*\n\nCreate a registry module like:\n\n`APP_ROOT/app/matestack/components/registry.rb`\n\n```ruby\nmodule Components::Registry\n\n  Matestack::Ui::Core::Component::Registry.register_components(\n    #...\n    my_component: Components::MyOwnComponent,\n    #...\n  )\n\nend\n```\n\nand make sure to include this module in your base controller like:\n\n```ruby\nclass ApplicationController < ActionController::Base\n\n  include Matestack::Ui::Core::ApplicationHelper\n  include Components::Registry\n\nend\n```\n\nLike in the core, the registered DSL method `my_component` does not have to match the component's namespace structure. In this example, the custom `MyOwnComponent` lives in `app/matestack/components/my_own_component.rb` and is being referenced as `my_component`.\n\nTBD:\n\nPlease be aware that once the component registry was loaded, the initially registered dsl_methods are cached. Removing a dsl_method from the registry will not have an effect until the server gets reloaded. Added dsl_methods however will be available without having to restart the server.\n\n*AddOn engine component*\n\nTODO\n\n**Migration TODOs:**\n\nIf you are already using custom components:\n- [ ] Add a component registry in `APP_ROOT/app/matestack/components/registry.rb`\n- [ ] Register your existing components like `    my_component: Components::MyOwnComponent`, respecting their namespaces and setting dls_methods of your choice. The obligation of prefixing them with a `custom_` does no longer apply.\n- [ ] Since the new dls_methods may differ from the former method calls, you need to refactor the custom component usage on existing apps and pages (e.g. formerly `custom_my_own_component` should now be called `my_component`)\n\n#### 4.1 Dynamic (Vue.js) core component naming\n\nUntil `1.0.0`, dynamic core components created the Vue.js component name automatically by deriving it from their class name. `Matestack::Ui::Core::Collection::Filter::Filter`, for example, was translated to the Vue.js componente name `matestack-ui-core-collection-filter`. The two occurrences of `Filter` at the end of the class name (which comes from the folder structure and namespacing constraints) was automatically detected and taken care of, so the Vue.js component name only had one occurrence of `filter` in it.\n\nThis behavior changes in `1.0.0`:\n\n* `Matestack::Ui::Core::Collection::Filter::Filter` will be translated to `matestack-ui-core-collection-filter-filter` without any further processing per default\n* It is now possible to set the Vue.js component name manually within the component configuration:\n\n```ruby\nclass Matestack::Ui::Core::Collection::Filter::Filter < Matestack::Ui::VueJsComponent\n  vue_js_component_name \"matestack-ui-core-collection-filter\"\n\n  #...\n\nend\n```\n\n**Migration Todos:**\n\nCore developers only:\n-[ ] set Vue.js component name explicitly in order to match current Vue.js component names of all dynamic core components\n\n#### 4.2 Dynamic (Vue.js) custom component naming\n\nFormerly, custom components behaved differently than core components. `Components::Some::Component` was translated to a Vue.js component named `custom-some-component`, in order to match their (now changed) dsl method name `custom_some_component`\n\nThis behavior changes in `1.0.0`:\n\n* Without any further default processing, `Components::Some::Component` will be translated into `components-some-component`\n* It is now possible to set the Vue.js component name manually:\n\n```ruby\nclass Components::Some::Component < Matestack::Ui::VueJsComponent\n  vue_js_component_name \"some-component\"\n\n  #...\n\nend\n```\n\n**Migration Todos:**\n\nPlease note that you have two options, but an action is required to make the new release work with existing custom dynamic components. Either you\n\n- [ ] set Vue.js component name explicitly in order to match current Vue.js component naming of all custom components\n\nOR\n\n- [ ] adapt the name of your custom Vue.js components to the new naming schema demonstrated above\n\n\n#### 5. No more components block wrapping in Pages/Components/Apps\n\nInstead of:\n\n```ruby\ndef response\n  components {\n    div do\n      plain \"hello!\"\n    end\n  }\nend\n```\n\nyou can now write:\n\n```ruby\ndef response\n  div do\n    plain \"hello!\"\n  end\nend\n```\n\nPlease note that the `components` block is still supported, but will be removed in a `1.0` release.\n\n**Migration Todos:**\n\n- [ ] To be on the safe side, remove all the `components {}` wrapping blocks in your apps and pages\n\n\n#### 6. Partials are now normal method calls and don't need a block\n\nInstead of writing:\n\n```ruby\ndef response\n  components {\n    div do\n      partial :my_partial, \"foo\"\n    end\n  }\nend\n\ndef my_partial param\n  partial {\n    plain param\n  }\nend\n```\n\nyou can now write:\n\n```ruby\ndef response\n  div do\n    my_partial \"foo\" #normal method call with optional params\n  end\nend\n\ndef my_partial param\n  plain param # no more partial {} block\nend\n```\n\nPlease note that the old `partial` block and method call approach are still supported but will be removed in a `1.0` release.\n\n**Migration Todos:**\n\n- [ ] To be on the safe side, remove all the `partial {}` wrapping blocks in the partials on your apps, pages and custom components\n\n#### 7. Slot syntax stays the same\n\nWe still need the `slot` block wrapping around slot content\n\n```ruby\ndef response\n  div do\n    some_static_component my_first_slot: my_simple_slot\n  end\nend\n\ndef my_simple_slot\n  slot do\n    span id: \"my_simple_slot\" do\n      plain \"some content\"\n    end\n  end\nend\n```\n\n#### 8. `page_content` should now be `yield_page`\n\nWe changed the naming to be more expressive and in order to align with the existing `yield_components`\n\n**Migration Todos:**\n\n- [ ] On an app layout, you should now use `yield_page` instead of `page_component`\n\n#### 9. Wrapping DOM structure of pages has changed\n\nWe changed the DOM structure around pages in order to enable better page loading state implementations.\nWe also changed the class names of these wrapping divs in order to better match css naming conventions\n\n```html\n<!-- some layout markup -->\n<div class=\"matestack-page-container\">\n  <div class=\"matestack-page-wrapper\">\n    <div><!--this div is necessary for conditional switch to async template via v-if -->\n      <div class=\"matestack-page-root\">\n        your page markup\n      </div>\n    </div>\n  </div>\n</div>\n<!-- some layout markup -->\n```\n\n**Migration Todos:**\n\n- [ ] If you used the old DOM structure and css class names of the wrapping elements for styling, please adjust your CSS accordingly\n\n#### 10. `yield_page` can now take a loading_state slot\n\nIn order to simplify the implementation of page loading state effects, we added an optional loading_state slot for `yield_page`:\n\n`app/matestack/example_app/app.rb`\n\n```ruby\nclass ExampleApp::App < Matestack::Ui::App\n\n  def response\n    # some layout stuff\n    main do\n      yield_page slots: { loading_state: my_loading_state_slot }\n    end\n    # some layout stuff\n  end\n\n  def my_loading_state_slot\n    slot do\n      span class: \"some-loading-spinner\" do\n        plain \"loading...\"\n      end\n    end\n  end\n\nend\n```\n\nwhich will render:\n\n```html\n<main>\n  <div class=\"matestack-page-container\">\n    <div class=\"loading-state-element-wrapper\">\n      <span class=\"some-loading-spinner\">\n        loading...\n      </span>\n    </div>\n    <div class=\"matestack-page-wrapper\">\n      <div><!--this div is necessary for conditional switch to async template via v-if -->\n        <div class=\"matestack-page-root\">\n          your page markup\n        </div>\n      </div>\n    </div>\n  </div>\n</end>\n```\n\nand during async page request triggered via transition:\n\n```html\n<main>\n  <div class=\"matestack-page-container loading\">\n    <div class=\"loading-state-element-wrapper loading\">\n      <span class=\"some-loading-spinner\">\n        loading...\n      </span>\n    </div>\n    <div class=\"matestack-page-wrapper loading\">\n      <div><!--this div is necessary for conditional switch to async template via v-if -->\n        <div class=\"matestack-page-root\">\n          your page markup\n        </div>\n      </div>\n    </div>\n  </div>\n</end>\n```\n\nYou can use the `loading` class and your loading state element to implement CSS based loading state effects.\n\n#### 11. `async` component now requires an ID\n\nWe changed the way how matestack resolves the content of an `async` component on rerender calls. It is now required to apply an ID to the `async` component\n\n```ruby\nasync rerender_on: \"some-event\", id: \"my-unique-id\" do\n  plain hello!\nend\n```\n\n**Migration Todos:**\n\n- [ ] Please add an unique ID to each `async` component usage, even if matestack is currently auto-generating an ID if not applied. This will be removed in future releases\n\n#### 12. New `toggle` component is replacing `async` shown_on, hide_on, hide_after...\n\nWe decided to move all pure clientside view state manipulation logic from the `async` component to a new component called `toggle`. `async` should now only take care of serverside rerendering based on events.\n\n```ruby\nasync show_on: \"some-event\" do\n  plain hello!\nend\n# should now be:\ntoggel show_on: \"some-event\" do\n  plain hello!\nend\n```\n\n**Migration Todos:**\n\n- [ ] Please use the new `toggle` component wherever you used `async show_on/hide_on/hide_after`\n\n#### 13. `async` DOM structure and loading state\n\nThe `async` components wrapping DOM structure has changed in order to align with the wrapping DOM structure of pages and isolated components:\n\n```ruby\nasync rerender_on: \"some-event\", id: \"my-unique-id\" do\n  plain hello!\nend\n```\n\nwill render to:\n\n```html\n<div class=\"matestack-async-component-container\">\n  <div class=\"matestack-async-component-wrapper\">\n    <div id=\"my-unique-id\" class=\"matestack-async-component-root\">\n      hello!\n    </div>\n  </div>\n</div>\n```\n\nand during rerender:\n\n```html\n<div class=\"matestack-async-component-container loading\">\n  <div class=\"matestack-async-component-wrapper loading\">\n    <div id=\"my-unique-id\" class=\"matestack-async-component-root\" >\n      hello!\n    </div>\n  </div>\n</div>\n```\n\n**Migration Todos:**\n\n- [ ] If you used the old DOM structure and css class names of the wrapping elements for styling, please adjust your CSS accordingly\n\n\n#### 14. `form` component changes\n\nWe reworked the form components quite a bit:\n\n- `include` keyword is no longer required\n- `form_input` component no longer supports the input type textarea.\n- Textareas were extracted in a component and can be used as standalone`textarea` or in forms with `form_textarea`.\n- `form_input`component now supports all types according to W3Cs possible types.\n- `form_select` is now only used for HTML select dropdowns\n- `form_radio` is used for rendering radio button inputs\n- `form_checkbox` is used for rendering checkbox inputs, either a single (true/false) checkbox or multiple checkboxes\n- options passed as hashes in to `form_select`, `form_radio` and `form_checkbox` are now expected to be { label_value: input_value } and thus the other way around. Until 0.7.6 it was { input_value: label_value }\n- and added a lot of new features, such as customizing the error rendering.\n\nWe invested a lot of time to improve the `form` API docs found [here](/docs/api/100-components/form.md).\n\n- [ ] Please make sure to read through the docs and migrate your forms accordingly!\n\n#### 15. New approach towards isolated components\n\nWe completely rethought the way we approached isolated components.\n\nThe old approach:\n\n```ruby\ndef response\n  #...\n  isolate :my_isolated_scope\n  #...\nend\n\ndef my_isolated_scope\n  isolate {\n    plain \"I'm isolated\"\n  }\nend\n```\nis removed.\n\nInstead, we created a new component class `Matestack::Ui::IsolatedComponent`. You can build custom component which inherits from this class in order to create components, which will be resolved completely isolated on rerender calls:\n\n```ruby\nclass MyPage < Matestack::Ui::Page\n\n  def response\n    #...\n    my_isolated_component defer: true, public_params: { id: 1 }\n    #...\n  end\n\nend\n```\n\n```ruby\nclass MyIsolatedComponent < Matestack::Ui::IsolatedComponent\n\n  def prepare\n    my_model = MyModel.find public_params[:id]\n  end\n\n  def response\n    div do\n      plain \"#{my_model} was resolved isolated within in a separate http request after page load\"\n    end\n  end\n\n  def authorized?\n    true\n    # check access here using current_user for example when using Devise\n    # true means, this isolated component is public\n  end\nend\n```\n\nUsing an isolated component with `defer` speeds up the init page load on complex UIs.\n\n**Migration Todos:**\n\n- [ ] Create custom isolated components wherever you used the old approach towards isolate\n\n#### 16. Params access from apps, pages and components\n\nIn order to access to request params like we do on controller level, we added the `params` method to apps, pages and components:\n\n```ruby\ndef response\n  plain context[:params][:id]\n  #or\n  plain @url_params[:id]\nend\n\n# should now be:\ndef response\n  plain params[:id]\nend\n```\n\n**Migration Todos:**\n\n- [ ] Switch to the new `params` method in order to access request params. `@url_params` will be deprecated in future releases\n\n#### 16. LICENSE change\n\nAs we're performing a major release from 0.7.6 to 1.0.0, we're able to switch the license. We decided to go for the [LGPLv3 license](http://www.gnu.org/licenses/lgpl-3.0.html) following the example of Sidekiq or Trailblazer. That won't have an effect on users of our library as long as you're just using `matestack-ui-core` and not creating/publishing a derivative work. You can use `matestack-ui-core` in commercial closed source applications without any issues.Trailblazer has a comprehensive article on that [topic](https://trailblazer.to/2.1/docs/pro.html#pro-license).\n\nOur goal is to create a sustainable open source project. Therefore we need to secure funding. Selling commercial licenses on top of the LGPLv3 license for companies wanting to create/sell closed source derivative work of `matestack-ui-core` should be one pillar of that funding.\n\n#### 17. Wrap-up\n\nAfter following all the **Migration Todos**, your application should work just fine. If that's not the case, please [open a GitHub issue](https://github.com/matestack/matestack-ui-core/issues/new) and/or improve this guide!\n\n### Improvements\n\n#### Using matestack components in Rails Views\n\nIt is now possible to use `matestack-ui-core` core and custom components in your Rails legacy views. Matestack provides a `matestack_component` helper to use components in views and partials.\n\nCreate a custom component like\n```ruby\nclass HeaderComponent < Matestack::Ui::Component\n  requires :title\n\n  def response\n    header id: 'my-page-header', text: title\n  end\n\nend\n```\n\nand register it in your registry\n```ruby\nmodule Components::Registry\n  Matestack::Ui::Core::Component::Registry.register_components(\n    header_component: HeaderComponent,\n  )\nend\n```\n\nNow, you can go ahead and use it in your views as shown below, even passing arguments works:\n```html\n<%= matestack_component(:header_component, title: 'A Title') %>\n```\n\n### Using Rails Views in Matestack Pages/Components\n\nTo render existing rails views inside your components or pages, use the new `rails_view` component. It replaces the old `html` component.\nYou can render existing partials and views with this helper anywhere in your app. For further information read the `rails_view` documentation.\n\nLet's say you have an old view file in `app/views/example/partial.html.erb`\n\n```html\n<p>An example text in a Rails view</p>\n```\n\nYou could go ahead and re-use it in a component (or simply add it to a page) like:\n```ruby\nclass TextComponent < Matestack::Ui::Component\n\n  def response\n    paragraph text: 'Example text directly in the component'\n    rails_view path: `example/partial.html.erb`\n  end\n\nend\n```\n\n### Collection select\n\n\n\n### Removed Components\n\n#### 1. Inline Component\n\nThe Form Inline Component has been removed and can no longer be used.\n\n#### 2. Absolute Component\n\nThe Absolute Component has been removed and can no longer be used.\n\n## v0.7.6 - 2020-05-06\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.6)\n\n[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.6)\n\n### Security Fixes\n\n* Various dependency version bumps by dependabot\n\n### Bugfixes\n\n* Radio button groups with same values on single page #399\n* Async rerendered components have access to ActionView context #405\n* Transition component `active` class fixed #408 #410\n* Query params were missing in async page load request when using browser history navigation #409\n\n### Improvements\n\n* Apps now have access to ActionView context #405\n* Transition component `active-child` class added #410\n* Added specs for ActionView context access #411\n* Added file upload feature to form (single and multiple) #413\n* Added form, transition, action `delay` option #412\n* Added form, action `emit` option #412\n* Added multi event listening to `async` component option #412 #147\n* Added Rails 6 support\n* Updated core dev and test environment to Rails 6\n* Added form/action `redirect_to` option #415\n\n## v0.7.5 - 2020-03-11\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.5)\n\n[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.5)\n\n### Security Fixes\n\n* Various dependency version bumps by dependabot\n\n### Improvements\n\n* Added `datalist` component\n* Added `range` type for `form_input`\n* Integrated generator specs in CI spec run\n* Added `turbolinks` support\n* Form component: Add support for `redirect_to` in the controller\n* HasViewContext: Check in advance whether the view context would respond to a missing method.\n\n### Bugfixes\n\n* Fixed broken history button behavior introduced in `0.7.4` #386\n\n## v0.7.4 2020-02-10\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.4)\n\n[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.4)\n\n### Security Fixes\n\nXSS/Script injection vulnerablilty fixed in 0.7.4\n\n* matestack-ui-core was vulnerable to XSS/Script injection\n* matestack-ui-core did not escape strings by default and did not cover this in the docs\n* matestack-ui-core should have escaped strings by default in order to prevent XSS/Script injection vulnerability\n* 0.7.4 fixes that by performing string escaping by default now\n* a new component `unescaped` (like `plain` before) allows to render unescaped strings, but forces the developer to explicitly make a concious decision about that\n\n```ruby\nclass Pages::MyApp::MyExamplePage < Matestack::Ui::Page\n\n  class FakeUser < Struct.new(:name)\n  end\n\n  def prepare\n    @user = FakeUser.new(\"<script>alert('such hack many wow')</script>\")\n  end\n\n  def response\n    components {\n      div do\n        heading size: 1, text: \"Hello #{@user.name}\" # was not escaped , from 0.7.4 on it's escaped\n        plain \"Hello #{@user.name}\" # was not escaped, from 0.7.4 on it's escaped\n        unescaped \"Hello #{@user.name}\" # is not escaped, as intended\n      end\n    }\n  end\nend\n\n```\n\nAffected Versions\n\n<= 0.7.3\n\nPatched Versions\n\n>= 0.7.4 --> please update!\n\nWorkarounds\n\nescape string explicitly/manually\n\nreported by @PragTob\n\n### Improvements\n\n* On form submit, matestack form values are reset to previous values by fiedl\n\n--> The form component now does not reset itself when using `put`\n\n--> The reset behavior can now be configured (described in `form` component docs)\n\n* Dockerized core dev and test environment by jonasjabari\n\n--> easy local dev and test setup, cross-platform default for dev and testing\n\n--> CI is configured to run tests via dockerized test suite; same as local testing and good base for matrix testing (upcoming)\n\n--> Usage described in contribution docs\n\n* Add `follow_response` option to action component by fiedl\n\n--> same behavior enhancement as added to the `form` component in 0.7.3\n\n--> server may now decide where the transition should navigate to\n\n--> described in `action` component docs\n\n* Add confirm option to action component by fiedl\n\n--> easily add confirmation before performing an action\n\n--> prevent unintended delete action for example\n\n--> described in `action` component docs\n\n* New webpacker features by fiedl\n\n  * make webpacker create es5 code instead of es6 code\n\n  * Switch to Vue Production Mode if RAILS_ENV=staging or production\n\n  * Establish webpack(er) and asset-pipeline workflows\n\n--> webpacker now builds assets for asset pipline usage AND webpacker usage (both usage approaches are described in the installation docs)\n\n--> webpacker now builds minified versions of matestack-ui-core.js (great improvement in file size!)\n\n--> webpacker now builds es5 code, which is compatible with IE11\n\n--> when used via asset pipeline, the minified version of matestack-ui-core together with the production build of vue.js is automatically required\n\n--> when used via webpacker, matestack-ui-core can be used within a modern javascript workflow, importing and extending\nsingle matestack module for example\n\n* New components\n  * Add HTML `<picture>` tag to core components by pascalwengerter\n  * Add HTML `<option>` tag to core components by pascalwengerter\n  * Add HTML `<optgroup>` tag to core components by pascalwengerter\n  * Add HTML `<iframe>` tag to core components by pascalwengerter\n  * Add HTML `<dfn>` tag to core components by pascalwengerter\n  * Add HTML `<del>` tag to core components by pascalwengerter\n  * Add HTML `<data>` tag to core components by pascalwengerter\n  * Add HTML `<bdo>` tag to core components by pascalwengerter\n  * Add HTML `<bdi>` tag to core components by pascalwengerter\n  * Add HTML `<wbr>` tag to core components by pascalwengerter\n  * Add HTML `<samp>` tag to core components by pascalwengerter\n  * Add HTML `<u>` tag to core components by pascalwengerter\n  * Add HTML `<template>` tag to core components by pascalwengerter\n\n\n### Bugfixes\n\n* Anchor Link Click triggers full page transition by PragTob\n\n\n## v0.7.3 - 2019-11-10\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/pulls?q=is%3Apr+is%3Aclosed+milestone%3A0.7.3)\n\n[Solved Issues](https://github.com/basemate/matestack-ui-core/issues?q=is%3Aissue+is%3Aclosed+milestone%3A0.7.3)\n\n### Potential Breaking Change - Migration Note\n\nUntil `0.7.2.1`, we included all `ActionView` modules in `Matestack::Ui::StaticComponent` and `Matestack::Ui::DynamicComponent`. As we didn't use these modules in all of our core components, we decided to move the `ActionView` modules to the new `Matestack::Ui::StaticActionviewComponent` and `Matestack::Ui::DynamicActionviewComponent` class. If you use `ActionView` modules in your components, you have to change the class you inherit from. This might be a potential breaking change for some users - we are not bumping to 0.8.0 as we don't break explicit specified behavior. If you have any problems, reach out via gitter!\n\n### Security Fixes\n\nnone\n\n### Improvements\n\n* Move ActionView dependencies to separate, custom-core-component by pascalwengerter\n* Add documentation for testing on macOS by marcoroth\n* Add HTML `<ruby>` tag to core components by stiwwelll\n* Add HTML `<rt>` tag to core components by stiwwelll\n* Add HTML `<rp>` tag to core components by stiwwelll\n* Add HTML `<q>` tag to core components by GrantBarry\n* Add HTML `<pre>` tag to core components by tae8838\n* Add HTML `<param>` tag to core components by marcoroth\n* Add HTML `<output>` tag to core components by marcoroth\n* Add HTML `<object>` tag to core components by pascalwengerter\n* Add HTML `<noscript>` tag to core components by stiwwelll\n* Add HTML `<meter>` tag to core components by bdlb77\n* Add HTML `<mark>` tag to core components by marcoroth\n* Add HTML `<map>` tag to core components by pascalwengerter\n* Add HTML `<legend>` tag to core components by stiwwelll\n* Add HTML `<kbd>` tag to core components by marcoroth\n* Add HTML `<ins>` tag to core components by lumisce\n* Add HTML `<figure>` tag to core components by lumisce\n* Add HTML `<em>` tag to core components by citizen428\n* Add HTML `<dt>` tag to core components by mayanktap\n* Add HTML `<dl>` tag to core components by mayanktap\n* Add HTML `<dd>` tag to core components by mayanktap\n* Add HTML `<code>` tag to core components by pascalwengerter\n* Add HTML `<cite>` tag to core components by cameronnorman\n* Add HTML `<var>` tag to core components by pascalwengerter\n* Add HTML `<s>` tag to core components by Manukam\n* Add HTML `<bold>` tag to core components by GrantBarry\n* Add HTML `<area>` tag to core components by pascalwengerter\n* Add tests for video component by MarcoBomfim\n* Usage of RecordTagHelper by pascalwengerter\n* Add HTML `<aside>` tag to core components by borref\n* Add HTML `<address>` tag to core components by michaelrevans\n* Add HTML `<sup>` tag to core components by borref\n* Add params options to link component documentation by pascalwengerter\n\n### Bugfixes\n\n* Unexpected behavior when creating a record in progress by jonasjabari\n* couldn't find file 'matestack_ui_core_manifest.js' on dummy app by jonasjabari\n* Add For Attribute to Stand Alone Label Component by bdlb77\n* Form component doesn't work on component-level by jonasjabari\n* Async component doesn't work on component-level by jonasjabari\n\n\n## v0.7.2.1 - 2019-09-10\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/milestone/5?closed=1)\n\n### Security Fixes\n\n- Dependency version bump (nokogiri) by dependabot\n\n### Bugfixes\n\n- Fixed image component 157 #158 by jonasjabari\n\n## v0.7.2 - 2019-09-05\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/milestone/4?closed=1)\n\n### Security Fixes\n\n- Various dependency version bumps by dependabot\n\n### Improvements\n\n- Add Isolation Component #154 by jonasjabari\n- Update integration docs #149 by pascalwengerter\n- Add youtube component #144 by pascalwengerter\n- Support new Doc App #143 by jonasjabari\n- Add class option to dropdown form selects  enhancement#135 by 3wille\n- Refactor core components v2  enhancement#134 by pascalwengerter\n- add sub tag  enhancement#132 by pascalwengerter\n- Add article component with docs and specs #127 by michaelrevans\n- Add address tag, specs and documentation #126 by michaelrevans\n- Extra table components #125 by michaelrevans\n- Add abbr component with specs and documentation #124 by michaelrevans\n- Add article component with docs and specs #122 by michaelrevans\n- Add address tag, specs and documentation #121 by michaelrevans\n- Add abbr component #120 by michaelrevans\n- Add thead, tbody and tfoot components\n\n### Bugfixes\n\n- Add init_show state to async component 140 #152 by jonasjabari\n- added missing @tag_attributes #151 by jonasjabari\n- update yarn and fix controller action name #141 by pascalwengerter\n\n## v0.7.1 - 2019-08-01\n\n[Merged PRs](https://github.com/basemate/matestack-ui-core/milestone/3?closed=1)\n\n### Improvements\n\n- Introduce scaffolder #72 by PasWen\n- Make buttons disableable  enhancement by PasWen\n- Collection Component #98 by jonasjabari\n- Added Async Defer Feature #100 by jonasjabari\n- Added blockquote tag to main component #88 by cameronnorman\n- Added small tags #87 by cameronnorman\n- Added strong tag #93 by cameronnorman\n- Added Infos that async component can currently only be used on page leve #85 by jonasjabari was merged 10\n- Update span component in 0.7.0 #74 by PasWen\n- Add documented, untested video component #70 by PasWen\n- Added summary details components #76 by bdlb77\n- Add caption with doc and specs  enhancement #68 by michaelrevans\n\n### Bugfixes\n\n- Fixed Link Component #84 by jonasjabari\n\n## v0.7.0 - 2019-06-25\n\n### Breaking changes for users\n\n* new base class names for pages, components and apps, issue #36 (@jonasjabari)\n* simplified custom component structure/class names #39 (@jonasjabari)\n* improved vue.js component naming convention #41 (@jonasjabari)\n* `pg` component is now called `paragraph`, issue #47, pull #48 (@PasWen)\n\n### Improvements for users\n\n* added `hr` component, pull #49, (@michaelrevans)\n* allow actions to accept id and class attributes, issue #44, pull #50 (@michaelrevans)\n\n### Breaking changes for core developers\n\n* namespaced core components using `Matestack::Ui::Core` module/folder, pull #64 (@jonasjabari)\n* simplified core components folder structure, (aligned with issue #39), pull #64 (@jonasjabari)\n* changed vue.js component naming, (aligned with issue #41), pull #64 (@jonasjabari)\n* add-on engine components now need `Matestack::Ui` namespacing, pull #64 (@jonasjabari)\n\n### Improvements for core developers\n\n* started to move business logic out of `app/concepts` into `app/lib` folder in order to create a better structure (in progress --> core refactoring)\n\n### Migration guide for users from v0.6.0\n\n#### App base class name\n\n***OLD:***\n\n`app/matestack/app/example_app.rb`\n\n```ruby\nclass Apps::ExampleApp < App::Cell::App end\n```\n\n***NEW:***\n\n`app/matestack/app/example_app.rb`\n\n```ruby\nclass Apps::ExampleApp < Matestack::Ui::App end\n```\n\n#### Page base class name\n\n***OLD:***\n\n`app/matestack/pages/example_app/example_page.rb`\n\n```ruby\nclass Pages::ExampleApp::ExamplePage < Page::Cell::Page end\n```\n\n***NEW:***\n\n`app/matestack/pages/example_app/example_page.rb`\n\n```ruby\nclass Pages::ExampleApp::ExamplePage < Matestack::Ui::Page end\n```\n\n#### Custom STATIC component base class name / folder structure\n\n***OLD:***\n\n`app/matestack/components/card/cell/card.rb`\n\n```ruby\nclass Components::Card::Cell::Card < Component::Cell::Static end\n```\n\n***NEW:***\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::StaticComponent end\n```\n\n#### Custom DYNAMIC component base class name / folder structure / vue.js naming\n\n***OLD:***\n\n`app/matestack/components/card/cell/card.rb`\n\n```ruby\nclass Components::Card::Cell::Card < Component::Cell::Dynamic end\n```\n\n`app/matestack/components/card/cell/card.js`\n\n```javascript\nMatestackUiCore.Vue.component('custom-card-cell', { ... });\n```\n\n***NEW:***\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::DynamicComponent end\n```\n\n`app/matestack/components/card.js`\n\n```javascript\nMatestackUiCore.Vue.component('custom-card', { ... }); //no -cell postfix\n```\n\n#### Paragraph component\n\n***OLD:***\n\n`app/matestack/pages/example_app/example_page.rb`\n\n```ruby\nclass Pages::ExampleApp::ExamplePage < Matestack::Ui::Page\n\n  def response\n    components {\n      pg do\n        plain \"some text\"\n      end\n    }\n  end\n\nend\n```\n\n***NEW:***\n\n`app/matestack/pages/example_app/example_page.rb`\n\n```ruby\nclass Pages::ExampleApp::ExamplePage < Matestack::Ui::Page\n\n  def response\n    components {\n      paragraph do\n        plain \"some text\"\n      end\n    }\n  end\n\nend\n```\n\n### Migration guide for core developers from v0.6.0\n\nIf you are not a CORE contributor, this part might not be relevant for you ;)\n\n#### Namespaced core components + simplified core components folder/module structure\n\nThe core components are moved from `app/concepts` to `app/concepts/matestack/ui/core` in order to stick to the engine namespacing (used in helpers etc...) and therefore scoped like:\n\n```\napp/concepts/matestack/ui/core\n|\n└───div\n│   │   div.rb (no cell folder anymore!)\n│   │   div.haml (no view folder anymore!)\n```\n\n`app/concepts/matestack/ui/core/div/div.rb`\n\n```ruby\nmodule Matestack::Ui::Core::Div\n  class Div < Matestack::Ui::Core::Component::Static\n\n\n  end\nend\n```\n\nWe also removed the `Cell` module (`cell` folder) and the separate `js` and `view` folders in each component folder in order to simplify folder structure (as we did for custom component development as well)\n\n**Note**\n\nLast module name and class name of CORE components have to be the same. That doesn't apply for CUSTOM components:\n\n`app/matestack/pages/example_app/example_page.rb`\n\n```ruby\nclass Pages::ExampleApp::ExamplePage < Matestack::Ui::Page\n\n  def response\n    components {\n      #CORE\n      div\n      # looking for 'Matestack::Ui::Core::Div::Div'\n      # defined in 'app/concepts/matestack/ui/core/div/div.rb'\n      form_input\n      # looking for 'Matestack::Ui::Core::Form::Input::Input'\n      # defined in 'app/concepts/matestack/ui/core/form/input/input.rb'\n\n      #CUSTOM\n      custom_card\n      # looking for 'Components::Card'\n      # defined in 'app/matestack/components/card.rb'\n      custom_fancy_card\n      # looking for 'Components::Fancy::Card'\n      # defined in 'app/matestack/components/fancy/card.rb'\n    }\n  end\n\nend\n```\n\nThe reasons why we decided to resolve core components a bit different than custom components are simple:\n* we want to make it as easy as possible to create custom components\n  * we therefore removed the obligatory `Cell` module\n  * we do not want to force the user to create a subfolder (and therefore module/namespace) in their `components` folder resulting in a class like:\n  `Components::Card::Card`. It should be as simple as `Components::Card` which is good and intuitive!\n* if we would use that simple approach for all our core components, it would lead to a messy code base, as all component cells, views and javascripts live in one big folder.\n  * we therefore enforce more structure inside the core, using a subfolder for each component within `app/concepts/matestack/ui/core` resulting in a class name for a component like: `Matestack::Ui::Core::Div::Div` (double DIV at the end --> subfolder(module name) :: class)\n\n#### Changed vue.js component naming\n\nScoping all core components within `Matestack::Ui::Core` is reflected in different vue.js component name as well:\n\nExample: `async` core component\n\n`app/concepts/matestack/ui/core/async`\n\n```javascript\n//old\nVue.component('async-cell', componentDef)\n//new\nVue.component('matestack-ui-core-async', componentDef)\n```\n\nWe also removed the `-cell` postfix.\n\n#### Add-on-engine component namespacing\n\nAdd-on-engine components now need `Matestack::Ui` namespacing:\n\nExample:\n\n```\nADDON_ENGINE_ROOT/app/concepts/matestack/ui/materialize\n|\n└───row\n│   │   row.rb\n│   │   row.haml\n```\n\n`ADDON_ENGINE_ROOT/app/concepts/matestack/ui/materialize/row/row.rb`\n\n```ruby\nmodule Matestack::Ui::Materialize::Row\n  class Row < Matestack::Ui::Core::Component::Static\n\n    def response\n      components {\n        div class: \"row\" do\n          yield_components\n        end\n      }\n    end\n\n  end\nend\n```\nUsage:\n\n`app/matestack/pages/example_app/example_page.rb`\n\n```ruby\nclass Pages::ExampleApp::ExamplePage < Matestack::Ui::Page\n\n  def response\n    components {\n      #CORE\n      div\n      # looking for 'Matestack::Ui::Core::Div::Div'\n      # defined in 'CORE_ENGINE_ROOT/app/concepts/matestack/ui/core/div/div.rb'\n\n      #ENGINE\n      materialize_row\n      # looking for 'Matestack::Ui::Materialize::Row::Row'\n      # defined in 'ADDON_ENGINE_ROOT/app/concepts/matestack/ui/materialize/row/row.rb'\n    }\n  end\n\nend\n```\n\n## v0.6.0 - 2019-04-27\n\n### Improvements\n\n* added documentation\n* added tests\n\n## v0.6.0.pre.1 - 2019-02-26\n\nThis release is marked as PRE. Test coverage is not sufficient at the moment.\n\n### Breaking Changes\n\n* Form component now need the ':include' keyword in order to populate the form config to its children\n* Input components are now renamed to form_* in order to show their dependency to a parent form component\n\n### Improvements\n\n* partials may now be defined in modules and used across multiple page classes\n* components may now define required attributes, which get validated automatically\n* components now raises more specific error messages\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at pascal@matestack.io. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "Dockerfile.dev",
    "content": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev npm libtool && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY Gemfile* /app/\nRUN bundle install\n"
  },
  {
    "path": "Dockerfile.test",
    "content": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev npm libtool && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY Gemfile* /app/\nRUN bundle install\n\nRUN apk update && apk upgrade \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \\\n    && apk add --no-cache \\\n    chromium=86.0.4240.111-r0 \\\n    nss@edge \\\n    && rm -rf /var/lib/apt/lists/* \\\n    /var/cache/apk/* \\\n    /usr/share/man \\\n    /tmp/*\n\nRUN apk add chromium-chromedriver=86.0.4240.111-r0\n\nENV CHROME_BIN=/usr/bin/chromium-browser \\\n    CHROME_PATH=/usr/lib/chromium/\n"
  },
  {
    "path": "Gemfile",
    "content": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's dependencies in matestack-ui-core.gemspec.\n# Bundler will treat runtime dependencies like base dependencies, and\n# development dependencies will be added by default to the :development group.\ngemspec\n\n# Declare any dependencies that are still in development here instead of in\n# your gemspec. These might include edge Rails or gems from your path or\n# Git. Remember to move these dependencies to your gemspec before releasing\n# your gem to rubygems.org.\n\ngem 'rails', '~> 7.0.1'\n\ngem 'turbo-rails'\n\ngroup :development, :test do\n  gem 'rspec-rails', '~> 4.0.2'\n  gem 'capybara'\n  gem 'webpacker', '~> 5.0'\n  gem 'pg', '>= 0.18', '< 2.0'\n  gem 'selenium-webdriver'\n  gem 'puma'\n  gem 'simplecov', require: false, group: :test\n  gem 'byebug'\n  gem 'webmock'\nend\n\ngroup :test do\n  gem 'pry-rails'\n  gem 'pry-byebug'\n  gem \"generator_spec\"\n  # gem \"rspec-retry\" # repeating flaky tests\n  # gem \"rspec-wait\", \"~> 0.0.9\"\nend\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) MateLab GmbH\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": "[![Specs](https://github.com/matestack/matestack-ui-core/workflows/specs/badge.svg)](https://github.com/matestack/matestack-ui-core/actions)\n[![Discord](https://img.shields.io/discord/771413294136426496.svg)](https://discord.com/invite/c6tQxFG)\n[![Gem Version](https://badge.fury.io/rb/matestack-ui-core.svg)](https://badge.fury.io/rb/matestack-ui-core)\n[![Docs](https://img.shields.io/badge/docs-matestack-blue.svg)](https://docs.matestack.io)\n[![Twitter Follow](https://img.shields.io/twitter/follow/matestack.svg?style=social)](https://twitter.com/matestack)\n\n![matestack logo](./logo.png)\n\n# matestack-ui-core | Component based web UIs in pure Ruby for Rails\n\nBoost your productivity & easily create component based web UIs in pure Ruby.\n\n`matestack-ui-core` enables you to craft maintainable web UIs in pure Ruby, skipping ERB and HTML. UI code becomes a native and fun part of your Rails app. `matestack-ui-core` can progressively replace the classic Rails-View-Layer. You are able to use\nit alongside your classic views.\n\n## Compatibility\n\n`matestack-ui-core` is tested against:\n\n- Rails 7.0.1 + Ruby 3.0.0\n- Rails 6.1.1 + Ruby 3.0.0\n- Rails 6.1.1 + Ruby 2.7.2\n- Rails 6.0.3.4 + Ruby 2.6.6\n- Rails 5.2.4.4 + Ruby 2.6.6\n\nRails versions below 5.2 are not supported.\n\n## Documentation/Installation\n\nDocumentation can be found [here](https://docs.matestack.io/matestack-ui-core)\n\n## Getting started\n\nA getting started guide can be found [here](https://docs.matestack.io/matestack-ui-core/getting-started/hello-world)\n\n## Changelog\n\nChangelog can be found [here](./CHANGELOG.md)\n\n## Community\n\nAs a low-barrier feedback channel for our early users, we have set up a Discord server that can be found [here](https://discord.com/invite/c6tQxFG). You are very welcome to ask questions and send us feedback there!\n\n## Contribution\n\nWe are happy to accept contributors of any kind! In order to make it as easy and fun as possible to contribute to `matestack-ui-core`, we would like to onboard contributors personally! Best way to become a contributor: Ping us on Discord! We will schedule a video call with you and show you, how and what to work on :)\n\n## Feature walk-through\n\n### 1. Create UI components in pure Ruby\n\nCraft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.\n\n#### Implement UI components in pure Ruby\n\nCreate Ruby classes within your Rails project and call matestack's core components through a Ruby DSL in order to craft your UIs.\nThe Ruby method \\\"div\\\" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. \\\"title\\\") or require them (e.g. \\\"body\\\").\n\n`app/matestack/components/card.rb`\n\n```ruby\n\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      div class: \"card-body\" do\n        h5 context.title if context.title.present?\n        paragraph context.body, class: \"card-text\"\n      end\n    end\n  end\n\nend\n\n```\n\n#### Use your Ruby UI components on your existing Rails views\n\nComponents can be then called on Rails views (not only! see below), enabling you to create a reusable card components, abstracting UI complexity in your own components.\n\n`app/views/your_view.html.erb`\n\n```erb\n\n<!-- some other erb markup -->\n<%= Components::Card.call(title: \"hello\", body: \"world\") %>\n<!-- some other erb markup -->\n\n```\n\n\n#### Use Ruby methods as partials\n\nSplit your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation.\nUsing this approach helps you to create a clean, readable and maintainable codebase.\n\n`app/matestack/components/card.rb`\n\n```ruby\n\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n  optional :footer\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      card_content\n      card_footer if context.footer.present?\n    end\n  end\n\n  def card_content\n    div class: \"card-body\" do\n      h5 context.title if context.title.present?\n      paragraph context.body, class: \"card-body\"\n    end\n  end\n\n  def card_footer\n    div class: \"card-footer text-muted\" do\n      plain context.footer\n    end\n  end\n\nend\n\n```\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::Card.call(title: \"hello\", body: \"world\", footer: \"foo\") %>\n<!-- some other erb markup -->\n```\n\n\n#### Use class inheritance\n\nBecause it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation.\nClass inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.\n\n`app/matestack/components/blue_card.rb`\n\n```ruby\n\nclass Components::BlueCard < Components::Card\n\n  def response\n    div class: \"card shadow-sm border-0 bg-primary text-white\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      card_content #defined in parent class\n      card_footer if context.footer.present? #defined in parent class\n    end\n  end\n\nend\n\n```\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::BlueCard.call(title: \"hello\", body: \"world\") %>\n<!-- some other erb markup -->\n```\n\n#### Use components within components\n\nJust like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components.\nYou decide when using a Ruby method partial should be replaced by another self contained UI component!\n\n`app/matestack/components/card.rb`\n\n```ruby\n\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      # calling the CardBody component rather than using Ruby method partials\n      Components::CardBody.call(title: context.title, body: context.body)\n    end\n  end\n\nend\n\n```\n`app/matestack/components/card_body.rb`\n\n```ruby\n\nclass Components::CardBody < Matestack::Ui::Component\n\n  required :body\n  optional :title\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      h5 context.title if context.title.present?\n      paragraph context.body, class: \"card-body\"\n    end\n  end\n\nend\n\n```\n\n\n#### Yield components into components\n\nSometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components!\nUsing this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.\n\n\n`app/matestack/components/card.rb`\n\n```ruby\n\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      Components::CardBody.call() do\n        # yielding a block into the card_body component\n        h5 context.title if context.title.present?\n        paragraph context.body, class: \"card-body\"\n      end\n    end\n  end\n\nend\n\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\n\nclass Components::CardBody < Matestack::Ui::Component\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      yield if block_given?\n    end\n  end\n\nend\n\n```\n\n#### Use named slots for advanced content injection\n\nIf you need to inject multiple blocks into your UI component, you can use \\\"slots\\\"!\nSlots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!\n\n`app/matestack/components/card.rb`\n\n```ruby\n\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      Components::CardBody.call(slots: {\n        heading: method(:heading_slot),\n        body: method(:body_slot)\n      })\n    end\n  end\n\n  def heading_slot\n    h5 context.title if context.title.present?      \n  end\n\n  def body_slot\n    paragraph context.body, class: \"card-body\"\n  end\n\nend\n\n```\n`app/matestack/components/card_body.rb`\n\n```ruby\n\nclass Components::CardBody < Matestack::Ui::Component\n\n  required :slots\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      div class: \"heading-section\" do\n        slot :heading\n      end\n      div class: \"body-section\" do\n        slot :body\n      end\n    end\n  end\n\nend\n\n```\n\n## License\n\n`matestack-ui-core` is an Open Source project licensed under the terms of the [MIT license](./LICENSE)\n"
  },
  {
    "path": "Rakefile",
    "content": "begin\n  require 'bundler/setup'\nrescue LoadError\n  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'\nend\n\nrequire 'rdoc/task'\n\nRDoc::Task.new(:rdoc) do |rdoc|\n  rdoc.rdoc_dir = 'rdoc'\n  rdoc.title    = 'Matestack::Ui::Core'\n  rdoc.options << '--line-numbers'\n  rdoc.rdoc_files.include('README.md')\n  rdoc.rdoc_files.include('lib/**/*.rb')\nend\n\nAPP_RAKEFILE = File.expand_path(\"spec/dummy/Rakefile\", __dir__)\nload 'rails/tasks/engine.rake'\n\nload 'rails/tasks/statistics.rake'\n\nrequire 'bundler/gem_tasks'\n\nrequire 'rake/testtask'\n\n# Rake::TestTask.new(:test) do |t|\n#   t.libs << 'test'\n#   t.pattern = 'test/**/*_test.rb'\n#   t.verbose = false\n# end\n#\n# task default: :test\n\ntask :webpack => 'webpack:build'\n\nnamespace :webpack do\n  task :build => ['build:development', 'build:production']\n\n  namespace :build do\n    task :development => 'yarn:install' do\n      Bundler.with_unbundled_env do\n        sh \"cd builder && bin/webpack\"\n      end\n    end\n    task :production => 'yarn:install' do\n      Bundler.with_unbundled_env do\n        sh \"cd builder && bin/rake webpacker:compile\"\n      end\n    end\n  end\n\n  task :watch => 'yarn:install' do\n    Bundler.with_unbundled_env do\n      sh \"cd builder && bin/webpack --watch\"\n    end\n  end\n\n  namespace :yarn do\n    task :install do\n      sh \"yarn install && cd builder && yarn install\"\n    end\n  end\nend\n\n"
  },
  {
    "path": "bin/rails",
    "content": "#!/usr/bin/env ruby\n# This command will automatically be run when you run \"rails\" with Rails gems\n# installed from the root of your application.\n\n# ENGINE_ROOT = File.expand_path('..', __dir__)\n# ENGINE_PATH = File.expand_path('../lib/matestack/ui/core/engine', __dir__)\nAPP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)\n\n# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)\nrequire 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])\n\nrequire 'rails/all'\nrequire 'rails/engine/commands'\n"
  },
  {
    "path": "ci/Dockerfile.test_5_2_ruby_2_6",
    "content": "FROM ruby:2.6-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY ./ci/Gemfile.5.2 /app/Gemfile\nRUN bundle install\n\nRUN apk update && apk upgrade \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \\\n    && apk add --no-cache \\\n    chromium=86.0.4240.111-r0 \\\n    nss@edge \\\n    && rm -rf /var/lib/apt/lists/* \\\n    /var/cache/apk/* \\\n    /usr/share/man \\\n    /tmp/*\n\nRUN apk add chromium-chromedriver=86.0.4240.111-r0\n\nENV CHROME_BIN=/usr/bin/chromium-browser \\\n    CHROME_PATH=/usr/lib/chromium/\n\nRUN mv Gemfile _Gemfile\nRUN mv Gemfile.lock _Gemfile.lock\nCOPY . /app\nRUN rm Gemfile\nRUN rm Gemfile.lock\nRUN mv _Gemfile Gemfile\nRUN mv _Gemfile.lock Gemfile.lock\n\nWORKDIR /app/spec/dummy\n\nRUN npm install\nRUN ./bin/webpack\n\nRUN rm ./db/schema.rb\n\nRUN rm ./config/application.rb\nRUN mv ./config/application.5.2_rb /app/spec/dummy/config/application.rb\n\nWORKDIR /app\n"
  },
  {
    "path": "ci/Dockerfile.test_6_0_ruby_2_6",
    "content": "FROM ruby:2.6-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY ./ci/Gemfile.6.0 /app/Gemfile\nRUN bundle install\n\nRUN apk update && apk upgrade \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \\\n    && apk add --no-cache \\\n    chromium=86.0.4240.111-r0 \\\n    nss@edge \\\n    && rm -rf /var/lib/apt/lists/* \\\n    /var/cache/apk/* \\\n    /usr/share/man \\\n    /tmp/*\n\nRUN apk add chromium-chromedriver=86.0.4240.111-r0\n\nENV CHROME_BIN=/usr/bin/chromium-browser \\\n    CHROME_PATH=/usr/lib/chromium/\n\nRUN mv Gemfile _Gemfile\nRUN mv Gemfile.lock _Gemfile.lock\nCOPY . /app\nRUN rm Gemfile\nRUN rm Gemfile.lock\nRUN mv _Gemfile Gemfile\nRUN mv _Gemfile.lock Gemfile.lock\n\nWORKDIR /app/spec/dummy\n\nRUN npm install\nRUN ./bin/webpack\n\nRUN rm ./db/schema.rb\n\nRUN rm ./config/application.rb\nRUN mv ./config/application.6.0_rb /app/spec/dummy/config/application.rb\n\nWORKDIR /app\n"
  },
  {
    "path": "ci/Dockerfile.test_6_1_ruby_2_7",
    "content": "FROM ruby:2.7-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY ./ci/Gemfile.6.1 /app/Gemfile\nRUN bundle install\n\nRUN apk update && apk upgrade \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \\\n    && apk add --no-cache \\\n    chromium=86.0.4240.111-r0 \\\n    nss@edge \\\n    && rm -rf /var/lib/apt/lists/* \\\n    /var/cache/apk/* \\\n    /usr/share/man \\\n    /tmp/*\n\nRUN apk add chromium-chromedriver=86.0.4240.111-r0\n\nENV CHROME_BIN=/usr/bin/chromium-browser \\\n    CHROME_PATH=/usr/lib/chromium/\n\nRUN mv Gemfile _Gemfile\nRUN mv Gemfile.lock _Gemfile.lock\nCOPY . /app\nRUN rm Gemfile\nRUN rm Gemfile.lock\nRUN mv _Gemfile Gemfile\nRUN mv _Gemfile.lock Gemfile.lock\n\nWORKDIR /app/spec/dummy\n\nRUN npm install\nRUN ./bin/webpack\n\nRUN rm ./db/schema.rb\n\nRUN rm ./config/application.rb\nRUN mv ./config/application.6.1_rb /app/spec/dummy/config/application.rb\n\nWORKDIR /app\n"
  },
  {
    "path": "ci/Dockerfile.test_6_1_ruby_3_0",
    "content": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY ./ci/Gemfile.6.1 /app/Gemfile\nRUN bundle install\n\nRUN apk update && apk upgrade \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \\\n    && apk add --no-cache \\\n    chromium=86.0.4240.111-r0 \\\n    nss@edge \\\n    && rm -rf /var/lib/apt/lists/* \\\n    /var/cache/apk/* \\\n    /usr/share/man \\\n    /tmp/*\n\nRUN apk add chromium-chromedriver=86.0.4240.111-r0\n\nENV CHROME_BIN=/usr/bin/chromium-browser \\\n    CHROME_PATH=/usr/lib/chromium/\n\nRUN mv Gemfile _Gemfile\nRUN mv Gemfile.lock _Gemfile.lock\nCOPY . /app\nRUN rm Gemfile\nRUN rm Gemfile.lock\nRUN mv _Gemfile Gemfile\nRUN mv _Gemfile.lock Gemfile.lock\n\nWORKDIR /app/spec/dummy\n\nRUN npm install\nRUN ./bin/webpack\n\nRUN rm ./db/schema.rb\n\nRUN rm ./config/application.rb\nRUN mv ./config/application.6.1_rb /app/spec/dummy/config/application.rb\n\nWORKDIR /app\n"
  },
  {
    "path": "ci/Dockerfile.test_7_0_ruby_3_0",
    "content": "FROM ruby:3.0-alpine3.12\n\nRUN gem install bundler:2.1.4\n\nRUN apk update --no-cache && \\\n    apk add build-base postgresql-dev git nodejs yarn tzdata bash sqlite-dev shared-mime-info npm && \\\n    mkdir -p /app\n\nWORKDIR /app\n\nCOPY ./lib/ /app/lib/\nCOPY matestack-ui-core.gemspec /app/\nCOPY ./ci/Gemfile.7.0 /app/Gemfile\nRUN bundle install\n\nRUN apk update && apk upgrade \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/community >> /etc/apk/repositories \\\n    && echo @edge http://nl.alpinelinux.org/alpine/edge/main >> /etc/apk/repositories \\\n    && apk add --no-cache \\\n    chromium=86.0.4240.111-r0 \\\n    nss@edge \\\n    && rm -rf /var/lib/apt/lists/* \\\n    /var/cache/apk/* \\\n    /usr/share/man \\\n    /tmp/*\n\nRUN apk add chromium-chromedriver=86.0.4240.111-r0\n\nENV CHROME_BIN=/usr/bin/chromium-browser \\\n    CHROME_PATH=/usr/lib/chromium/\n\nRUN mv Gemfile _Gemfile\nRUN mv Gemfile.lock _Gemfile.lock\nCOPY . /app\nRUN rm Gemfile\nRUN rm Gemfile.lock\nRUN mv _Gemfile Gemfile\nRUN mv _Gemfile.lock Gemfile.lock\n\nWORKDIR /app/spec/dummy\n\nRUN npm install\nRUN ./bin/webpack\n\nRUN rm ./db/schema.rb\n\nRUN rm ./config/application.rb\nRUN mv ./config/application.7.0_rb /app/spec/dummy/config/application.rb\n\nWORKDIR /app\n"
  },
  {
    "path": "ci/Gemfile.5.2",
    "content": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's dependencies in matestack-ui-core.gemspec.\n# Bundler will treat runtime dependencies like base dependencies, and\n# development dependencies will be added by default to the :development group.\ngemspec\n\n# Declare any dependencies that are still in development here instead of in\n# your gemspec. These might include edge Rails or gems from your path or\n# Git. Remember to move these dependencies to your gemspec before releasing\n# your gem to rubygems.org.\n\ngem 'rails', '5.2.4.4'\n\ngroup :development, :test do\n  gem 'rspec-rails', '~> 3.8'\n  gem 'capybara'\n  gem 'webpacker', '~> 4.0'\n  gem 'pg', '>= 0.18', '< 2.0'\n  gem 'selenium-webdriver'\n  gem 'puma'\n  gem 'simplecov', require: false, group: :test\n  gem 'byebug'\n  gem 'webmock'\n  gem 'turbolinks'\nend\n\ngroup :test do\n  gem 'pry-rails'\n  gem 'pry-byebug'\n  gem \"generator_spec\"\n  gem \"rspec-retry\" # repeating flaky tests\n  gem \"rspec-wait\", \"~> 0.0.9\"\nend\n"
  },
  {
    "path": "ci/Gemfile.6.0",
    "content": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's dependencies in matestack-ui-core.gemspec.\n# Bundler will treat runtime dependencies like base dependencies, and\n# development dependencies will be added by default to the :development group.\ngemspec\n\n# Declare any dependencies that are still in development here instead of in\n# your gemspec. These might include edge Rails or gems from your path or\n# Git. Remember to move these dependencies to your gemspec before releasing\n# your gem to rubygems.org.\n\ngem 'rails', '6.0.3.4'\n\ngroup :development, :test do\n  gem 'rspec-rails', '~> 3.8'\n  gem 'capybara'\n  gem 'webpacker', '~> 4.0'\n  gem 'pg', '>= 0.18', '< 2.0'\n  gem 'selenium-webdriver'\n  gem 'puma'\n  gem 'simplecov', require: false, group: :test\n  gem 'byebug'\n  gem 'webmock'\n  gem 'turbolinks'\nend\n\ngroup :test do\n  gem 'pry-rails'\n  gem 'pry-byebug'\n  gem \"generator_spec\"\n  gem \"rspec-retry\" # repeating flaky tests\n  gem \"rspec-wait\", \"~> 0.0.9\"\nend\n"
  },
  {
    "path": "ci/Gemfile.6.1",
    "content": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's dependencies in matestack-ui-core.gemspec.\n# Bundler will treat runtime dependencies like base dependencies, and\n# development dependencies will be added by default to the :development group.\ngemspec\n\n# Declare any dependencies that are still in development here instead of in\n# your gemspec. These might include edge Rails or gems from your path or\n# Git. Remember to move these dependencies to your gemspec before releasing\n# your gem to rubygems.org.\n\ngem 'rails', '6.1.1'\n\ngroup :development, :test do\n  gem 'rspec-rails', '~> 4.0.2'\n  gem 'capybara'\n  gem 'webpacker', '~> 4.0'\n  gem 'pg', '>= 0.18', '< 2.0'\n  gem 'selenium-webdriver'\n  gem 'puma'\n  gem 'simplecov', require: false, group: :test\n  gem 'byebug'\n  gem 'webmock'\n  gem 'turbolinks'\nend\n\ngroup :test do\n  gem 'pry-rails'\n  gem 'pry-byebug'\n  gem \"generator_spec\"\n  gem \"rspec-retry\" # repeating flaky tests\n  gem \"rspec-wait\", \"~> 0.0.9\"\nend\n"
  },
  {
    "path": "ci/Gemfile.7.0",
    "content": "source 'https://rubygems.org'\ngit_source(:github) { |repo| \"https://github.com/#{repo}.git\" }\n\n# Declare your gem's dependencies in matestack-ui-core.gemspec.\n# Bundler will treat runtime dependencies like base dependencies, and\n# development dependencies will be added by default to the :development group.\ngemspec\n\n# Declare any dependencies that are still in development here instead of in\n# your gemspec. These might include edge Rails or gems from your path or\n# Git. Remember to move these dependencies to your gemspec before releasing\n# your gem to rubygems.org.\n\ngem 'rails', '7.0.1'\n\ngroup :development, :test do\n  gem 'rspec-rails', '~> 4.0.2'\n  gem 'capybara'\n  gem 'webpacker', '~> 4.0'\n  gem 'pg', '>= 0.18', '< 2.0'\n  gem 'selenium-webdriver'\n  gem 'puma'\n  gem 'simplecov', require: false, group: :test\n  gem 'byebug'\n  gem 'webmock'\n  gem 'turbolinks'\nend\n\ngroup :test do\n  gem 'pry-rails'\n  gem 'pry-byebug'\n  gem \"generator_spec\"\n  gem \"rspec-retry\" # repeating flaky tests\n  gem \"rspec-wait\", \"~> 0.0.9\"\nend\n"
  },
  {
    "path": "ci/artifacts/.keep",
    "content": ""
  },
  {
    "path": "ci/docker-compose.ci.yml",
    "content": "version: '3'\nservices:\n\n  test_5_2_ruby_2_6:\n    build:\n      context: ../\n      dockerfile: ./ci/Dockerfile.test_5_2_ruby_2_6\n    environment:\n      RAILS_ENV: test\n    volumes:\n      - \"../ci/artifacts:/app/ci/artifacts\"\n    links:\n      - \"postgres_test_5_2_ruby_2_6:postgres_test\"\n    command: sh -c \"bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock\"\n    user: ${CURRENT_UID}\n\n  test_6_0_ruby_2_6:\n    build:\n      context: ../\n      dockerfile: ./ci/Dockerfile.test_6_0_ruby_2_6\n    environment:\n      RAILS_ENV: test\n    volumes:\n      - \"../ci/artifacts:/app/ci/artifacts\"\n    links:\n      - \"postgres_test_6_0_ruby_2_6:postgres_test\"\n    command: sh -c \"bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock\"\n    user: ${CURRENT_UID}\n\n  test_6_1_ruby_2_7:\n    build:\n      context: ../\n      dockerfile: ./ci/Dockerfile.test_6_1_ruby_2_7\n    environment:\n      RAILS_ENV: test\n    volumes:\n      - \"../ci/artifacts:/app/ci/artifacts\"\n    links:\n      - \"postgres_test_6_1_ruby_2_7:postgres_test\"\n    command: sh -c \"bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock\"\n    user: ${CURRENT_UID}\n\n  test_6_1_ruby_3_0:\n    build:\n      context: ../\n      dockerfile: ./ci/Dockerfile.test_6_1_ruby_3_0\n    environment:\n      RAILS_ENV: test\n    volumes:\n      - \"../ci/artifacts:/app/ci/artifacts\"\n    links:\n      - \"postgres_test_6_1_ruby_3_0:postgres_test\"\n    command: sh -c \"bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock\"\n    user: ${CURRENT_UID}\n\n  test_7_0_ruby_3_0:\n    build:\n      context: ../\n      dockerfile: ./ci/Dockerfile.test_7_0_ruby_3_0\n    environment:\n      RAILS_ENV: test\n    volumes:\n      - \"../ci/artifacts:/app/ci/artifacts\"\n    links:\n      - \"postgres_test_7_0_ruby_3_0:postgres_test\"\n    command: sh -c \"bundle exec rake db:drop && bundle exec rake db:create && bundle exec rake db:migrate && bundle exec rspec spec/test/core && cp Gemfile.lock ./ci/artifacts/Gemfile.lock\"\n    user: ${CURRENT_UID}\n\n  postgres_test_base: &postgres_test_base\n    image: postgres\n    expose:\n      - 5432\n    environment:\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: postgres\n      POSTGRES_DB: test\n\n  postgres_test_7_0_ruby_3_0:\n    <<: *postgres_test_base\n\n  postgres_test_6_1_ruby_3_0:\n    <<: *postgres_test_base\n\n  postgres_test_6_1_ruby_2_7:\n    <<: *postgres_test_base\n\n  postgres_test_6_0_ruby_2_6:\n    <<: *postgres_test_base\n\n  postgres_test_5_2_ruby_2_6:\n    <<: *postgres_test_base\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3'\nservices:\n\n  dummy:\n    build:\n      context: .\n      dockerfile: ./Dockerfile.dev\n    ports:\n      - \"3000:3000\"\n    environment:\n      RAILS_ENV: development\n    links:\n      - postgres_dummy\n    volumes:\n      - ./:/app\n      - gem-volume:/usr/local/bundle\n    command: \"bundle exec rails server -b 0.0.0.0\"\n    user: ${CURRENT_UID}\n    stdin_open: true\n    tty: true\n\n  webpack-watcher:\n    build:\n      context: .\n      dockerfile: ./Dockerfile.dev\n    environment:\n      RAILS_ENV: development\n    volumes:\n      - ./:/app\n      - gem-volume:/usr/local/bundle\n    command: \"sh -c 'cd spec/dummy && ./bin/webpack --watch'\"\n    user: ${CURRENT_UID}\n\n  test:\n    build:\n      context: .\n      dockerfile: ./Dockerfile.test\n    environment:\n      RAILS_ENV: test\n    links:\n      - postgres_test\n    ports:\n      - \"33123:33123\"\n    volumes:\n      - ./:/app\n      - gem-volume:/usr/local/bundle\n    command: \"bundle exec rspec spec/test\"\n    user: ${CURRENT_UID}\n\n\n\n  postgres_dummy:\n    image: postgres\n    expose:\n      - 5432\n    environment:\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: postgres\n      POSTGRES_DB: dummy\n    volumes:\n      - dummy-data-volume:/var/lib/postgresql/data\n\n  postgres_test_base: &postgres_test_base\n    image: postgres\n    expose:\n      - 5432\n    environment:\n      POSTGRES_USER: postgres\n      POSTGRES_PASSWORD: postgres\n      POSTGRES_DB: test\n\n  postgres_test:\n    <<: *postgres_test_base\n\nvolumes:\n  test-data-volume:\n  dummy-data-volume:\n  gem-volume:\n"
  },
  {
    "path": "docs/README.md",
    "content": "---\ndescription: >-\n  Matestack Ui Core - Boost your productivity & easily create component based\n  web UIs in pure Ruby.\n---\n\n# Welcome\n\n{% hint style=\"info\" %}\nVersion 3.0.0 was released on the xth of February 2022. Click here for more [details](migrate-from-2.x-to-3.0.md)\n\n**Most important changes:**\n\n* Split `matestack-ui-core` into `matestack-ui-core` and `matestack-ui-vuejs`\n* Rails 7 support\n* Vue 3 support in `matestack-ui-vuejs`\n\n****\n\n**If you want to see the docs for Version 2.1, click** [**here**](https://docs.matestack.io/matestack-ui-core/v/2.1/)**:**\n{% endhint %}\n\n## **About**\n\n`matestack-ui-core` enables you to craft maintainable, **component based** web UIs in **pure Ruby**, skipping ERB and HTML. UI code becomes a native and fun part of your Rails app. It can progressively replace the classic Rails-View-Layer. You are able to use it alongside your Rails views.\n\n## Compatibility\n\n`matestack-ui-core` is automatically tested against:\n\n* Rails 7.0.1 + Ruby 3.0.0\n* Rails 6.1.1 + Ruby 3.0.0\n* Rails 6.1.1 + Ruby 2.7.2\n* Rails 6.0.3.4 + Ruby 2.6.6\n* Rails 5.2.4.4 + Ruby 2.6.6\n\n{% hint style=\"danger\" %}\nRails versions below 5.2 are not officially supported.\n{% endhint %}\n\n## Getting Started\n\nStart right away and install `matestack-ui-core` on top of your Rails app, or read something about the features below.\n\n{% content-ref url=\"getting-started/installation-update.md\" %}\n[installation-update.md](getting-started/installation-update.md)\n{% endcontent-ref %}\n\n## Feature walk-through\n\n### 1. Create UI components in pure Ruby\n\nCraft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.\n\n**Implement UI components in pure Ruby**\n\nCreate Ruby classes within your Rails project and call Matestack's core components through a Ruby DSL in order to craft your UIs. The Ruby method \"div\" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. \"title\") or require them (e.g. \"body\").\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      div class: \"card-body\" do\n        h5 context.title if context.title.present?\n        paragraph context.body, class: \"card-text\"\n      end\n    end\n  end\n\nend\n```\n\n**Use your Ruby UI components on your existing Rails views**\n\nComponents can be then called on Rails views (not only! see below), enabling you to create a reusable card components, abstracting UI complexity in your own components.\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::Card.call(title: \"hello\", body: \"world\") %>\n<!-- some other erb markup -->\n```\n\n**Use Ruby methods as partials**\n\nSplit your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation. Using this approach helps you to create a clean, readable and maintainable codebase.\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n  optional :footer\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      card_content\n      card_footer if context.footer.present?\n    end\n  end\n\n  def card_content\n    div class: \"card-body\" do\n      h5 context.title if context.title.present?\n      paragraph context.body, class: \"card-body\"\n    end\n  end\n\n  def card_footer\n    div class: \"card-footer text-muted\" do\n      plain footer\n    end\n  end\n\nend\n```\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::Card.call(title: \"hello\", body: \"world\", footer: \"foo\") %>\n<!-- some other erb markup -->\n```\n\n**Use class inheritance**\n\nBecause it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation. Class inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.\n\n`app/matestack/components/blue_card.rb`\n\n```ruby\nclass Components::BlueCard < Components::Card\n\n  def response\n    div class: \"card shadow-sm border-0 bg-primary text-white\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      card_content #defined in parent class\n      card_footer if context.footer.present? #defined in parent class\n    end\n  end\n\nend\n```\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::BlueCard.call(title: \"hello\", body: \"world\") %>\n<!-- some other erb markup -->\n```\n\n**Use components within components**\n\nJust like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components. You decide when using a Ruby method partial should be replaced by another self contained UI component!\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      # calling the CardBody component rather than using Ruby method partials\n      Components::CardBody.call(title: context.title, body: context.body)\n    end\n  end\n\nend\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\nclass Components::CardBody < Matestack::Ui::Component\n\n  required :body\n  optional :title\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      h5 context.title if context.title.present?\n      paragraph context.body, class: \"card-body\"\n    end\n  end\n\nend\n```\n\n**Yield components into components**\n\nSometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components! Using this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      Components::CardBody.call() do\n        # yielding a block into the card_body component\n        h5 context.title if context.title.present?\n        paragraph context.body, class: \"card-body\"\n      end\n    end\n  end\n\nend\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\nclass Components::CardBody < Matestack::Ui::Component\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      yield if block_given?\n    end\n  end\n\nend\n```\n\n**Use named slots for advanced content injection**\n\nIf you need to inject multiple blocks into your UI component, you can use \"slots\"! Slots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      Components::CardBody.call(slots: {\n        heading: method(:heading_slot),\n        body: method(:body_slot)\n      })\n    end\n  end\n\n  def heading_slot\n    h5 context.title if context.title.present?      \n  end\n\n  def body_slot\n    paragraph context.body, class: \"card-body\"\n  end\n\nend\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\nclass Components::CardBody < Matestack::Ui::Component\n\n  required :slots\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      div class: \"heading-section\" do\n        slot :heading\n      end\n      div class: \"body-section\" do\n        slot :body\n      end\n    end\n  end\n\nend\n```\n\n### 2. Substitute Rails Views with Matestack Pages\n\nUntil here we used Matestack components on Rails views. If desired you can go one step further and use Matestack components on something called a Matestack Page:\n\nA Matestack page can be compared to a Rails view and might be yielded within a layout provided by an associated Matestack layout class (see below). The page itself uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.\n\n{% code title=\"app/matestack/pages/some_page.rb\" %}\n```ruby\nclass Pages::SomePage < Matestack::Ui::Page\n\n  def response\n    div class: \"container\" do\n      span id: \"hello\" do\n        plain \"hello world!\"\n      end\n      Components::Card.call(title: \"foo\", body: \"bar\")\n    end\n  end\n\nend\n```\n{% endcode %}\n\nPages are used as Rails view substitutes and therefore called in a Rails controller action:\n\n{% code title=\"app/controllers/some_controller.rb\" %}\n```ruby\nclass SomeController < ApplicationController\n\n  include Matestack::Ui::Core::Helper\n\n  def overview\n    render Pages::SomePage\n  end\n\nend\n```\n{% endcode %}\n\nThe page response - in this case - will be yielded into the Rails layout if not specified differently.\n\n### 3. Wrap Matestack Pages in Matestack Layouts\n\nJust like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack page. The layout uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.\n\n{% code title=\"app/matestack/some_app/some_layout.rb\" %}\n```ruby\nclass SomeApp::SomeLayout < Matestack::Ui::Layout\n\n  def response\n    h1 \"Some App\"\n    main do\n      yield\n    end\n  end\n\nend\n```\n{% endcode %}\n\nIn this basic example the layout is using the methods `h1` and `main` in order to create the markup as well as a `yield` in order to yield a page on a specific position.\n\n{% hint style=\"info\" %}\nA Matestack layout itself will be yielded into the Rails layout, unless the Rails layout is disabled in the controller via:`layout false`\n{% endhint %}\n\nUsually a layout implies a specific context of your application. Multiple pages are then scoped within that context, which could lead to a file structure like:\n\n```bash\napp/matestack/\n|\n└───some_app/\n│   │   some_layout.rb\n│   └───pages/\n│   │   │   page1.rb\n│   │   │   page2.rb\n│   │   │   page3.rb\n```\n\nand then used in a controller like this:\n\n{% code title=\"app/controllers/some_controller.rb\" %}\n```ruby\nclass SomeController < ApplicationController\n\n  include Matestack::Ui::Core::Helper\n\n  matestack_layout SomeApp::SomeLayout\n\n  def page_1\n    render SomeApp::Pages::Page1\n  end\n\n  def page_2\n    render SomeApp::Pages::Page2\n  end\n\n  def page_3\n    render SomeApp::Pages::Page3, matestack_layout: false # skip app layout on this page\n  end\n\nend\n```\n{% endcode %}\n"
  },
  {
    "path": "docs/SUMMARY.md",
    "content": "# Table of contents\n\n* [Welcome](README.md)\n* [Migrating from 2.x to 3.0](migrate-from-2.x-to-3.0.md)\n\n## Getting started\n\n* [Installation & Update](getting-started/installation-update.md)\n* [Hello World](getting-started/hello-world.md)\n\n## HTML Rendering\n\n* [Basic Rendering Mechanism](html-rendering/html-rendering.md)\n* [Integrating Action View Helpers](html-rendering/integrating-action-view-helpers.md)\n* [Integrating Rails Views or Partials](html-rendering/reusing-views-or-partials.md)\n\n## Components\n\n* [API](components/api.md)\n* [Usage on Rails Views](components/usage-on-rails-views.md)\n* [Usage on Matestack Pages](components/usage-on-matestack-pages.md)\n* [Usage on Matestack Layouts](components/usage-on-matestack-layouts.md)\n* [Usage in Isolation](components/usage-in-isolation.md)\n* [Registry](components/registry.md)\n\n## Pages\n\n* [API](pages/api.md)\n* [Rails Controller Integration](pages/rails-controller-integration.md)\n\n## Layouts\n\n* [API](layouts/api.md)\n* [Rails Controller Integration](layouts/rails-controller-integration.md)\n"
  },
  {
    "path": "docs/components/api.md",
    "content": "# API\n\n## Response\n\nUse the `response` method to define the UI of the component by using Matestack's HTML rendering or calling components.\n\n```ruby\n  class SomeComponent < Matestack::Ui::Component\n\n    def response\n      div id: \"my-component\" do\n        plain \"hello world!\"\n      end\n      SomeOtherComponent.()\n    end\n\n  end\n```\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n      SomeComponent.()\n    end\n  end\n\nend\n```\n\n## Partials and helper methods\n\nUse partials to keep the code dry and indentation layers manageable!\n\n### Local partials on component level\n\nIn the component definition, see how this time from inside the response, the `my_partial` method below is called:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      my_partial \"foo from component\"\n    end\n  end\n\n  private # optionally mark your partials as private\n\n  def my_partial text\n    div class: \"nested\"\n      plain text\n    end\n  end\n\nend\n```\n\n### Partials defined in modules\n\nExtract code snippets to modules for an even better project structure. First, create a module:\n\n```ruby\nmodule MySharedPartials\n\n  def my_partial text\n    div class: \"nested\"\n      plain text\n    end\n  end\n\nend\n```\n\nInclude the module in the component:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  include MySharedPartials\n\n  def response\n    div id: \"my-component\" do\n      my_partial \"foo from component\"\n    end\n  end\n\nend\n```\n\n### Helper methods\n\nNot only can instance methods be used as \"partials\" but as general helpers performing any kind of logic or data resolving:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      if is_admin?\n        latest_users.each do |user|\n          div do\n            plain user.name # ...\n          end\n        end\n      else\n        plain \"not authorized\"\n      end \n    end\n  end\n\n  private # optionally mark your helper methods as private\n\n  def is_admin?\n    true # some crazy Ruby logic!\n  end\n\n  def latest_users\n    User.last(10) # calling ActiveRecord models for example\n  end\n\nend\n```\n\n## Render?\n\nUse the `render?` method to conditionally render the component based on custom rules:\n\n```ruby\nclass AdminComponent < Matestack::Ui::Component\n  required :user\n\n  def render?\n    context.user.admin?\n  end\n\n  def response\n    div id: \"admin-component\" do\n      plain \"This component should only get rendered for admins\"\n    end\n  end\nend\n```\n\nThis is particularly useful to avoid plastering your views with conditional statements like `if` and `unless`.\n\nInstead of:\n\n```ruby\n  <% if current_user.admin? %>\n    <%= Components::AdminComponent.(user: current_user) %>\n  <% end %>\n```\n\nYou can just use:\n\n```ruby\n  <%= Components::AdminComponent.(user: current_user) %>\n```\n\n## Prepare\n\nUse a prepare method to resolve instance variables before rendering a component if required.\n\n```ruby\n  class SomeComponent < Matestack::Ui::Component\n\n    def prepare\n      @some_data = \"some data\"\n    end\n\n    def response\n      div id: \"my-component\" do\n        plain @some_data\n      end\n    end\n\n  end\n```\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n      SomeComponent.()\n    end\n  end\n\nend\n```\n\nThis is the HTML which gets created:\n\n```markup\n<div id=\"div-on-page\">\n  <div id=\"my-component\">\n    some data\n  </div>\n</div>\n```\n\n## Params access\n\nA component can access request information, e.g. url query params, by calling the `params` method:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      plain params[:foo]\n    end\n  end\n\nend\n```\n\nOn the example page, reference the component as usual.\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n     SomeComponent.()\n    end\n  end\n\nend\n```\n\nNow, visiting the respective route to the page, e.g. via `/xyz?foo=bar`, the component reads the `[:foo]` from the params and displays it like so:\n\n```markup\n<div id=\"div-on-page\">\n  <div id=\"my-component\">\n    bar\n  </div>\n</div>\n```\n\n## Passing data to components\n\nYou often need to pass data into your component to make them reusable. You have multiple possibilities to do that:\n\n### General options access\n\nIf you pass in a hash to a component...\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n      SomeComponent.(foo: \"bar\")\n    end\n  end\n\nend\n```\n\n...this hash is accessible via options in the component:\n\n```ruby\nclass Some::Component < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      plain options[:foo]\n    end\n  end\n\nend\n```\n\n### Optional and required options\n\nMatestack components give you the possibility to define an explicit API for your component describing required and optional options for a component. Using this approach, it's way easier to understand what data can be processed by your component.\n\n{% hint style=\"info\" %}\n`required` and `optional` options will be deleted from the `options` hash and are only available via the `context` object.\n{% endhint %}\n\n#### Required options\n\nRequired options are required for your component to work, like the name suggests. If at least one required option is missing, an Exception is raised.\n\nDeclare your required options by calling `required` as follows:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  required :some_property, :some_other\n\nend\n```\n\nYou then can use these options simply by calling the provided OpenStruct object `context`, which includes the injected options with their name:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  required :some_property, :some_other\n\n  def response\n    # display some_property plain inside a div and some_other property inside a paragraph beneath it\n    div do\n      plain context.some_property\n    end\n    paragraph text: context.some_other\n  end\n\nend\n```\n\n#### Optional options\n\nTo define optional options you can use the same syntax as `required`. Just use `optional` instead of `required`. Optional options are optional and not validated for presence like required options.\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  optional :optional_property, :other_optional_property # optional properties could be empty\n\n  def response\n    div do\n      plain context.optional_property\n    end\n    paragraph context.other_optional_property\n  end\n\nend\n```\n\n#### Passing more complex data structures to components\n\nYou can pass any object you like and use it in the component with the helper.\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  required :some_option,\n  optional :some_other\n\n  def response\n    div do\n      plain context.some_option\n    end\n    if context.some_other.present?\n      paragraph context.some_other[:option]\n    end\n  end\n\nend\n```\n\nUse it in the example page and pass in one option as a hash\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def prepare\n    @hello = \"hello!\"\n  end\n\n  def response\n    div id: \"div-on-page\" do\n      SomeComponent.(some_option: @hello, some_other: { option: \"world!\" })\n    end\n  end\n\nend\n```\n\n#### Alias properties\n\nIt's not possible to overwrite core methods of the OpenStruct object `context`\n\n```markup\n[:!, :!=, :!~, :<=>, :==, :===, :=~, :[], :[]=, :__id__, :__send__, :acts_like?, :as_json, :blank?, :byebug, :class, :class_eval, :clone, :dclone, :debugger, :deep_dup, :define_singleton_method, :delete_field, :dig, :display, :dup, :duplicable?, :each_pair, :enum_for, :eql?, :equal?, :extend, :freeze, :frozen?, :gem, :hash, :html_safe?, :in?, :inspect, :instance_eval, :instance_exec, :instance_of?, :instance_values, :instance_variable_defined?, :instance_variable_get, :instance_variable_names, :instance_variable_set, :instance_variables, :is_a?, :itself, :kind_of?, :load_dependency, :marshal_dump, :marshal_load, :method, :method_missing, :methods, :nil?, :object_id, :presence, :presence_in, :present?, :pretty_inspect, :pretty_print, :pretty_print_cycle, :pretty_print_inspect, :pretty_print_instance_variables, :private_methods, :protected_methods, :public_method, :public_methods, :public_send, :remote_byebug, :remove_instance_variable, :require_dependency, :require_or_load, :respond_to?, :send, :singleton_class, :singleton_method, :singleton_methods, :table, :table!, :taint, :tainted?, :tap, :then, :to_enum, :to_h, :to_json, :to_param, :to_query, :to_s, :to_yaml, :trust, :try, :try!, :unloadable, :untaint, :untrust, :untrusted?, :with_options, :yield_self]\n```\n\nIf you somehow want to inject options with a key matching a core method of the OpenStruct object, simply provide an alias name with the `as:` option. You can then use the alias accordingly. A popular example would be the option called `class`\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  required :foo, :bar, class: { as: :my_class }\n\n  def response\n    div class: context.my_class do\n      plain \"#{context.foo} - #{context.bar}\"\n    end\n  end\n\nend\n```\n\n### Text argument\n\nSometimes you just want to pass in a simple (text) argument rather than a hash with multiple keys:\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n      # simply pass in a string here\n      SomeComponent.(\"foo from page\")\n    end\n  end\n\nend\n```\n\nA component can access this text argument in various ways:\n\n```ruby\nclass Some::Component < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      plain self.text # because such an argument is almost always a string\n      # or\n      plain context.text # for compatibility with older releases\n    end\n  end\n\nend\n```\n\nThis approach can be combined with injecting Hashes to components:\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n      # simply pass in a string here\n      Some::Component.(\"foo from page\", { foo: \"bar\" })\n    end\n  end\n\nend\n```\n\n```ruby\nclass Some::Component < Matestack::Ui::Component\n\n  optional :foo\n\n  def response\n    div id: \"my-component\" do\n      plain self.text # because such an argument is almost always a string\n      # or\n      plain context.text # for compatibility with older releases\n      plain context.foo\n    end\n  end\n\nend\n```\n\n## Yielding inside components\n\nComponents can yield a block with access to scope, where a block is defined.\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      yield\n    end\n  end\n\nend\n```\n\nPass a block to a component on the page as shown below:\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def prepare\n    @foo = \"foo from page\"\n  end\n\n  def response\n    div id: \"div-on-page\" do\n      SomeComponent.() do\n        plain @foo\n      end\n    end\n  end\n\nend\n```\n\nNot a fancy example, but this is the result:\n\n```markup\n<div id=\"div-on-page\">\n  <div id=\"my-component\">\n    foo from page\n  </div>\n</div>\n```\n\n## Slots\n\nSlots in Matestack allow us to inject whole UI snippets into the component. It's a more specific yielding mechanism as you will yield multiple \"named blocks\" into the component. Each of these blocks can be referenced and positioned independently in the component,\n\n### Slots on the page instance scope\n\nDefine the slots within the component file as shown below. Please make sure to inject slots within a hash `slots: { ... }` into the component.\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  def prepare\n    @foo = \"foo from component\"\n  end\n\n  def response\n    div id: \"my-component\" do\n      slot :my_first_slot\n      br\n      slot :my_second_slot\n    end\n  end\n\nend\n```\n\nSlots have access to the scope of the class, where they are defined. In this case `@foo`\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def prepare\n    @foo = \"foo from page\"\n  end\n\n  def response\n    div do\n      some_component slots: {\n        my_first_slot: method(:my_simple_slot),\n        my_second_slot: method(:my_second_simple_slot)\n      }\n    end\n  end\n\n  def my_simple_slot\n    span id: \"my_simple_slot\" do\n      plain \"some content\"\n    end\n  end\n\n  def my_second_simple_slot\n    span id: \"my_simple_slot\" do\n      plain @foo\n    end\n  end\n\nend\n```\n\nThis gets rendered into HTML as shown below. Notice that the `@foo` from the component configuration got overwritten by the page's local `@foo`!\n\n```markup\n<div>\n  <div id=\"my-component\">\n    <span id=\"my_simple_slot\">\n      some content\n    </span>\n    <br/>\n    <span id=\"my_simple_slot\">\n      foo from page\n    </span>\n  </div>\n</div>\n```\n\n### Using slots of components within components\n\nTo use _component instance scope slots_, first define slots within a static component:\n\n```ruby\nclass Other::Component < Matestack::Ui::Component\n\n  def prepare\n    @foo = \"foo from other component\"\n  end\n\n  def response\n    div id: \"my-other-component\" do\n      slot :my_slot_from_component\n      br\n      slot :my_slot_from_page\n      br\n      plain @foo\n    end\n  end\n\nend\n```\n\nand also in some component:\n\n```ruby\nclass Some::Component < Matestack::Ui::Component\n\n  def prepare\n    @foo = \"foo from component\"\n  end\n\n  def response\n    div id: \"my-component\" do\n      other_component slots: {\n        my_slot_from_component: method(:my_slot_from_component),\n        my_slot_from_page: slots[:my_slot_from_page]\n      }\n    end\n  end\n\n  def my_slot_from_component\n    span id: \"my-slot-from-component\" do\n      plain @foo\n    end\n  end\n\nend\n```\n\nThen, put both components (note that some component uses other component so that's how they're both in here) to use on the example page:\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def prepare\n    @foo = \"foo from page\"\n  end\n\n  def response\n    div id: \"page-div\" do\n      some_component slots: { my_slot_from_page: method(:my_slot_from_page) }\n    end\n  end\n\n  def my_slot_from_page\n    span id: \"my-slot-from-page\" do\n      plain @foo\n    end\n  end\n\nend\n```\n\nThis gets rendered into the HTML below:\n\n```markup\n<div id=\"page-div\">\n  <div id=\"my-component\">\n    <div id=\"my-other-component\">\n      <span id=\"my-slot-from-component\">\n        foo from component\n      </span>\n      <br/>\n      <span id=\"my-slot-from-page\">\n        foo from page\n      </span>\n      <br/>\n      foo from other component\n    </div>\n  </div>\n</div>\n```\n\n### Calling slots with params\n\nSometimes it's necessary to call a slot with params:\n\n```ruby\nclass SomeComponent < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      User.last(10).each do |user|\n        slot(:user_card, user)\n      end\n    end\n  end\n\nend\n```\n\n```ruby\nclass ExamplePage < Matestack::Ui::Page\n\n  def response\n    div do\n      some_component slots: {\n        user_card: method(:user_card)\n      }\n    end\n  end\n\n  def user_card user\n    div class: \"card\" do\n      plain user.name\n    end\n  end\n\nend\n```\n"
  },
  {
    "path": "docs/components/registry.md",
    "content": "# Registry\n\nBy default, components can be called directly like `Components::Card.call(title: \"foo\", body: \"bar\")` which will return the desired HTML string.\n\nIf desired, you can create alias methods in order to avoid the class call syntax:\n\n{% code title=\"app/matestack/components/registry.rb\" %}\n```ruby\nmodule Components::Registry\n\n  def card(text=nil, options=nil, &block)\n    Components::Card.call(text, options, &block)\n  end\n\n  #...\n\nend\n```\n{% endcode %}\n\nwhich then allows you to call the card component like `card(title: \"foo\", body: \"bar\")` if the above shown module is included properly.\n\nAs this is just a plain Ruby module, you need to include it in all contexts you want to use the alias method. It might be a good idea to create your own `ApplicationPage`, `ApplicationComponent` and `ApplicationLayout` as base classes for your pages, components ans layouts. In there, you include your component registry module(s) only once and have access to the alias methods in all child classes:\n\n{% code title=\"app/matestack/application_page.rb\" %}\n```ruby\nclass ApplicationPage < Matestack::Ui::Page\n\n  include Components::Registry\n\nend\n```\n{% endcode %}\n\n{% code title=\"app/matestack/application_component.rb\" %}\n```ruby\nclass ApplicationComponent < Matestack::Ui::Component\n\n  include Components::Registry\n\nend\n```\n{% endcode %}\n\n{% code title=\"app/matestack/application_layout.rb\" %}\n```ruby\nclass ApplicationLayout < Matestack::Ui::Layout\n\n  include Components::Registry\n\nend\n```\n{% endcode %}\n"
  },
  {
    "path": "docs/components/usage-in-isolation.md",
    "content": "# Usage in Isolation\n\n"
  },
  {
    "path": "docs/components/usage-on-matestack-layouts.md",
    "content": "# Usage on Matestack Layouts\n\n"
  },
  {
    "path": "docs/components/usage-on-matestack-pages.md",
    "content": "# Usage on Matestack Pages\n\n"
  },
  {
    "path": "docs/components/usage-on-rails-views.md",
    "content": "# Components on Rails views\n\nIf you already have plenty of Rails views \\(ERB, Haml or Slim\\) and want to start creating small UI components in pure Ruby, you are able to use components on these existing views.\n\n{% code title=\"app/matestack/components/products/teaser.rb\" %}\n```ruby\nclass Components::Products::Teaser < Matestack::Ui::Component\n\n  requires :product\n\n  def response\n    a path: product_path(context.product), class: 'product-teaser' do\n      div do\n        h2 context.product.name\n        paragraph conext.product.description\n        b context.product.price\n      end\n    end\n  end\n\nend\n```\n{% endcode %}\n\nThe class is then called on your Rails view, in this case an ERB view:\n\n```markup\n<%= @products.each do |product| %>\n  <%= Components::Products::Teaser.(product: product) %>\n<% end %>\n```\n\n{% hint style=\"info\" %}\nThis approach is suitable for existing apps and a good idea to migrate to Matestack step by step. If you start with a blank Rails app, we recommend to go full Matestack right away**!**\n{% endhint %}\n\n"
  },
  {
    "path": "docs/getting-started/hello-world.md",
    "content": "# Hello World\n\nWIP!\n"
  },
  {
    "path": "docs/getting-started/installation-update.md",
    "content": "# Installation & Update\n\n## Installation\n\nAdd 'matestack-ui-core' to your Gemfile\n\n```ruby\ngem 'matestack-ui-core'\n```\n\nand run\n\n```\n$ bundle install\n```\n\n### Matestack folder\n\nCreate a folder called `matestack` in your app directory. All your Matestack layouts, pages and components will be defined there.\n\n```\n$ mkdir app/matestack\n```\n\n### Controller setup\n\nAdd the Matestack helper to your controllers. If you want to make the helpers available in all controllers, add it to your `ApplicationController` :\n\n`app/controllers/application_controller.rb`\n\n```ruby\nclass ApplicationController < ActionController::Base\n  include Matestack::Ui::Core::Helper\n  #...\nend\n```\n\nNow, you are able to create UI components in pure Ruby and use them in your Rails views. Additionally you can substitute Rails views and layouts with Matestack pages and layouts.\n\n## Update\n\n### Ruby Gem\n\nDepending on the entry in your Gemfile, you might need to adjust the allowed version ranges in order to update the Gem. After checked and adjusted the version ranges, run:\n\n```bash\nbundle update matestack-ui-core\n```\n\nand then check the installed version:\n\n```bash\nbundle info matestack-ui-core\n```\n"
  },
  {
    "path": "docs/html-rendering/html-rendering.md",
    "content": "# Basic Rendering Mechanism\n\nMatestack’s rendering mechanism takes care of converting Ruby into HTML:\n\n```ruby\ndiv class: \"card shadow-sm border-0 bg-light\", foo: \"bar\" do\n  img path: \"...\", class: \"w-100\"\n  div class: \"card-body\" do\n    h5 \"foo\", class: \"card-title\"\n    paragraph \"bar\", class: \"card-text\"\n  end\nend\n```\n\nwill be rendered to:\n\n```markup\n<div class=\"card shadow-sm border-0 bg-light\" foo=\"bar\">\n  <img src=\"...\" class=\"w-100\">\n  <div class=\"card-body\">\n    <h5 class=\"card-title\">foo</h5>\n    <p class=\"card-text\">bar</p>\n  </div>\n</div>\n```\n\nThat's working because `matestack-ui-core` defines all kind of Ruby methods targeting Rails ActionView `tag` helper, rendering the desired HTML tag and content as a String. This enables you to build a well known DOM structure while writing and utilizing pure Ruby!\n\nAs you can see, you can add CSS classes and ids as well as custom tag attributes. This way `matestack-ui-core` can be combined with various [CSS frameworks](broken-reference), your custom styles and all kinds of reactivity systems.&#x20;\n\nIt’s already fun to write pure Ruby instead of HTML or any other templating engine syntax but this approach is really paying of, when you start using Ruby's language features in order to split your UI implementation into various small chunks, organized through included modules, class inheritance or simply multiple Ruby methods within one class!\n\n{% hint style=\"info\" %}\nThe above shown Ruby code lives in Ruby classes inheriting from `Matestack::Ui::Component`, `Matestack::Ui::Page` or Matestack::Ui::Layout - they are described in the following sections of these docs and might look like this:\n\n```ruby\nclass Components::HelloWorld < Matestack::Ui::Component\n\n  def response\n    div class: \"my-class\" do\n      plain \"hello world!\"\n    end\n  end\n\nend\n```\n{% endhint %}\n\n## Supported HTML Tags\n\n### Void Tags\n\nThese tags by definition do not allow an inner HTML and therefore do not take an block but all kinds of tag attributes, e.g.:\n\n```ruby\n# ...\nhr class: \"some-class\"\n# ...\n```\n\n* area\n* base\n* br\n* col\n* hr\n* img | _you can use `src` or `path` in order to reference the url to the image_\n* input\n* link\n* meta\n* param\n* command\n* keygen\n* source\n\n### Tags\n\nThe following tags take content via a block OR first (non-hash) argument and all kind of tag attributes, e.g.:\n\n```ruby\n# define inner HTML via a block\nspan class: \"some-class\" do\n  plain \"foo\"\nend\n# OR: define inner HTML via a simple first non-hash argument \nspan \"foo\", class: \"some-class\"\n# ...\n```\n\n* a | _you can use `href` or `path` in order to reference the url of the link_\n* abbr\n* acronym\n* address\n* applet\n* article\n* aside\n* audio\n* b\n* base\n* basefont\n* bdi\n* bdo\n* big\n* blockquote\n* body\n* button\n* canvas\n* caption\n* center\n* cite\n* code\n* col\n* colgroup\n* data\n* datalist\n* dd\n* del\n* details\n* dfn\n* dialog\n* dir\n* div\n* dl\n* dt\n* em\n* embed\n* fieldset\n* figcaption\n* figure\n* font\n* footer\n* form\n* frame\n* frameset\n* h1 | _also available via `heading size: 1`_\n* h2 | _also available via `heading size: 2`_\n* h3 | _also available via `heading size: 3`_\n* h4 | _also available via `heading size: 4`_\n* h5 | _also available via `heading size: 5`_\n* h6 | _also available via `heading size: 6`_\n* head\n* header\n* html\n* i\n* iframe\n* ins\n* kbd\n* label\n* legend\n* li\n* main\n* map\n* mark\n* meter\n* nav\n* noframes\n* noscript\n* object\n* ol\n* optgroup\n* option\n* output\n* paragraph | _p is not working as it's an alias for puts in Ruby core_\n* picture\n* pre\n* progress\n* q\n* rp\n* rt\n* ruby\n* s\n* samp\n* script\n* section\n* select\n* small\n* span\n* strike\n* strong\n* style\n* sub\n* summary\n* sup\n* svg\n* table\n* tbody\n* td\n* template\n* textarea\n* tfoot\n* th\n* thead\n* time\n* title\n* tr\n* track\n* tt\n* u\n* ul\n* var\n* video\n* wbr\n\n## Text Rendering\n\nIn order to render plain text, do:\n\n```ruby\n#...\nplain \"hello world!\"\n# \"hello world!\" alone would not be rendered!\n#...\n```\n\n## Tag/Data Attributes\n\nMatestack's rendering mechanism automatically renders all given options as tag attributes. For convenience, data attributes can be passend in within a data hash:\n\n```ruby\ndiv class: \"foo\", id: \"bar\", hello: \"world\", data: { foo: \"bar\" } do\n  #...\nend\n```\n\n```markup\n<div class=\"foo\" id=\"bar\" hello=\"world\" data-foo=\"bar\">\n  <!-- ... -->\n</div>\n```\n\n## Custom HTML Tags\n\nIf you want to use HTML tags which are not supported by Matestack's rendering mechanism by default, you can call ActionView's `tag` helper manually:\n\n[https://apidock.com/rails/ActionView/Helpers/TagHelper/tag](https://apidock.com/rails/ActionView/Helpers/TagHelper/tag)\n\n```ruby\nplain tag.xyz(\"foo\")\n```\n\nwill render:\n\n```markup\n<xyz>foo</xyz>\n```\n"
  },
  {
    "path": "docs/html-rendering/integrating-action-view-helpers.md",
    "content": "# Integrating Action View Helpers\n\nUsing Rails view helpers ([https://api.rubyonrails.org/classes/ActionView/Helpers.html](https://api.rubyonrails.org/classes/ActionView/Helpers.html)) in components, pages and layouts is supported when using the approaches shown below;\n\n## Helpers without a block\n\nSimple Action View helpers working without a block, can easily be integrated in a Matestack class response by calling `plain`:\n\n```ruby\ndef response\n  plain t(\"my.locale\")\n  # ...\n  plain link_to \"Show\", post_path(@post)\n  # ...\n  plain my_own_view_helper_method\n  # ...\n  plain any_method_returning_a_string\nend\n```\n\n## Helpers yielding a block\n\nIf you want to use a helper like `form_for` you have to follow following approach:\n\n```ruby\ndef response\n  # ...\n  plain do # <-- add this\n    form_with url: \"/some_path\" do |f|\n      matestack_to_s do # <-- add this, which converst following block to a string\n        plain f.text_field :foo # <-- call plain here again\n        br\n        div class: \"some-input-wrapper\" do\n          plain f.text_field :bar\n        end\n        br\n        plain f.submit\n      end\n    end\n  end\n  # ...\n  plain do\n    link_to root_path do\n      matestack_to_s do\n        div class: \"some-link-wrapper\" do\n          plain \"foo from block\"\n        end\n      end\n    end\n  end\n  # ...\n  # Code below will not work!\n  plain link_to root_path do\n    matestack_to_s do\n      div class: \"some-link-wrapper\" do\n        plain \"foo from block\"\n      end\n    end\n  end\nend\n```\n\n{% hint style=\"info\" %}\nA component needs to be called in context of a controller (with included `Matestack::Ui::Core::Helper`), which is true when you're calling components from Rails views or on Matestack Pages/Layouts (which are themselves called by a controller normally).\n\nWhen calling a component in isolation (which is possible), the view helpers might not work properly, especially when (implicitly) requiring a request object!\n{% endhint %}\n\n{% hint style=\"info\" %}\nWe're currently working on an improved way to integrate ActionView Helpers which will enable removing the `plain` calls from your code.\n{% endhint %}\n"
  },
  {
    "path": "docs/html-rendering/reusing-views-or-partials.md",
    "content": "# Integrating Rails Views or Partials\n\nMatestack `rails_render` component offers the possibility to render a view or partial by passing its name and required params to it.\n\n## Components reusing partials\n\nImagine the partial `app/views/products/_teaser.html.erb` containing following content:\n\n```markup\n<%= link_to product_path(product), class: 'product-teaser' do %>\n  <div>\n    <h2><%= product.name %></h2>\n    <p><%= product.description %></p>\n    <b><%= product.price %></b>\n  </div>\n<% end %>\n```\n\n```ruby\nclass Components::Products::Trending < Matestack::Ui::Component\n\n  def prepare\n    @products = Product.where(trending: true)\n  end\n\n  def response\n    h1 'Trending products'\n    @products.each do |product|\n      rails_render partial: '/products/teaser', locals: { product: product }\n    end\n  end\n\nend\n```\n\nAs you see, we used the `rails_render` component here to render our products teaser partial. Given the string rails searches for a partial in `app/views/products/_teaser.html.erb`. As our product teaser partial uses a `product` we pass in a product as a `local`.\n\n`rails_render` works with ERB, Haml and Slim Templates, as long as you have installed and configured the desired templating engine correctly in your Rails app.\n\n## Components reusing views\n\nAs mentioned above the `rails_render` component can not only render partials but also views. Following Rails view can be reused within a Matestack component:\n\n`app/views/static/index.html.erb`\n\n```markup\n<main>\n  <%= render partial: 'products/teaser', collection: products, as: :product %>\n</main>\n\n<div>\n  <%= link_to 'All products', products_path %>\n</div>\n```\n\n```ruby\nclass Components::Products::Index < Matestack::Ui::Component\n\n  def prepare\n    @products = Product.where(trending: true)\n  end\n\n  def response\n    rails_render template: '/static/index', locals: { products: @products }\n  end\n\nend\n```\n"
  },
  {
    "path": "docs/layouts/api.md",
    "content": "# API\n\nA layout class defines a layout within its `response` method and is suppose to yield the content of a page.\n\n## Response\n\nUse the `response` method to define the UI of the app by using Matestack's HTML rendering and optionally calling components.\n\n```ruby\nclass SomeApp < Matestack::Ui::App\n\n  def response\n    nav do \n      a path: some_rails_path, text: \"Navigate!\"\n    end\n    main do\n      yield\n    end\n    footer do\n      div id: \"div-on-app\" do\n        SomeComponent.()\n      end\n    end\n  end\n\nend\n```\n\n## Partials and helper methods\n\nUse partials to keep the code dry and indentation layers manageable!\n\n### Local partials on page level\n\nIn the page definition, see how this time from inside the response, the `my_partial` method below is called:\n\n```ruby\nclass SomeApp < Matestack::Ui::App\n\n  def response\n    nav do \n      a path: some_rails_path, text: \"Navigate!\"\n    end\n    main do\n      yield\n    end\n    footer do\n      div id: \"div-on-app\" do\n        SomeComponent.()\n      end\n      my_partial \"foo from app\"\n    end\n  end\n\n  private # optionally mark your partials as private\n\n  def my_partial text\n    div class: \"nested\" do\n      plain text\n    end\n  end\n\nend\n```\n\n### Partials defined in modules\n\nExtract code snippets to modules for an even better project structure. First, create a module:\n\n```ruby\nmodule MySharedPartials\n\n  def my_partial text\n    div class: \"nested\" do\n      plain text\n    end\n  end\n\nend\n```\n\nInclude the module in the page:\n\n```ruby\nclass SomeApp < Matestack::Ui::App\n\n  include MySharedPartials\n\n  def response\n    nav do \n      a path: some_rails_path, text: \"Navigate!\"\n    end\n    main do\n      yield\n    end\n    footer do\n      div id: \"div-on-app\" do\n        SomeComponent.()\n      end\n      my_partial \"foo from app\"\n    end\n  end\n\nend\n```\n\n### Helper methods\n\nNot only can instance methods be used as \"partials\" but as general helpers performing any kind of logic or data resolving:\n\n```ruby\nclass SomeApp < Matestack::Ui::App\n\n  def response\n    nav do \n      a path: some_rails_path, text: \"Navigate!\"\n    end\n    main do\n      if is_admin?\n        yield\n      else\n        plain \"not authorized\"\n      end \n    end\n  end\n\n  private # optionally mark your helper methods as private\n\n  def is_admin?\n    true # some crazy Ruby logic!\n  end\n\nend\n```\n\n## Prepare\n\nUse a prepare method to resolve instance variables before rendering a page if required.\n\n```ruby\nclass SomeApp < Matestack::Ui::App\n\n  def prepare\n    @heading = \"Foo\"\n  end\n\n  def response\n    h1 @heading\n    nav do \n      a path: some_rails_path, text: \"Navigate!\"\n    end\n    main do\n      yield\n    end\n  end\n\nend\n```\n\n## Params access\n\nAn app can access request information, e.g. url query params, by calling the `params` method:\n\n```ruby\nclass SomeApp < Matestack::Ui::App\n\n  def response\n    nav do \n      a path: some_rails_path, text: \"Navigate!\"\n    end\n    main do\n      plain params[:foo] # \"bar\" \n      yield\n    end\n  end\n\nend\n```\n\nNow, visiting the respective route to the page, e.g. via `/xyz?foo=bar`, the page reads the `[:foo]` from the params and displays it.\n"
  },
  {
    "path": "docs/layouts/rails-controller-integration.md",
    "content": "# Rails Controller Integration\n\nJust like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack page. The layout uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.\n\n{% code title=\"app/matestack/some_app/some_layout.rb\" %}\n```ruby\nclass SomeApp::SomeLayout < Matestack::Ui::Layout\n\n  def response\n    h1 \"Some App\"\n    main do\n      yield\n    end\n  end\n\nend\n```\n{% endcode %}\n\nIn this basic example the layout is using the methods `h1` and `main` in order to create the markup as well as a `yield` in order to yield a page on a specific position.\n\n{% hint style=\"info\" %}\nA Matestack layout itself will be yielded into the Rails layout, unless the Rails layout is disabled in the controller via:`layout false`\n{% endhint %}\n\nUsually a layout implies a specific context of your application. Multiple pages are then scoped within that context, which could lead to a file structure like:\n\n```bash\napp/matestack/\n|\n└───some_app/\n│   │   some_layout.rb\n│   └───pages/\n│   │   │   page1.rb\n│   │   │   page2.rb\n│   │   │   page3.rb\n```\n\nand then used in a controller like this:\n\n\n\n### Feature walk-through\n\n#### 1. Create UI components in pure Ruby\n\nCraft your UI based on your components written in pure Ruby. Utilizing Ruby's amazing language features, you're able to create a cleaner and more maintainable UI implementation.\n\n**Implement UI components in pure Ruby**\n\nCreate Ruby classes within your Rails project and call Matestack's core components through a Ruby DSL in order to craft your UIs. The Ruby method \"div\" for example calls one of the static core components, responsible for rendering HTML tags. A component can take Strings, Integers Symbols, Arrays or Hashes (...) as optional properties (e.g. \"title\") or require them (e.g. \"body\").\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      div class: \"card-body\" do\n        h5 context.title if context.title.present?\n        paragraph context.body, class: \"card-text\"\n      end\n    end\n  end\n\nend\n```\n\n**Use your Ruby UI components on your existing Rails views**\n\nComponents can be then called on Rails views (not only! see below), enabling you to create a reusable card components, abstracting UI complexity in your own components.\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::Card.call(title: \"hello\", body: \"world\") %>\n<!-- some other erb markup -->\n```\n\n**Use Ruby methods as partials**\n\nSplit your UI implementation into multiple small chunks helping others (and yourself) to better understand your implementation. Using this approach helps you to create a clean, readable and maintainable codebase.\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n  optional :footer\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      card_content\n      card_footer if context.footer.present?\n    end\n  end\n\n  def card_content\n    div class: \"card-body\" do\n      h5 context.title if context.title.present?\n      paragraph context.body, class: \"card-body\"\n    end\n  end\n\n  def card_footer\n    div class: \"card-footer text-muted\" do\n      plain footer\n    end\n  end\n\nend\n```\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::Card.call(title: \"hello\", body: \"world\", footer: \"foo\") %>\n<!-- some other erb markup -->\n```\n\n**Use class inheritance**\n\nBecause it's just a Ruby class, you can use class inheritance in order to further improve the quality of your UI implementation. Class inheritance can be used to easily create variants of UI components but still reuse parts of the implementation.\n\n`app/matestack/components/blue_card.rb`\n\n```ruby\nclass Components::BlueCard < Components::Card\n\n  def response\n    div class: \"card shadow-sm border-0 bg-primary text-white\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      card_content #defined in parent class\n      card_footer if context.footer.present? #defined in parent class\n    end\n  end\n\nend\n```\n\n`app/views/your_view.html.erb`\n\n```erb\n<!-- some other erb markup -->\n<%= Components::BlueCard.call(title: \"hello\", body: \"world\") %>\n<!-- some other erb markup -->\n```\n\n**Use components within components**\n\nJust like you used matestack's core components on your own UI component, you can use your own UI components within other custom UI components. You decide when using a Ruby method partial should be replaced by another self contained UI component!\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      # calling the CardBody component rather than using Ruby method partials\n      Components::CardBody.call(title: context.title, body: context.body)\n    end\n  end\n\nend\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\nclass Components::CardBody < Matestack::Ui::Component\n\n  required :body\n  optional :title\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      h5 context.title if context.title.present?\n      paragraph context.body, class: \"card-body\"\n    end\n  end\n\nend\n```\n\n**Yield components into components**\n\nSometimes it's not enough to just pass simple data into a component. No worries! You can just yield a block into your components! Using this approach gives you more flexibility when using your UI components. Ofcourse yielding can be used alongside passing in simple params.\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      Components::CardBody.call() do\n        # yielding a block into the card_body component\n        h5 context.title if context.title.present?\n        paragraph context.body, class: \"card-body\"\n      end\n    end\n  end\n\nend\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\nclass Components::CardBody < Matestack::Ui::Component\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      yield if block_given?\n    end\n  end\n\nend\n```\n\n**Use named slots for advanced content injection**\n\nIf you need to inject multiple blocks into your UI component, you can use \"slots\"! Slots help you to build complex UI components with multiple named content placeholders for highest implementation flexibility!\n\n`app/matestack/components/card.rb`\n\n```ruby\nclass Components::Card < Matestack::Ui::Component\n\n  required :body\n  optional :title\n  optional :image\n\n  def response\n    div class: \"card shadow-sm border-0 bg-light\" do\n      img path: context.image, class: \"w-100\" if context.image.present?\n      Components::CardBody.call(slots: {\n        heading: method(:heading_slot),\n        body: method(:body_slot)\n      })\n    end\n  end\n\n  def heading_slot\n    h5 context.title if context.title.present?      \n  end\n\n  def body_slot\n    paragraph context.body, class: \"card-body\"\n  end\n\nend\n```\n\n`app/matestack/components/card_body.rb`\n\n```ruby\nclass Components::CardBody < Matestack::Ui::Component\n\n  required :slots\n\n  def response\n    # Just an example. Would make more sense, if this component had\n    # a more complex structure\n    div class: \"card-body\" do\n      div class: \"heading-section\" do\n        slot :heading\n      end\n      div class: \"body-section\" do\n        slot :body\n      end\n    end\n  end\n\nend\n```\n\n#### 2. Substitute Rails Views with Matestack Pages\n\nUntil here we used Matestack components on Rails views. If desired you can go one step further and use Matestack components on something called a Matestack Page:\n\nA Matestack page can be compared to a Rails view and might be yielded within a layout provided by an associated Matestack layout class (see below). The page itself uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.\n\n{% code title=\"app/matestack/pages/some_page.rb\" %}\n```ruby\nclass Pages::SomePage < Matestack::Ui::Page\n\n  def response\n    div class: \"container\" do\n      span id: \"hello\" do\n        plain \"hello world!\"\n      end\n      Components::Card.call(title: \"foo\", body: \"bar\")\n    end\n  end\n\nend\n```\n{% endcode %}\n\nPages are used as Rails view substitutes and therefore called in a Rails controller action:\n\n{% code title=\"app/controllers/some_controller.rb\" %}\n```ruby\nclass SomeController < ApplicationController\n\n  include Matestack::Ui::Core::Helper\n\n  def overview\n    render Pages::SomePage\n  end\n\nend\n```\n{% endcode %}\n\nThe page response - in this case - will be yielded into the Rails layout if not specified differently.\n\n#### 3. Wrap Matestack Pages in Matestack Layouts\n\nJust like a Rails layout would yield a Rails view, a Matestack layout yields a Matestack page. The layout uses Matestack's HTML rendering mechanism in a `response` method and may additionally call other components in order to define a specific UI.\n\n{% code title=\"app/matestack/some_app/some_layout.rb\" %}\n```ruby\nclass SomeApp::SomeLayout < Matestack::Ui::Layout\n\n  def response\n    h1 \"Some App\"\n    main do\n      yield\n    end\n  end\n\nend\n```\n{% endcode %}\n\nIn this basic example the layout is using the methods `h1` and `main` in order to create the markup as well as a `yield` in order to yield a page on a specific position.\n\n{% hint style=\"info\" %}\nA Matestack layout itself will be yielded into the Rails layout, unless the Rails layout is disabled in the controler via:`layout false`\n{% endhint %}\n\nUsually a layout implies a specific context of your application. Multiple pages are then scoped within that context, which could lead to a file structure like:\n\n```bash\napp/matestack/\n|\n└───some_app/\n│   │   some_layout.rb\n│   └───pages/\n│   │   │   page1.rb\n│   │   │   page2.rb\n│   │   │   page3.rb\n```\n\nand then used in a controller like this:\n\n{% code title=\"app/controllers/some_controller.rb\" %}\n```ruby\nclass SomeController < ApplicationController\n\n  include Matestack::Ui::Core::Helper\n\n  matestack_layout SomeApp::SomeLayout\n\n  def page_1\n    render SomeApp::Pages::Page1\n  end\n\n  def page_2\n    render SomeApp::Pages::Page2\n  end\n\n  def page_3\n    render SomeApp::Pages::Page3, matestack_layout: false # skip app layout on this page\n  end\n\nend\n```\n{% endcode %}\n"
  },
  {
    "path": "docs/migrate-from-2.x-to-3.0.md",
    "content": "# Migrating from 2.x to 3.0\n\n## Core/VueJs repo and gem split\n\n* `matestack-ui-core` previously contained logic for\n  * Ruby -> HTML conversion\n  * Reactivity via prebuilt and custom Vue.js components\n* in order to have better seperation of concerns, we've moved the reactivity related things to its own repository/gem -> `matestack-ui-vue_js`\n* `matestack-ui-core` is now meant to be combined with any reactivity framework or none at all\n\n{% hint style=\"warning\" %}\n**Please follow the migration guide within the docs of `matestack-ui-vuejs` when using reactivity features of `matestack-ui-core` 2.x**\n{% endhint %}\n\n## Remove `matestack-ui-core` JavaScript package\n\n- `matestack-ui-core` does not ship a JavaScript package anymore\n- please remove the package from your application and switch to `matestack-ui-vuejs` for the VueJs driven reactivity if required\n\n```\nyarn remove matestack-ui-core\n```\n\n## `Matestack::Ui::App` is now called `Matestack::Ui::Layout`\n\n* `Matestack::Ui::App` was always meant to be a layout wrapping pages, but was supercharged with some vuejs logic before splitting the `core` and `vuejs` repos\n* now `Matestack::Ui::App` is only a layout, that's why it should be named like that: `Matestack::Ui::Layout`\n\n\\-> Search\\&Replace\n\n## `matestack_app` method is renamed to `matestack_layout`\n\n* following the above mentioned naming adjustment, the `matestack_app` method used on controller level is renamed to `matestack_layout`\n\n`app/controllers/demo_controller.rb`\n\n```ruby\nclass DemoController < ActionController::Base\n  include Matestack::Ui::Core::Helper\n\n  layout \"application\" # root rails layout file\n\n  matestack_layout DemoApp::Layout # <-- renamed from matestack_app\n\n  def foo\n    render DemoApp::Pages::Foo\n  end\n\nend\n```\n\n\\-> Search\\&Replace\n\n## `Matestack::Ui::Layout` `Matestack::Ui::Page` wrapping DOM structures\n\n* previously, `Matestack::Ui::App` added some wrapping DOM structure around the whole layout and around it's `yield`\n* this enabled dynamic page transition and loading state animations\n* `Matestack::Ui::Layout` now purely renders the layout and yields a page without anything in between\n* the wrapping DOM structres required for dynamic page transitions and loading state animations needs to be added via two new components if you want to use these features via `matestack-ui-vue_js` (see section below!)\n\n`matestack/some/app/layout.rb`\n\n```ruby\nclass Some::App::Layout < Matestack::Ui::Layout\n  def response\n    h1 \"Demo App\"\n    main do\n      yield\n    end\n  end\nend\n```\n\n`matestack/some/app/pages/some_page.rb`\n\n```ruby\nclass Some::App::Pages::SomePage < Matestack::Ui::Page\n  def response\n    h2 \"Some Page\"\n  end\nend\n```\n\nwill just render:\n\n```html\n<body> <!-- coming from rails layout if specified -->\n  <!-- no wrapping DON structure around the layout -->\n  <h1>Demo App</<h1>\n  <main>\n    <!-- page markup without any wrapping DOM structure -->\n    <h2>Some Page</h2>\n  <main>\n</body>\n```\n\n\\-> Adjust CSS if you have created any rules targeting the wrapping DOM structure which now only is applied when using components from `matestack-ui-vuejs` explicitly\n"
  },
  {
    "path": "docs/pages/api.md",
    "content": "# Page API\n\n## Response\n\nUse the `response` method to define the UI of the page by using Matestack's HTML rendering or calling components.\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  def response\n    div id: \"div-on-page\" do\n      SomeComponent.()\n    end\n  end\n\nend\n```\n\n```ruby\n  class SomeComponent < Matestack::Ui::Component\n\n    def response\n      div id: \"my-component\" do\n        plain \"hello world!\"\n      end\n    end\n\n  end\n```\n\n## Partials and helper methods\n\nUse partials to keep the code dry and indentation layers manageable!\n\n### Local partials on page level\n\nIn the page definition, see how this time from inside the response, the `my_partial` method below is called:\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  def response\n    div id: \"my-page\" do\n      my_partial \"foo from page\"\n    end\n  end\n\n  private # optionally mark your partials as private\n\n  def my_partial text\n    div class: \"nested\"\n      plain text\n    end\n  end\n\nend\n```\n\n### Partials defined in modules\n\nExtract code snippets to modules for an even better project structure. First, create a module:\n\n```ruby\nmodule MySharedPartials\n\n  def my_partial text\n    div class: \"nested\"\n      plain text\n    end\n  end\n\nend\n```\n\nInclude the module in the page:\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  include MySharedPartials\n\n  def response\n    div id: \"my-page\" do\n      my_partial \"foo from component\"\n    end\n  end\n\nend\n```\n\n### Helper methods\n\nNot only can instance methods be used as \"partials\" but as general helpers performing any kind of logic or data resolving:\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  def response\n    div id: \"my-page\" do\n      if is_admin?\n        latest_users.each do |user|\n          div do\n            plain user.name # ...\n          end\n        end\n      else\n        plain \"not authorized\"\n      end \n    end\n  end\n\n  private # optionally mark your helper methods as private\n\n  def is_admin?\n    true # some crazy Ruby logic!\n  end\n\n  def latest_users\n    User.last(10) # calling ActiveRecord models for example\n  end\n\nend\n```\n\n## Prepare\n\nUse a prepare method to resolve instance variables before rendering a page if required.\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  def prepare\n    @some_data = \"some data\"\n  end\n\n  def response\n    div id: \"my-page\" do\n      plain @some_data\n    end\n  end\n\nend\n```\n\n## Params access\n\nA page can access request information, e.g. url query params, by calling the `params` method:\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  def response\n    div id: \"my-page\" do\n      plain params[:foo]\n    end\n  end\n\nend\n```\n\nNow, visiting the respective route to the page, e.g. via `/xyz?foo=bar`, the page reads the `[:foo]` from the params and displays it.\n\n## Passing data to pages\n\nSometimes you want to pass in data from the calling controller action into the page. This works the same way as seen at components:\n\n```ruby\nclass SoomeController < ActionController::Base\n\n  include Matestack::Ui::Core::Helper\n\n  def some_page\n    render SomePage, foo: 'bar', bar: 'baz'\n  end\n\nend\n```\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  required :foo\n  optional :bar\n\n  def response\n    div id: \"my-page\" do\n      plain context.foo # \"bar\"\n      plain context.bar # \"baz\"\n    end\n  end\n\nend\n```\n\n"
  },
  {
    "path": "docs/pages/rails-controller-integration.md",
    "content": "# Rails Controller Integration\n\nPages are used as Rails view substitutes and therefore called in a Rails controller action:\n\n{% code title=\"app/controllers/some_controller.rb\" %}\n```ruby\nclass SomeController < ApplicationController\n\n  include Matestack::Ui::Core::Helper\n\n  def overview\n    render Pages::SomePage\n  end\n\nend\n```\n{% endcode %}\n\n{% hint style=\"info\" %}\nA Matestack page will in this case be yielded into the Rails layout, unless the Rails layout is disabled in the controller via:`layout false`\n{% endhint %}\n\n## Passing data to pages\n\nSometimes you want to pass in data from the calling controller action into the page. This works the same way as seen at components:\n\n```ruby\nclass SomeController < ActionController::Base\n\n  include Matestack::Ui::Core::Helper\n\n  def some_page\n    render SomePage, foo: 'bar', bar: 'baz'\n  end\n\nend\n```\n\n```ruby\nclass SomePage < Matestack::Ui::Page\n\n  required :foo\n  optional :bar\n\n  def response\n    div id: \"my-page\" do\n      plain context.foo # \"bar\"\n      plain context.bar # \"baz\"\n    end\n  end\n\nend\n```\n"
  },
  {
    "path": "entrypoint.sh",
    "content": "#!/bin/bash\nset -e\n\nif [[ ! -e /app/Gemfile.lock ]]; then\n    bundle install\nfi\n\n# Remove a potentially pre-existing server.pid for Rails.\nrm -f /app/tmp/pids/server.pid\n\n# Then exec the container's main process (what's set as CMD in the Dockerfile).\nexec \"$@\"\n"
  },
  {
    "path": "lib/matestack/ui/component.rb",
    "content": "Matestack::Ui::Component = Matestack::Ui::Core::Component"
  },
  {
    "path": "lib/matestack/ui/core/base.rb",
    "content": "require_relative 'tag_helper'\n\nmodule Matestack\n  module Ui\n    module Core\n      class Base\n        include ActionView::Helpers::TagHelper\n\n        include Matestack::Ui::Core::Properties\n        include Matestack::Ui::Core::TagHelper\n\n        attr_accessor :html_tag, :text, :options, :parent, :escape, :bind_to_parent\n\n        def initialize(html_tag = nil, text = nil, options = {}, &block)\n          return unless render?\n\n          if options && options[:detach_from_parent] == true\n            self.bind_to_parent = false\n          else\n            self.bind_to_parent = ([:without_parent].include?(html_tag) ? false : true)\n          end\n          self.slots = self.options.delete(:slots) if self.options\n          # extract_options(text, options) is called in properties\n          self.html_tag = html_tag if self.bind_to_parent\n          self.escape = self.options.delete(:escape) || true\n          self.parent = Matestack::Ui::Core::Context.parent\n          self.parent.children << self if self.parent if self.bind_to_parent\n          self.prepare\n          Matestack::Ui::Core::Context.parent = self\n          create_children(&block)\n          Matestack::Ui::Core::Context.parent = self.parent\n          self\n        end\n\n        # can be optionally overwritten in subclass\n        # in order to conditionally render the component\n        def render?\n          true\n        end\n\n        # check if text is given and set text and options accordingly\n        def extract_options(text, options)\n          if text.is_a? Hash\n            # we need to dup the text object because we're deleting keys from this object which manipulates the object passed in here\n            # if this object is reused after beeing injected into this component, the keys would be missing\n            self.options = text.dup\n          else\n            self.text = text\n            # we need to dup the options object because we're deleting keys from this object which manipulates the object passed in here\n            # if this object is reused after beeing injected into this component, the keys would be missing\n            self.options = options.dup || {}\n          end\n          self.options.symbolize_keys!\n        end\n\n        def prepare\n          # can be optionally overwritten in subclass in order to set\n          # instance vars for example, might get deprecated in the future\n        end\n\n        # create child items by either running the response method if exists or executing the block\n        # overwrite if needed (like in pages or apps)\n        def create_children(&block)\n          if respond_to?(:response)\n            self.response &block\n          else\n            block.call if block_given?\n          end\n        end\n\n        def self.call(text = nil, options = {}, &block)\n          self.new(nil, text, options, &block).render_content\n        end\n\n        def children\n          @children ||= []\n        end\n\n        def render_content\n          if children.empty?\n            child_content = self.escape ? ERB::Util.html_escape(text) : text if text\n          else\n            # using \"\\n\" in order to preserve the 1.x rendering behavior which impacts appearance in browser\n            child_content = (children.map { |child| \" \\n \" + child.render_content }.join + \" \\n \").html_safe\n          end\n          result = ''\n          if self.html_tag\n            result = tag.public_send(self.html_tag, child_content, **self.options || {})\n          elsif child_content\n            result = child_content\n          end\n          result\n        end\n\n        def params\n          Matestack::Ui::Core::Context.params || ActionController::Parameters.new({})\n        end\n\n        def view_context\n          if Matestack::Ui::Core::Context.controller.nil?\n            Matestack::Ui::Core::Context.controller = ActionController::Base.new\n          else\n            Matestack::Ui::Core::Context.controller&.view_context\n          end\n        end\n\n        def method_missing(name, *args, **kwargs, &block)\n          if view_context && view_context.respond_to?(name, true)\n            view_context_response = view_context.send(name, *args, **kwargs, &block)\n            return view_context_response\n          end\n          if Rails.application.routes.url_helpers.respond_to?(name, true)\n            return Rails.application.routes.url_helpers.send(name, *args, &block)\n          end\n          return raise NameError, \"#{name} is not defined for #{self.class}\", caller\n        end\n\n        def to_str\n          render_content\n        end\n        alias to_s to_str\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/component.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      class Component < Base\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/matestack/ui/core/context.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      class Context < ActiveSupport::CurrentAttributes\n\n        attribute :layout\n        attribute :parent\n        attribute :isolated_parent\n        attribute :params\n        attribute :controller\n        attribute :component_block\n        attribute :async_components\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/helper.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      module Helper\n\n        def self.included(base)\n          base.extend ClassMethods\n        end\n\n        module ClassMethods\n          def inherited(subclass)\n            subclass.matestack_layout(@matestack_layout)\n            super\n          end\n\n          def matestack_layout(layout = nil)\n            @matestack_layout = layout ? layout : @matestack_layout\n          end\n        end\n\n        def render(*args)\n          setup_context\n          if args.first.is_a?(Class) && args.first.ancestors.include?(Base)\n            raise 'expected a hash as second argument' unless args.second.is_a?(Hash) || args.second.nil?\n\n            begin\n              controller_layout = self.class.send(:_layout)\n            rescue\n              controller_layout = nil\n            end\n\n            options = args.second || {}\n            layout = options.delete(:matestack_layout) || self.class.matestack_layout\n            page = args.first\n\n            if controller_layout == false\n              root_layout = layout ? layout.layout : false\n            else\n              # when using the turbo-rails gem, controller_layout is a Proc\n              # https://github.com/hotwired/turbo-rails/blob/v1.0.1/app/controllers/turbo/frames/frame_request.rb#L16\n              # and not nil or a string indicating which layout to be used like before\n              if controller_layout.nil? || controller_layout.is_a?(Proc)\n                root_layout = \"application\"\n              else\n                root_layout = controller_layout\n              end\n            end\n\n            if layout && params[:only_page].nil? && params[:component_key].nil? && params[:component_class].nil?\n              render_layout layout, page, options, root_layout\n            else\n              if params[:component_key] && params[:component_class].nil?\n                render_component layout, page, params[:component_key], options\n              elsif params[:component_class]\n                if params[:component_key]\n                  render_component nil, params[:component_class].constantize, params[:component_key], JSON.parse(params[:public_options] || '{}')\n                else\n                  render html: params[:component_class].constantize.(public_options: JSON.parse(params[:public_options] || '{}'))\n                end\n              else\n                if params[:only_page]\n                  render_page page, options, false\n                else\n                  render_page page, options, root_layout\n                end\n              end\n            end\n          else\n            super\n          end\n        end\n\n        def render_layout(layout, page, options, root_layout)\n          render html: layout.new(options) { page.new(options) }.render_content.html_safe, layout: root_layout\n        end\n\n        def render_page(page, options, root_layout)\n          render html: page.new(options).render_content.html_safe, layout: root_layout\n        end\n\n        def render_component(layout, page, component_key, options)\n          layout ? layout.new(options) { page.new(options) } : page.new(options) # create page structure in order to later access registered async components\n          render html: Matestack::Ui::Core::Context.async_components[component_key].render_content.html_safe, layout: false\n        end\n\n        def setup_context\n          Matestack::Ui::Core::Context.params = self.params\n          Matestack::Ui::Core::Context.controller = (self.class <= ActionController::Base) ? self : @_controller\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/layout.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      class Layout < Base\n\n        def initialize(options = {})\n          @controller = Context.controller\n          Context.layout = self\n          super(nil, nil, options)\n        end\n\n        # layout class method to specify if a rails layout should be used\n        def self.inherited(subclass)\n          subclass.layout(@layout)\n          super\n        end\n\n        def self.layout(layout = nil)\n          @layout = layout ? layout : @layout\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/page.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      class Page < Base\n\n        def initialize(options = {})\n          super(nil, nil, options)\n        end\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/properties.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      module Properties\n\n        def self.included(base)\n          base.extend ClassMethods\n          base.send :prepend, Initializer\n        end\n\n        module Initializer\n          def initialize(html_tag = nil, text = nil, options = {}, &block)\n            extract_options(text, options)\n            create_context\n            set_text\n            super\n          end\n        end\n\n        module ClassMethods\n          extend Gem::Deprecate\n\n          def required(*args)\n            @required = (@required || []).concat(args)\n          end\n          alias requires required\n\n          def optional(*args)\n            @optional = (@optional || []).concat(args)\n          end\n\n          def required_property_keys\n            @required\n          end\n\n          def optional_property_keys\n            @optional\n          end\n\n          def inherited(subclass)\n            subclass.required(*required_property_keys)\n            subclass.optional(*optional_property_keys)\n            super\n          end\n        end\n\n        def context\n          @context ||= OpenStruct.new\n        end\n        alias :ctx :context\n\n        def required_property_keys\n          self.class.required_property_keys || []\n        end\n\n        def optional_property_keys\n          self.class.optional_property_keys || []\n        end\n\n        def create_context\n          create_context_for_properties(self.required_property_keys, required: true)\n          create_context_for_properties(self.optional_property_keys)\n        end\n\n        def create_context_for_properties(properties, required: false)\n          properties.uniq.each do |property|\n            if property.is_a? Hash\n              property.each do |key, value|\n                method_name = value[:as] || key\n                raise \"required property '#{key}' is missing for '#{self.class}'\" if required && self.options[key].nil?\n                context.send(:\"#{method_name}=\", self.options.delete(key))\n              end\n            else\n              raise \"required property '#{property}' is missing for '#{self.class}'\" if required && self.options[property].nil?\n              context.send(:\"#{property}=\", self.options.delete(property))\n            end\n          end if properties\n        end\n\n        def set_text\n          # the text property is treated specially since 2.0.0 enables text injection for all components like:\n          #\n          # some_component \"foo\", class: \"whatever\" -> self.text -> \"foo\"\n          #\n          # prior to 2.0.0, text injection happened like that:\n          #\n          # some_component text: \"foo\", class: \"whatever\" -> self.options[:text] -> \"foo\"\n          #\n          # in both cases \"foo\" should be available via self.context.text AND self.text\n          #\n          # in 2.0.0 text is available via context.text if text is marked as required or optional\n          # in order to have a consistent access, we make this text accessable via self.text as well in this case\n          # in all cases, text is accessable via self.text AND self.context.text\n          # we make the passed in text option available via context.text by default, even if not marked as required or optional\n          #\n          # additionally we need to delete text from the options, as they might be used to be rendered as\n          # tag attributes without any whitelisting as happened prior to 2.0.0\n          self.text = self.options.delete(:text) if self.options.has_key?(:text)\n          self.context.text = self.text\n        end\n        \n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/slots.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      module Slots\n\n        attr_accessor :slots\n\n        def slot(key, *args)\n          slots[key].call(*args)\n        end\n\n      end\n    end\n  end\nend"
  },
  {
    "path": "lib/matestack/ui/core/tag_helper.rb",
    "content": "require_relative 'slots'\nmodule Matestack\n  module Ui\n    module Core\n      module TagHelper\n        extend Gem::Deprecate\n        include Slots\n\n        # can't take content or a block\n        VOID_TAGS = %i[area base br col hr img input link meta param command keygen source]\n\n        TAGS = [:a, :abbr, :acronym, :address, :applet, :area, :article, :aside, :audio, :b, :base, :basefont, :bdi, :bdo, :big, :blockquote, :body, :br, :button, :canvas, :caption, :center, :cite, :code, :col, :colgroup, :data, :datalist, :dd, :del, :details, :dfn, :dialog, :dir, :div, :dl, :dt, :em, :embed, :fieldset, :figcaption, :figure, :font, :footer, :form, :frame, :frameset, :h1, :h2, :h3, :h4, :h5, :h6, :head, :header, :hr, :html, :i, :iframe, :img, :input, :ins, :kbd, :label, :legend, :li, :link, :main, :map, :mark, :meta, :meter, :nav, :noframes, :noscript, :object, :ol, :optgroup, :option, :output, :paragraph, :param, :picture, :pre, :progress, :q, :rp, :rt, :ruby, :s, :samp, :script, :section, :select, :small, :source, :span, :strike, :strong, :style, :sub, :summary, :sup, :svg, :table, :tbody, :td, :template, :textarea, :tfoot, :th, :thead, :time, :title, :tr, :track, :tt, :u, :ul, :var, :video, :wbr]\n\n        VOID_TAGS.each do |tag|\n          define_method tag do |options = {}|\n            Matestack::Ui::Core::Base.new(tag, nil, options)\n          end\n        end\n\n        TAGS.each do |tag|\n          define_method tag do |text = nil, options = {}, &block|\n            tag = :p if tag == :paragraph\n            Matestack::Ui::Core::Base.new(tag, text, options, &block)\n          end\n        end\n\n        def plain(text=nil, options=nil, &block)\n          if block_given?\n            Matestack::Ui::Core::Base.new(nil, yield, options)\n          else\n            Matestack::Ui::Core::Base.new(nil, text, options)\n          end\n        end\n\n        def unescape(text)\n          Matestack::Ui::Core::Base.new(nil, text&.html_safe, escape: false)\n        end\n        alias unescaped unescape\n\n        # override image in order to implement automatically using rails assets path\n        def img(text = nil, options = {}, &block)\n          # if :src attribut given try to replace automatically\n          if src = text.delete(:path)\n            text[:src] = ActionController::Base.helpers.asset_path(src)\n          end\n          Matestack::Ui::Core::Base.new(:img, text, options, &block)\n        end\n\n        def a(text = nil, options = {}, &block)\n          # if :path attribut given rename to href\n          if text.is_a?(Hash)\n            text[:href] = text.delete(:path) if text[:href].nil?\n          else\n            options[:href] = options.delete(:path) if options[:href].nil?\n          end\n          Matestack::Ui::Core::Base.new(:a, text, options, &block)\n        end\n\n        # support old heading component\n        def heading(text = nil, options=nil, &block)\n          if text.is_a?(Hash)\n            options = text\n          end\n\n          case options[:size]\n          when 1\n            h1(text, options, &block)\n          when 2\n            h2(text, options, &block)\n          when 3\n            h3(text, options, &block)\n          when 4\n            h4(text, options, &block)\n          when 5\n            h5(text, options, &block)\n          when 6\n            h6(text, options, &block)\n          else\n            h1(text, options, &block)\n          end\n        end\n\n        def rails_render(options = {})\n          plain render options\n        end\n\n        def detached(text=nil, options=nil, &block)\n          options = {} if options.nil?\n          options[:detach_from_parent] = true\n          Matestack::Ui::Core::Base.new(nil, text, options, &block)\n        end\n\n        def detached_to_s(text=nil, options=nil, &block)\n          detached(text, options, &block).to_str\n        end\n        alias matestack_to_s detached_to_s\n\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core/version.rb",
    "content": "module Matestack\n  module Ui\n    module Core\n      VERSION = '3.0.1'\n    end\n  end\nend\n"
  },
  {
    "path": "lib/matestack/ui/core.rb",
    "content": "base_path = 'matestack/ui/core'\nrequire \"#{base_path}/version\"\n\nmodule Matestack\n  module Ui\n    module Core\n\n    end\n  end\nend\n\nrequire \"#{base_path}/context\"\nrequire \"#{base_path}/properties\"\nrequire \"#{base_path}/base\"\nrequire \"#{base_path}/component\"\nrequire \"#{base_path}/page\"\nrequire \"#{base_path}/layout\"\nrequire \"#{base_path}/helper\"\n\n# require abbreveations for apps, pages and components\nrequire \"matestack/ui/layout\"\nrequire \"matestack/ui/page\"\nrequire \"matestack/ui/component\"\n"
  },
  {
    "path": "lib/matestack/ui/layout.rb",
    "content": "Matestack::Ui::Layout = Matestack::Ui::Core::Layout\n"
  },
  {
    "path": "lib/matestack/ui/page.rb",
    "content": "Matestack::Ui::Page = Matestack::Ui::Core::Page\n"
  },
  {
    "path": "matestack-ui-core.gemspec",
    "content": "$:.push File.expand_path(\"lib\", __dir__)\n\n# Maintain your gem's version:\nrequire \"matestack/ui/core/version\"\n\n# Describe your gem and declare its dependencies:\nGem::Specification.new do |s|\n  s.name        = \"matestack-ui-core\"\n  s.version     = Matestack::Ui::Core::VERSION\n  s.authors     = [\"Jonas Jabari\"]\n  s.email       = [\"jonas@matestack.io\"]\n  s.homepage    = \"https://matestack.io\"\n  s.summary     = \"Escape the frontend hustle & easily create interactive web apps in pure Ruby.\"\n  s.description = \"Matestack provides a collection of open source gems made for Ruby on Rails developers. Matestack enables you to craft interactive web UIs without JavaScript in pure Ruby with minimum effort. UI code becomes a native and fun part of your Rails app.\"\n  s.license     = \"MIT\"\n  s.metadata    = { \"source_code_uri\" => \"https://github.com/matestack/matestack-ui-core\" }\n\n  s.files = Dir[\"{app,config,db,lib,vendor}/**/*\", \"LICENSE\", \"Rakefile\", \"README.md\"]\n\n  s.add_dependency \"rails\", '>= 5.2'\nend\n"
  },
  {
    "path": "results.txt",
    "content": "Capybara starting Puma...\n* Version 4.3.5 , codename: Mysterious Traveller\n* Min threads: 0, max threads: 4\n* Listening on tcp://0.0.0.0:33123\n.............................................................................................................................\n\nFinished in 12.69 seconds (files took 2.38 seconds to load)\n125 examples, 0 failures\n\nCoverage report generated for Unit Tests to /app/coverage. 209 / 2187 LOC (9.56%) covered.\n"
  },
  {
    "path": "spec/core_spec_helper.rb",
    "content": "# This file was generated by the `rails generate rspec:install` command. Conventionally, all\n# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.\n# The generated `.rspec` file contains `--require spec_helper` which will cause\n# this file to always be loaded, without a need to explicitly require it in any\n# files.\n#\n# Given that it is always loaded, you are encouraged to keep this file as\n# light-weight as possible. Requiring heavyweight dependencies from this file\n# will add to the boot time of your test suite on EVERY test run, even for an\n# individual file that may not need all of that loaded. Instead, consider making\n# a separate helper file that requires the additional dependencies and performs\n# the additional setup, and require it from the spec files that actually need\n# it.\n#\n# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration\nrequire 'simplecov'\nSimpleCov.start do\n  enable_coverage :branch\n\n  add_filter \"/spec\"\n  add_filter %r{^/config/}\n\n\n  add_group \"Concepts\", \"/app/concepts\"\n  add_group \"Helpers\", \"/app/helpers\"\n  add_group \"App Lib\", \"/app/lib\"\n  add_group \"Lib\", %r{^/lib/}\n\n  track_files \"{app,lib}/**/*.rb\"\nend\n\nrequire 'webmock/rspec'\nWebMock.allow_net_connect!\n\nrequire File.join File.dirname(__FILE__), 'dummy', 'config', 'environment.rb'\n\nDir[File.join File.dirname(__FILE__), 'test', 'core', 'support', '**', '*.rb'].each { |f| require f }\n\nrequire 'pry'\n\n# require 'rspec/retry'\n# require \"rspec/wait\"\n\nRSpec.configure do |config|\n\n  # run retry only on features\n  # config.around :each, :js do |ex|\n  #   ex.run_with_retry retry: 3\n  # end\n\n  # config.include Capybara::DSL\n  # rspec-expectations config goes here. You can use an alternate\n  # assertion/expectation library such as wrong or the stdlib/minitest\n  # assertions if you prefer.\n  config.expect_with :rspec do |expectations|\n    # This option will default to `true` in RSpec 4. It makes the `description`\n    # and `failure_message` of custom matchers include text for helper methods\n    # defined using `chain`, e.g.:\n    #     be_bigger_than(2).and_smaller_than(4).description\n    #     # => \"be bigger than 2 and smaller than 4\"\n    # ...rather than:\n    #     # => \"be bigger than 2\"\n    expectations.include_chain_clauses_in_custom_matcher_descriptions = true\n  end\n\n  # rspec-mocks config goes here. You can use an alternate test double\n  # library (such as bogus or mocha) by changing the `mock_with` option here.\n  config.mock_with :rspec do |mocks|\n    # Prevents you from mocking or stubbing a method that does not exist on\n    # a real object. This is generally recommended, and will default to\n    # `true` in RSpec 4.\n    mocks.verify_partial_doubles = true\n  end\n\n  # This option will default to `:apply_to_host_groups` in RSpec 4 (and will\n  # have no way to turn it off -- the option exists only for backwards\n  # compatibility in RSpec 3). It causes shared context metadata to be\n  # inherited by the metadata hash of host groups and examples, rather than\n  # triggering implicit auto-inclusion in groups with matching metadata.\n  config.shared_context_metadata_behavior = :apply_to_host_groups\n\n# The settings below are suggested to provide a good initial experience\n# with RSpec, but feel free to customize to your heart's content.\n=begin\n  # This allows you to limit a spec run to individual examples or groups\n  # you care about by tagging them with `:focus` metadata. When nothing\n  # is tagged with `:focus`, all examples get run. RSpec also provides\n  # aliases for `it`, `describe`, and `context` that include `:focus`\n  # metadata: `fit`, `fdescribe` and `fcontext`, respectively.\n  config.filter_run_when_matching :focus\n\n  # Allows RSpec to persist some state between runs in order to support\n  # the `--only-failures` and `--next-failure` CLI options. We recommend\n  # you configure your source control system to ignore this file.\n  config.example_status_persistence_file_path = \"spec/examples.txt\"\n\n  # Limits the available syntax to the non-monkey patched syntax that is\n  # recommended. For more details, see:\n  #   - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/\n  #   - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/\n  #   - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode\n  config.disable_monkey_patching!\n\n  # Many RSpec users commonly either run the entire suite or an individual\n  # file, and it's useful to allow more verbose output when running an\n  # individual spec file.\n  if config.files_to_run.one?\n    # Use the documentation formatter for detailed output,\n    # unless a formatter has already been configured\n    # (e.g. via a command-line flag).\n    config.default_formatter = \"doc\"\n  end\n\n  # Print the 10 slowest examples and example groups at the\n  # end of the spec run, to help surface which specs are running\n  # particularly slow.\n  config.profile_examples = 10\n\n  # Run specs in random order to surface order dependencies. If you find an\n  # order dependency and want to debug it, you can fix the order by providing\n  # the seed, which is printed after each run.\n  #     --seed 1234\n  config.order = :random\n\n  # Seed global randomization in this process using the `--seed` CLI option.\n  # Setting this allows you to use `--seed` to deterministically reproduce\n  # test failures related to randomization by passing the same `--seed` value\n  # as the one that triggered the failure.\n  Kernel.srand config.seed\n=end\n\n  config.before :all, type: :feature do\n    unless Rails.application.routes.url_helpers.method_defined?(:matestack_components_test_path)\n      Rails.application.routes.append do\n        get '/matestack_components_test', to: 'matestack_components#matestack_components_test', as: :matestack_components_test\n        get '/matestack_transition_test', to: 'matestack_components#matestack_transition_test', as: :matestack_transition_test\n        get '/example', to: 'example#page'\n        get '/base_example', to: 'example#base'\n      end\n      Rails.application.reload_routes!\n    end\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/Rakefile",
    "content": "# Add your own tasks in files placed in lib/tasks ending in .rake,\n# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.\n\nrequire_relative 'config/application'\n\nRails.application.load_tasks\n"
  },
  {
    "path": "spec/dummy/app/assets/config/manifest.js",
    "content": "//= link_tree ../images\n//= link_tree ../videos\n"
  },
  {
    "path": "spec/dummy/app/assets/images/.keep",
    "content": ""
  },
  {
    "path": "spec/dummy/app/channels/application_cable/channel.rb",
    "content": "module ApplicationCable\n  class Channel < ActionCable::Channel::Base\n  end\nend\n"
  },
  {
    "path": "spec/dummy/app/channels/application_cable/connection.rb",
    "content": "module ApplicationCable\n  class Connection < ActionCable::Connection::Base\n  end\nend\n"
  },
  {
    "path": "spec/dummy/app/controllers/application_controller.rb",
    "content": "class ApplicationController < ActionController::Base\nend\n"
  },
  {
    "path": "spec/dummy/app/controllers/concerns/.keep",
    "content": ""
  },
  {
    "path": "spec/dummy/app/controllers/demo_core_controller.rb",
    "content": "class DemoCoreController < ActionController::Base\n  include Matestack::Ui::Core::Helper\n\n  layout \"application_core\"\n\n  matestack_layout Demo::Core::Layout\n\n  def first\n    render Demo::Core::Pages::FirstPage\n  end\n\n  def second\n    render Demo::Core::Pages::SecondPage\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/controllers/legacy_views/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/controllers/legacy_views/pages_controller.rb",
    "content": "# used in specs\n\nclass LegacyViews::PagesController < ApplicationController\n  include Matestack::Ui::Core::Helper\n\n  layout 'legacy_views'\n\n  def viewcontext_custom_component\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/helpers/application_helper.rb",
    "content": "module ApplicationHelper\n  include Matestack::Ui::Core::Helper\n  include Matestack::Ui::Core::TagHelper\nend\n"
  },
  {
    "path": "spec/dummy/app/javascript/channels/consumer.js",
    "content": "// Action Cable provides the framework to deal with WebSockets in Rails.\n// You can generate new channels where WebSocket features live using the `rails generate channel` command.\n\nimport { createConsumer } from \"@rails/actioncable\"\n\nexport default createConsumer()\n"
  },
  {
    "path": "spec/dummy/app/javascript/channels/index.js",
    "content": "// Load all the channels within this directory and all subdirectories.\n// Channel files must be named *_channel.js.\n\nconst channels = require.context('.', true, /_channel\\.js$/)\nchannels.keys().forEach(channels)\n"
  },
  {
    "path": "spec/dummy/app/javascript/packs/application.js",
    "content": "/* eslint no-console:0 */\n// This file is automatically compiled by Webpack, along with any other files\n// present in this directory. You're encouraged to place your actual application logic in\n// a relevant structure within app/javascript and only use these pack files to reference\n// that code so it'll be compiled.\n//\n// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate\n// layout file, like app/views/layouts/application.html.erb\n\nrequire(\"@rails/ujs\").start()\nrequire(\"channels\")\n"
  },
  {
    "path": "spec/dummy/app/javascript/packs/application_core.js",
    "content": "/* eslint no-console:0 */\n// This file is automatically compiled by Webpack, along with any other files\n// present in this directory. You're encouraged to place your actual application logic in\n// a relevant structure within app/javascript and only use these pack files to reference\n// that code so it'll be compiled.\n//\n// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate\n// layout file, like app/views/layouts/application.html.erb\n\n// require(\"@rails/ujs\").start()\n// require(\"channels\")\n"
  },
  {
    "path": "spec/dummy/app/jobs/application_job.rb",
    "content": "class ApplicationJob < ActiveJob::Base\nend\n"
  },
  {
    "path": "spec/dummy/app/mailers/application_mailer.rb",
    "content": "class ApplicationMailer < ActionMailer::Base\n  default from: 'from@example.com'\n  layout 'mailer'\nend\n"
  },
  {
    "path": "spec/dummy/app/matestack/components/legacy_views/pages/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/matestack/components/legacy_views/pages/viewcontext.rb",
    "content": "# used in specs\n\nclass Components::LegacyViews::Pages::Viewcontext < Matestack::Ui::Component\n\n  def response\n    div id: \"my-component\" do\n      if view_context.view_renderer.instance_of?(ActionView::Renderer)\n        plain \"has access to ActionView Context\"\n      end\n      plain link_to \"Test Link\", \"/some/page\" # calling an ActionView Url Helper here\n      plain time_ago_in_words(3.minutes.from_now) # calling an ActionView Date Helper here\n      plain \"root_path: #{root_path}\" # calling a Path Helper here\n    end\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/matestack/demo/core/components/static_component.rb",
    "content": "class Demo::Core::Components::StaticComponent < Matestack::Ui::Component\n\n  required :foo\n\n  def response\n    plain \"A simple Static Component with given input foo: #{context.foo}\"\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/matestack/demo/core/layout.rb",
    "content": "class Demo::Core::Layout < Matestack::Ui::Layout\n\n  def response\n    h1 \"Demo Core App\"\n\n    paragraph do\n      plain \"play around! --> spec/dummy/app/matestack/demo/core/app.rb\"\n    end\n\n    nav do\n      a path: demo_core_first_page_path do\n        button \"First Page\"\n      end\n      a path: demo_core_second_page_path do\n        button \"Second Page\"\n      end\n    end\n\n    main do\n      yield\n    end\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/matestack/demo/core/pages/first_page.rb",
    "content": "class Demo::Core::Pages::FirstPage < Matestack::Ui::Page\n\n  def response\n    h2 \"First page\"\n\n    paragraph do\n      plain \"play around! --> spec/dummy/app/matestack/demo/core/pages/first_page.rb\"\n    end\n\n    # you can call components on pages:\n    Demo::Core::Components::StaticComponent.call(foo: \"bar\")\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/matestack/demo/core/pages/second_page.rb",
    "content": "class Demo::Core::Pages::SecondPage < Matestack::Ui::Page\n\n  def response\n    h2 \"Second Page\"\n\n    paragraph do\n      plain \"play around! --> spec/dummy/app/matestack/demo/core/pages/second_page.rb\"\n    end\n\n    # you can call components on pages:\n    Demo::Core::Components::StaticComponent.call(foo: \"baz\")\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/app/models/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/models/application_record.rb",
    "content": "class ApplicationRecord < ActiveRecord::Base\n  self.abstract_class = true\nend\n"
  },
  {
    "path": "spec/dummy/app/models/concerns/.keep",
    "content": ""
  },
  {
    "path": "spec/dummy/app/models/dummy_child_model.rb",
    "content": "# used in specs\n\nclass DummyChildModel < ApplicationRecord\n\n  validates :title, presence: true, uniqueness: true\n\n  has_one_attached :file\n  has_many_attached :files\n\nend\n"
  },
  {
    "path": "spec/dummy/app/models/dummy_model.rb",
    "content": "# used in specs\n\nclass DummyModel < ApplicationRecord\n\n  validates :title, presence: true, uniqueness: true\n\n  has_one_attached :file\n  has_many_attached :files\n\n  has_many :dummy_child_models, index_errors: true #https://bigbinary.com/blog/errors-can-be-indexed-with-nested-attrbutes-in-rails-5\n  accepts_nested_attributes_for :dummy_child_models, allow_destroy: true\nend\n"
  },
  {
    "path": "spec/dummy/app/models/test_model.rb",
    "content": "# used in specs\n\nclass TestModel < ApplicationRecord\n\n  has_one_attached :file\n\nend\n"
  },
  {
    "path": "spec/dummy/app/views/_some_partial.html.erb",
    "content": "<h1>This is some partial</h1>\n<p><%= foo %></p>"
  },
  {
    "path": "spec/dummy/app/views/demo/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/views/demo/_header.html.erb",
    "content": "<header>\n  <h1>Rails Partial</h1>\n  <p><%= @title %></p>\n</header>"
  },
  {
    "path": "spec/dummy/app/views/demo/header.html.erb",
    "content": "<header>\n  <h1>Rails View</h1>\n  <p><%= @title %></p>\n</header>"
  },
  {
    "path": "spec/dummy/app/views/layouts/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/views/layouts/application.html.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Dummy</title>\n    <%= csrf_meta_tags %>\n    <%= csp_meta_tag %>\n\n    <%= javascript_pack_tag 'application' %>\n  </head>\n\n  <body>\n    <%= yield %>\n    <div id='from-rails-layout'></div>\n  </body>\n</html>\n"
  },
  {
    "path": "spec/dummy/app/views/layouts/application_core.html.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Core Demo</title>\n    <%= csrf_meta_tags %>\n    <%= csp_meta_tag %>\n\n    <%= javascript_pack_tag 'application_core' %>\n  </head>\n\n  <body>\n    <%= yield %>\n  </body>\n  <div id='from-rails-core-layout'></div> \n</html>\n"
  },
  {
    "path": "spec/dummy/app/views/layouts/legacy_views.erb",
    "content": "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Dummy</title>\n    <%= csrf_meta_tags %>\n    <%= csp_meta_tag %>\n\n    <%= javascript_pack_tag 'application_vue_js' %>\n  </head>\n\n  <body>\n    <div id='matestack-ui'>\n      <nav>\n        <ul>Page 1</ul>\n        <ul>Page 2</ul>\n      </nav>\n      <div>\n        <%= yield %>\n      </div>\n    </div>\n  </body>\n</html>\n"
  },
  {
    "path": "spec/dummy/app/views/legacy_views/pages/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/views/legacy_views/pages/viewcontext_custom_component.html.erb",
    "content": "<h1>Viewcontext Custom Component</h1>\n<%= Components::LegacyViews::Pages::Viewcontext.() %>\n"
  },
  {
    "path": "spec/dummy/app/views/rails/0_USED_IN_SPECS_DONT_TOUCH",
    "content": ""
  },
  {
    "path": "spec/dummy/app/views/rails/_some_partial.html.erb",
    "content": "<h2><%= name %></h2>\n<% 5.times do |i| %>\n  <p><%= i %><p>\n<% end %>"
  },
  {
    "path": "spec/dummy/app/views/rails/index.html.erb",
    "content": "<h1>Test</h1>\n<% 100.times do %>\n  <div>\n    <div>\n      <div>\n        <div>\n          <div>\n            <div>\n              <b>Nested Content</b>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n<% end %>\n<%= render partial: 'rails/some_partial', collection: (1..100).to_a, as: :name %>"
  },
  {
    "path": "spec/dummy/app/views/some_view.html.erb",
    "content": "<h1>A view :D</h1>\n<p><%= foo %></p>"
  },
  {
    "path": "spec/dummy/bin/bundle",
    "content": "#!/usr/bin/env ruby\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __dir__)\nload Gem.bin_path('bundler', 'bundle')\n"
  },
  {
    "path": "spec/dummy/bin/rails",
    "content": "#!/usr/bin/env ruby\nAPP_PATH = File.expand_path('../config/application', __dir__)\nrequire_relative '../config/boot'\nrequire 'rails/commands'\n"
  },
  {
    "path": "spec/dummy/bin/rake",
    "content": "#!/usr/bin/env ruby\nrequire_relative '../config/boot'\nrequire 'rake'\nRake.application.run\n"
  },
  {
    "path": "spec/dummy/bin/setup",
    "content": "#!/usr/bin/env ruby\nrequire 'fileutils'\ninclude FileUtils\n\n# path to your application root.\nAPP_ROOT = File.expand_path('..', __dir__)\n\ndef system!(*args)\n  system(*args) || abort(\"\\n== Command #{args} failed ==\")\nend\n\nchdir APP_ROOT do\n  # This script is a starting point to setup your application.\n  # Add necessary setup steps to this file.\n\n  puts '== Installing dependencies =='\n  system! 'gem install bundler --conservative'\n  system('bundle check') || system!('bundle install')\n\n  # Install JavaScript dependencies if using Yarn\n  # system('bin/yarn')\n\n  # puts \"\\n== Copying sample files ==\"\n  # unless File.exist?('config/database.yml')\n  #   cp 'config/database.yml.sample', 'config/database.yml'\n  # end\n\n  puts \"\\n== Preparing database ==\"\n  system! 'bin/rails db:setup'\n\n  puts \"\\n== Removing old logs and tempfiles ==\"\n  system! 'bin/rails log:clear tmp:clear'\n\n  puts \"\\n== Restarting application server ==\"\n  system! 'bin/rails restart'\nend\n"
  },
  {
    "path": "spec/dummy/bin/update",
    "content": "#!/usr/bin/env ruby\nrequire 'fileutils'\ninclude FileUtils\n\n# path to your application root.\nAPP_ROOT = File.expand_path('..', __dir__)\n\ndef system!(*args)\n  system(*args) || abort(\"\\n== Command #{args} failed ==\")\nend\n\nchdir APP_ROOT do\n  # This script is a way to update your development environment automatically.\n  # Add necessary update steps to this file.\n\n  puts '== Installing dependencies =='\n  system! 'gem install bundler --conservative'\n  system('bundle check') || system!('bundle install')\n\n  # Install JavaScript dependencies if using Yarn\n  # system('bin/yarn')\n\n  puts \"\\n== Updating database ==\"\n  system! 'bin/rails db:migrate'\n\n  puts \"\\n== Removing old logs and tempfiles ==\"\n  system! 'bin/rails log:clear tmp:clear'\n\n  puts \"\\n== Restarting application server ==\"\n  system! 'bin/rails restart'\nend\n"
  },
  {
    "path": "spec/dummy/bin/webpack",
    "content": "#!/usr/bin/env ruby\n\nENV[\"RAILS_ENV\"] ||= ENV[\"RACK_ENV\"] || \"development\"\nENV[\"NODE_ENV\"]  ||= \"development\"\n\nrequire \"pathname\"\nENV[\"BUNDLE_GEMFILE\"] ||= File.expand_path(\"../../../../Gemfile\",\n  Pathname.new(__FILE__).realpath)\n\nrequire \"bundler/setup\"\n\nrequire \"webpacker\"\nrequire \"webpacker/webpack_runner\"\n\nAPP_ROOT = File.expand_path(\"..\", __dir__)\nDir.chdir(APP_ROOT) do\n  Webpacker::WebpackRunner.run(ARGV)\nend\n"
  },
  {
    "path": "spec/dummy/bin/webpack-dev-server",
    "content": "#!/usr/bin/env ruby\n\nENV[\"RAILS_ENV\"] ||= ENV[\"RACK_ENV\"] || \"development\"\nENV[\"NODE_ENV\"]  ||= \"development\"\n\nrequire \"pathname\"\nENV[\"BUNDLE_GEMFILE\"] ||= File.expand_path(\"../../../../Gemfile\",\n  Pathname.new(__FILE__).realpath)\n\nrequire \"bundler/setup\"\n\nrequire \"webpacker\"\nrequire \"webpacker/dev_server_runner\"\n\nAPP_ROOT = File.expand_path(\"..\", __dir__)\nDir.chdir(APP_ROOT) do\n  Webpacker::DevServerRunner.run(ARGV)\nend\n"
  },
  {
    "path": "spec/dummy/bin/yarn",
    "content": "#!/usr/bin/env ruby\nAPP_ROOT = File.expand_path('..', __dir__)\nDir.chdir(APP_ROOT) do\n  begin\n    exec \"yarnpkg\", *ARGV\n  rescue Errno::ENOENT\n    $stderr.puts \"Yarn executable was not detected in the system.\"\n    $stderr.puts \"Download Yarn at https://yarnpkg.com/en/docs/install\"\n    exit 1\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/application.5.2_rb",
    "content": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n  class Application < Rails::Application\n    # Initialize configuration defaults for originally generated Rails version.\n    config.load_defaults 5.2\n\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration can go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded after loading\n    # the framework and any gems in your application.\n    # config.eager_load_paths += %W( #{config.root}/app/matestack/registry )\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/application.6.0_rb",
    "content": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n  class Application < Rails::Application\n    # Initialize configuration defaults for originally generated Rails version.\n    config.load_defaults 6.0\n\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration can go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded after loading\n    # the framework and any gems in your application.\n    # config.eager_load_paths += %W( #{config.root}/app/matestack/registry )\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/application.6.1_rb",
    "content": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n  class Application < Rails::Application\n    # Initialize configuration defaults for originally generated Rails version.\n    config.load_defaults 6.1\n\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration can go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded after loading\n    # the framework and any gems in your application.\n    # config.eager_load_paths += %W( #{config.root}/app/matestack/registry )\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/application.7.0_rb",
    "content": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n  class Application < Rails::Application\n    # Initialize configuration defaults for originally generated Rails version.\n    config.load_defaults 7.0\n\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration can go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded after loading\n    # the framework and any gems in your application.\n    # config.eager_load_paths += %W( #{config.root}/app/matestack/registry )\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/application.rb",
    "content": "require_relative 'boot'\n\nrequire 'rails/all'\n\nBundler.require(*Rails.groups)\nrequire \"matestack/ui/core\"\n\nmodule Dummy\n  class Application < Rails::Application\n    # Initialize configuration defaults for originally generated Rails version.\n    config.load_defaults 7.0\n\n    # Settings in config/environments/* take precedence over those specified here.\n    # Application configuration can go into files in config/initializers\n    # -- all .rb files in that directory are automatically loaded after loading\n    # the framework and any gems in your application.\n    # config.eager_load_paths += %W( #{config.root}/app/matestack/registry )\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/boot.rb",
    "content": "# Set up gems listed in the Gemfile.\nENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../Gemfile', __dir__)\n\nrequire 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])\n$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)\n"
  },
  {
    "path": "spec/dummy/config/cable.yml",
    "content": "development:\n  adapter: async\n\ntest:\n  adapter: async\n\nproduction:\n  adapter: redis\n  url: <%= ENV.fetch(\"REDIS_URL\") { \"redis://localhost:6379/1\" } %>\n  channel_prefix: dummy_production\n"
  },
  {
    "path": "spec/dummy/config/database.yml",
    "content": "default: &default\n  adapter: postgresql\n  encoding: unicode\n  host: postgres\n  username: <%= ENV.fetch(\"POSTGRES_USER\") { \"postgres\" } %>\n  password: <%= ENV.fetch(\"POSTGRES_PASSWORD\") { \"postgres\" } %>\n  pool: <%= ENV.fetch(\"RAILS_MAX_THREADS\") { 5 } %>\n\ntest:\n  <<: *default\n  host: postgres_test\n  database: test\n\ndevelopment:\n  <<: *default\n  host: postgres_dummy\n  database: dummy\n\nstaging:\n  <<: *default\n  database: staging\n\nproduction:\n  <<: *default\n  database: production\n"
  },
  {
    "path": "spec/dummy/config/environment.rb",
    "content": "# Load the Rails application.\nrequire_relative 'application'\n\n# Initialize the Rails application.\nRails.application.initialize!\n"
  },
  {
    "path": "spec/dummy/config/environments/development.rb",
    "content": "Rails.application.configure do\n  # Verifies that versions and hashed value of the package contents in the project's package.json\n  config.webpacker.check_yarn_integrity = true\n  # Settings specified here will take precedence over those in config/application.rb.\n\n  # In the development environment your application's code is reloaded on\n  # every request. This slows down response time but is perfect for development\n  # since you don't have to restart the web server when you make code changes.\n  config.cache_classes = false\n\n  # Do not eager load code on boot.\n  config.eager_load = false\n\n  # Show full error reports.\n  config.consider_all_requests_local = true\n\n  # Enable/disable caching. By default caching is disabled.\n  # Run rails dev:cache to toggle caching.\n  if Rails.root.join('tmp', 'caching-dev.txt').exist?\n    config.action_controller.perform_caching = true\n\n    config.cache_store = :memory_store\n    config.public_file_server.headers = {\n      'Cache-Control' => \"public, max-age=#{2.days.to_i}\"\n    }\n  else\n    config.action_controller.perform_caching = false\n\n    config.cache_store = :null_store\n  end\n\n  # Store uploaded files on the local file system (see config/storage.yml for options)\n  config.active_storage.service = :local\n\n  # Don't care if the mailer can't send.\n  config.action_mailer.raise_delivery_errors = false\n\n  config.action_mailer.perform_caching = false\n\n  # Print deprecation notices to the Rails logger.\n  config.active_support.deprecation = :log\n\n  # Raise an error on page load if there are pending migrations.\n  config.active_record.migration_error = :page_load\n\n  # Highlight code that triggered database queries in logs.\n  config.active_record.verbose_query_logs = true\n\n  # Debug mode disables concatenation and preprocessing of assets.\n  # This option may cause significant delays in view rendering with a large\n  # number of complex assets.\n  # config.assets.debug = true\n\n  # Suppress logger output for asset requests.\n  # config.assets.quiet = true\n\n  # Raises error for missing translations\n  # config.action_view.raise_on_missing_translations = true\n\n  # Use an evented file watcher to asynchronously detect changes in source code,\n  # routes, locales, etc. This feature depends on the listen gem.\n  # config.file_watcher = ActiveSupport::EventedFileUpdateChecker\nend\n"
  },
  {
    "path": "spec/dummy/config/environments/production.rb",
    "content": "Rails.application.configure do\n  # Verifies that versions and hashed value of the package contents in the project's package.json\n  config.webpacker.check_yarn_integrity = false\n  # Settings specified here will take precedence over those in config/application.rb.\n\n  # Code is not reloaded between requests.\n  config.cache_classes = true\n\n  # Eager load code on boot. This eager loads most of Rails and\n  # your application in memory, allowing both threaded web servers\n  # and those relying on copy on write to perform better.\n  # Rake tasks automatically ignore this option for performance.\n  config.eager_load = true\n\n  # Full error reports are disabled and caching is turned on.\n  config.consider_all_requests_local       = false\n  config.action_controller.perform_caching = true\n\n  # Ensures that a master key has been made available in either ENV[\"RAILS_MASTER_KEY\"]\n  # or in config/master.key. This key is used to decrypt credentials (and other encrypted files).\n  # config.require_master_key = true\n\n  # Disable serving static files from the `/public` folder by default since\n  # Apache or NGINX already handles this.\n  config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?\n\n  # Compress JavaScripts and CSS.\n  # config.assets.js_compressor = :uglifier\n  # config.assets.css_compressor = :sass\n\n  # Do not fallback to assets pipeline if a precompiled asset is missed.\n  config.assets.compile = false\n\n  # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb\n\n  # Enable serving of images, stylesheets, and JavaScripts from an asset server.\n  # config.action_controller.asset_host = 'http://assets.example.com'\n\n  # Specifies the header that your server uses for sending files.\n  # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache\n  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX\n\n  # Store uploaded files on the local file system (see config/storage.yml for options)\n  config.active_storage.service = :local\n\n  # Mount Action Cable outside main process or domain\n  # config.action_cable.mount_path = nil\n  # config.action_cable.url = 'wss://example.com/cable'\n  # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\\/\\/example.*/ ]\n\n  # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.\n  # config.force_ssl = true\n\n  # Use the lowest log level to ensure availability of diagnostic information\n  # when problems arise.\n  config.log_level = :debug\n\n  # Prepend all log lines with the following tags.\n  config.log_tags = [ :request_id ]\n\n  # Use a different cache store in production.\n  # config.cache_store = :mem_cache_store\n\n  # Use a real queuing backend for Active Job (and separate queues per environment)\n  # config.active_job.queue_adapter     = :resque\n  # config.active_job.queue_name_prefix = \"dummy_#{Rails.env}\"\n\n  config.action_mailer.perform_caching = false\n\n  # Ignore bad email addresses and do not raise email delivery errors.\n  # Set this to true and configure the email server for immediate delivery to raise delivery errors.\n  # config.action_mailer.raise_delivery_errors = false\n\n  # Enable locale fallbacks for I18n (makes lookups for any locale fall back to\n  # the I18n.default_locale when a translation cannot be found).\n  config.i18n.fallbacks = true\n\n  # Send deprecation notices to registered listeners.\n  config.active_support.deprecation = :notify\n\n  # Use default logging formatter so that PID and timestamp are not suppressed.\n  config.log_formatter = ::Logger::Formatter.new\n\n  # Use a different logger for distributed setups.\n  # require 'syslog/logger'\n  # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name')\n\n  if ENV[\"RAILS_LOG_TO_STDOUT\"].present?\n    logger           = ActiveSupport::Logger.new(STDOUT)\n    logger.formatter = config.log_formatter\n    config.logger    = ActiveSupport::TaggedLogging.new(logger)\n  end\n\n  # Do not dump schema after migrations.\n  config.active_record.dump_schema_after_migration = false\nend\n"
  },
  {
    "path": "spec/dummy/config/environments/test.rb",
    "content": "Rails.application.configure do\n  # Settings specified here will take precedence over those in config/application.rb.\n\n  # The test environment is used exclusively to run your application's\n  # test suite. You never need to work with it otherwise. Remember that\n  # your test database is \"scratch space\" for the test suite and is wiped\n  # and recreated between test runs. Don't rely on the data there!\n  config.cache_classes = true\n\n  # Do not eager load code on boot. This avoids loading your whole application\n  # just for the purpose of running a single test. If you are using a tool that\n  # preloads Rails for running tests, you may have to set it to true.\n  config.eager_load = false\n\n  # Configure public file server for tests with Cache-Control for performance.\n  config.public_file_server.enabled = true\n  config.public_file_server.headers = {\n    'Cache-Control' => \"public, max-age=#{1.hour.to_i}\"\n  }\n\n  # Show full error reports and disable caching.\n  config.consider_all_requests_local       = true\n  config.action_controller.perform_caching = false\n\n  # Raise exceptions instead of rendering exception templates.\n  config.action_dispatch.show_exceptions = true\n\n  # Disable request forgery protection in test environment.\n  config.action_controller.allow_forgery_protection = true\n\n  # Store uploaded files on the local file system in a temporary directory\n  config.active_storage.service = :test\n\n  config.action_mailer.perform_caching = false\n\n  # Tell Action Mailer not to deliver emails to the real world.\n  # The :test delivery method accumulates sent emails in the\n  # ActionMailer::Base.deliveries array.\n  config.action_mailer.delivery_method = :test\n\n  # Print deprecation notices to the stderr.\n  config.active_support.deprecation = :stderr\n\n  # Raises error for missing translations\n  # config.action_view.raise_on_missing_translations = true\nend\n"
  },
  {
    "path": "spec/dummy/config/initializers/application_controller_renderer.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# ActiveSupport::Reloader.to_prepare do\n#   ApplicationController.renderer.defaults.merge!(\n#     http_host: 'example.org',\n#     https: false\n#   )\n# end\n"
  },
  {
    "path": "spec/dummy/config/initializers/assets.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Version of your assets, change this if you want to expire all your assets.\n# Rails.application.config.assets.version = '1.0'\n#\n# # Add additional assets to the asset load path.\n# # Rails.application.config.assets.paths << Emoji.images_path\n# # Add Yarn node_modules folder to the asset load path.\n# Rails.application.config.assets.paths << Rails.root.join('node_modules')\n# Rails.application.config.assets.paths << Rails.root.join('app/matestack/components')\n#\n# # Precompile additional assets.\n# # application.js, application.css, and all non-JS/CSS in the app/assets\n# # folder are already added.\n# Rails.application.config.assets.precompile += %w( application.js application_with_turbolinks.js )\n"
  },
  {
    "path": "spec/dummy/config/initializers/backtrace_silencers.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.\n# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }\n\n# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.\n# Rails.backtrace_cleaner.remove_silencers!\n"
  },
  {
    "path": "spec/dummy/config/initializers/content_security_policy.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Define an application-wide content security policy\n# For further information see the following documentation\n# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy\n\n# Rails.application.config.content_security_policy do |policy|\n#   policy.default_src :self, :https\n#   policy.font_src    :self, :https, :data\n#   policy.img_src     :self, :https, :data\n#   policy.object_src  :none\n#   policy.script_src  :self, :https\n#   policy.style_src   :self, :https\n\n#   # Specify URI for violation reports\n#   # policy.report_uri \"/csp-violation-report-endpoint\"\n# end\n\n# If you are using UJS then enable automatic nonce generation\n# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }\n\n# Report CSP violations to a specified URI\n# For further information see the following documentation:\n# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only\n# Rails.application.config.content_security_policy_report_only = true\n"
  },
  {
    "path": "spec/dummy/config/initializers/cookies_serializer.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Specify a serializer for the signed and encrypted cookie jars.\n# Valid options are :json, :marshal, and :hybrid.\nRails.application.config.action_dispatch.cookies_serializer = :json\n"
  },
  {
    "path": "spec/dummy/config/initializers/filter_parameter_logging.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Configure sensitive parameters which will be filtered from the log file.\nRails.application.config.filter_parameters += [:password]\n"
  },
  {
    "path": "spec/dummy/config/initializers/inflections.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Add new inflection rules using the following format. Inflections\n# are locale specific, and you may define rules for as many different\n# locales as you wish. All of these examples are active by default:\n# ActiveSupport::Inflector.inflections(:en) do |inflect|\n#   inflect.plural /^(ox)$/i, '\\1en'\n#   inflect.singular /^(ox)en/i, '\\1'\n#   inflect.irregular 'person', 'people'\n#   inflect.uncountable %w( fish sheep )\n# end\n\n# These inflection rules are supported but not enabled by default:\n# ActiveSupport::Inflector.inflections(:en) do |inflect|\n#   inflect.acronym 'RESTful'\n# end\n"
  },
  {
    "path": "spec/dummy/config/initializers/matestack.rb",
    "content": "# Matestack::Ui::Core::Component::Registry.register_component(:my_card, Components::Card)\n"
  },
  {
    "path": "spec/dummy/config/initializers/mime_types.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# Add new mime types for use in respond_to blocks:\n# Mime::Type.register \"text/richtext\", :rtf\n"
  },
  {
    "path": "spec/dummy/config/initializers/nested_attrs_error_index_patch.rb",
    "content": "# Support propper mapping of errors on existing nested models in nested forms\n# https://github.com/rails/rails/issues/24390#issuecomment-703708842\n\nmodule ActiveRecord\n  module AutosaveAssociation\n    def validate_collection_association(reflection)\n      if association = association_instance_get(reflection.name)\n        if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave])\n          all_records = association.target.find_all\n          records.each do |record|\n            index = all_records.find_index(record)\n            association_valid?(reflection, record, index)\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/dummy/config/initializers/wrap_parameters.rb",
    "content": "# Be sure to restart your server when you modify this file.\n\n# This file contains settings for ActionController::ParamsWrapper which\n# is enabled by default.\n\n# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.\nActiveSupport.on_load(:action_controller) do\n  wrap_parameters format: [:json]\nend\n\n# To enable root element in JSON for ActiveRecord objects.\n# ActiveSupport.on_load(:active_record) do\n#   self.include_root_in_json = true\n# end\n"
  },
  {
    "path": "spec/dummy/config/locales/en.yml",
    "content": "# Files in the config/locales directory are used for internationalization\n# and are automatically loaded by Rails. If you want to use locales other\n# than English, add the necessary files in this directory.\n#\n# To use the locales, use `I18n.t`:\n#\n#     I18n.t 'hello'\n#\n# In views, this is aliased to just `t`:\n#\n#     <%= t('hello') %>\n#\n# To use a different locale, set it with `I18n.locale`:\n#\n#     I18n.locale = :es\n#\n# This would use the information in config/locales/es.yml.\n#\n# The following keys must be escaped otherwise they will not be retrieved by\n# the default I18n backend:\n#\n# true, false, on, off, yes, no\n#\n# Instead, surround them with single quotes.\n#\n# en:\n#   'true': 'foo'\n#\n# To learn more, please read the Rails Internationalization guide\n# available at http://guides.rubyonrails.org/i18n.html.\n\nen:\n  hello: \"Hello world\"\n"
  },
  {
    "path": "spec/dummy/config/puma.rb",
    "content": "# Puma can serve each request in a thread from an internal thread pool.\n# The `threads` method setting takes two numbers: a minimum and maximum.\n# Any libraries that use thread pools should be configured to match\n# the maximum value specified for Puma. Default is set to 5 threads for minimum\n# and maximum; this matches the default thread size of Active Record.\n#\nthreads_count = ENV.fetch(\"RAILS_MAX_THREADS\") { 5 }\nthreads threads_count, threads_count\n\n# Specifies the `port` that Puma will listen on to receive requests; default is 3000.\n#\nport        ENV.fetch(\"PORT\") { 3000 }\n\n# Specifies the `environment` that Puma will run in.\n#\nenvironment ENV.fetch(\"RAILS_ENV\") { \"development\" }\n\n# Specifies the number of `workers` to boot in clustered mode.\n# Workers are forked webserver processes. If using threads and workers together\n# the concurrency of the application would be max `threads` * `workers`.\n# Workers do not work on JRuby or Windows (both of which do not support\n# processes).\n#\n# workers ENV.fetch(\"WEB_CONCURRENCY\") { 2 }\n\n# Use the `preload_app!` method when specifying a `workers` number.\n# This directive tells Puma to first boot the application and load code\n# before forking the application. This takes advantage of Copy On Write\n# process behavior so workers use less memory.\n#\n# preload_app!\n\n# Allow puma to be restarted by `rails restart` command.\nplugin :tmp_restart\n"
  },
  {
    "path": "spec/dummy/config/routes.rb",
    "content": "Rails.application.routes.draw do\n\n  root to: 'demo_core#first'\n\n  scope :demo do\n    scope :core do\n      get :first, to: 'demo_core#first', as: :demo_core_first_page\n      get :second, to: 'demo_core#second', as: :demo_core_second_page\n    end\n  end\n\nend\n"
  },
  {
    "path": "spec/dummy/config/spring.rb",
    "content": "%w[\n  .ruby-version\n  .rbenv-vars\n  tmp/restart.txt\n  tmp/caching-dev.txt\n].each { |path| Spring.watch(path) }\n"
  },
  {
    "path": "spec/dummy/config/storage.yml",
    "content": "test:\n  service: Disk\n  root: <%= Rails.root.join(\"tmp/storage\") %>\n\nlocal:\n  service: Disk\n  root: <%= Rails.root.join(\"storage\") %>\n\n# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key)\n# amazon:\n#   service: S3\n#   access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>\n#   secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>\n#   region: us-east-1\n#   bucket: your_own_bucket\n\n# Remember not to checkin your GCS keyfile to a repository\n# google:\n#   service: GCS\n#   project: your_project\n#   credentials: <%= Rails.root.join(\"path/to/gcs.keyfile\") %>\n#   bucket: your_own_bucket\n\n# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key)\n# microsoft:\n#   service: AzureStorage\n#   storage_account_name: your_account_name\n#   storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %>\n#   container: your_container_name\n\n# mirror:\n#   service: Mirror\n#   primary: local\n#   mirrors: [ amazon, google, microsoft ]\n"
  },
  {
    "path": "spec/dummy/config/webpack/development.js",
    "content": "process.env.NODE_ENV = process.env.NODE_ENV || 'development'\n\nconst environment = require('./environment')\n\nmodule.exports = environment.toWebpackConfig()\n"
  },
  {
    "path": "spec/dummy/config/webpack/environment.js",
    "content": "const { environment } = require('@rails/webpacker')\n\nmodule.exports = environment\n"
  },
  {
    "path": "spec/dummy/config/webpack/production.js",
    "content": "process.env.NODE_ENV = process.env.NODE_ENV || 'production'\n\nconst environment = require('./environment')\n\nmodule.exports = environment.toWebpackConfig()\n"
  },
  {
    "path": "spec/dummy/config/webpack/test.js",
    "content": "process.env.NODE_ENV = process.env.NODE_ENV || 'development'\n\nconst environment = require('./environment')\n\nmodule.exports = environment.toWebpackConfig()\n"
  },
  {
    "path": "spec/dummy/config/webpacker.yml",
    "content": "# Note: You must restart bin/webpack-dev-server for changes to take effect\n\ndefault: &default\n  source_path: app/javascript\n  source_entry_path: packs\n  public_output_path: packs\n  cache_path: tmp/cache/webpacker\n\n  # Additional paths webpack should lookup modules\n  # ['app/assets', 'engine/foo/app/assets']\n  additional_paths: ['node_modules']\n\n  # Reload manifest.json on all requests so we reload latest compiled packs\n  cache_manifest: false\n\n  extensions:\n    - .js\n    - .sass\n    - .scss\n    - .css\n    - .module.sass\n    - .module.scss\n    - .module.css\n    - .png\n    - .svg\n    - .gif\n    - .jpeg\n    - .jpg\n\ndevelopment:\n  <<: *default\n  compile: true\n\n  # Reference: https://webpack.js.org/configuration/dev-server/\n  dev_server:\n    https: false\n    host: localhost\n    port: 3035\n    public: localhost:3035\n    hmr: false\n    # Inline should be set to true if using HMR\n    inline: true\n    overlay: true\n    compress: true\n    disable_host_check: true\n    use_local_ip: false\n    quiet: false\n    headers:\n      'Access-Control-Allow-Origin': '*'\n    watch_options:\n      ignored: /node_modules/\n\n\ntest:\n  <<: *default\n  compile: true\n\n  # Compile test packs to a separate directory\n  public_output_path: packs-test\n\nproduction:\n  <<: *default\n\n  # Production depends on precompilation of packs prior to booting for performance.\n  compile: false\n\n  # Cache manifest.json for performance\n  cache_manifest: true\n"
  },
  {
    "path": "spec/dummy/config.ru",
    "content": "# This file is used by Rack-based servers to start the application.\n\nrequire_relative 'config/environment'\n\nrun Rails.application\n"
  },
  {
    "path": "spec/dummy/db/migrate/20190419174203_create_test_models.rb",
    "content": "class CreateTestModels < ActiveRecord::Migration[5.2]\n  def change\n    create_table :test_models do |t|\n      t.string :title\n      t.text :description\n      t.integer :status\n      t.text :some_data\n      t.text :more_data\n\n      t.timestamps\n    end\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/migrate/20190427134012_create_dummy_models.rb",
    "content": "class CreateDummyModels < ActiveRecord::Migration[5.2]\n  def change\n    create_table :dummy_models do |t|\n      t.string :title\n      t.text :description\n      t.integer :status\n      t.text :some_data\n      t.text :more_data\n\n      t.timestamps\n    end\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/migrate/20190908153924_create_dummy_child_models.rb",
    "content": "class CreateDummyChildModels < ActiveRecord::Migration[5.2]\n  def change\n    create_table :dummy_child_models do |t|\n      t.string :title\n      t.text :description\n      t.integer :status\n      t.text :some_data\n      t.text :more_data\n\n      t.timestamps\n    end\n    add_reference :dummy_child_models, :dummy_model, foreign_key: true\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/migrate/20200427170812_create_active_storage_tables.active_storage.rb",
    "content": "# This migration comes from active_storage (originally 20170806125915)\nclass CreateActiveStorageTables < ActiveRecord::Migration[5.2]\n  def change\n    create_table :active_storage_blobs do |t|\n      t.string   :key,        null: false\n      t.string   :filename,   null: false\n      t.string   :content_type\n      t.text     :metadata\n      t.bigint   :byte_size,  null: false\n      t.string   :checksum,   null: false\n      t.datetime :created_at, null: false\n\n      t.index [ :key ], unique: true\n    end\n\n    create_table :active_storage_attachments do |t|\n      t.string     :name,     null: false\n      t.references :record,   null: false, polymorphic: true, index: false\n      t.references :blob,     null: false\n\n      t.datetime :created_at, null: false\n\n      t.index [ :record_type, :record_id, :name, :blob_id ], name: \"index_active_storage_attachments_uniqueness\", unique: true\n      t.foreign_key :active_storage_blobs, column: :blob_id\n    end\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/migrate/20201222161321_add_boolean_value_to_test_models.rb",
    "content": "class AddBooleanValueToTestModels < ActiveRecord::Migration[5.2]\n  def change\n    add_column :test_models, :some_boolean_value, :boolean\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/migrate/20210204135043_add_service_name_to_active_storage_blobs.active_storage.rb",
    "content": "# This migration comes from active_storage (originally 20190112182829)\nif Rails::VERSION::MAJOR >= 6 && Rails::VERSION::MINOR >= 1\n  class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0]\n    def up\n      unless column_exists?(:active_storage_blobs, :service_name)\n        add_column :active_storage_blobs, :service_name, :string\n\n        if configured_service = ActiveStorage::Blob.service.name\n          ActiveStorage::Blob.unscoped.update_all(service_name: configured_service)\n        end\n\n        change_column :active_storage_blobs, :service_name, :string, null: false\n      end\n    end\n\n    def down\n      remove_column :active_storage_blobs, :service_name\n    end\n  end\nelse\n  class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[5.2]\n    def up\n\n    end\n\n    def down\n\n    end\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/migrate/20210204135044_create_active_storage_variant_records.active_storage.rb",
    "content": "# This migration comes from active_storage (originally 20191206030411)\nif Rails::VERSION::MAJOR >= 6 && Rails::VERSION::MINOR >= 1\n  class CreateActiveStorageVariantRecords < ActiveRecord::Migration[6.0]\n    def change\n      create_table :active_storage_variant_records do |t|\n        t.belongs_to :blob, null: false, index: false\n        t.string :variation_digest, null: false\n\n        t.index %i[ blob_id variation_digest ], name: \"index_active_storage_variant_records_uniqueness\", unique: true\n        t.foreign_key :active_storage_blobs, column: :blob_id\n      end\n    end\n  end\nelse\n  class CreateActiveStorageVariantRecords < ActiveRecord::Migration[5.2]\n    def change\n      \n    end\n  end\nend\n"
  },
  {
    "path": "spec/dummy/db/schema.rb",
    "content": "# This file is auto-generated from the current state of the database. Instead\n# of editing this file, please use the migrations feature of Active Record to\n# incrementally modify your database, and then regenerate this schema definition.\n#\n# This file is the source Rails uses to define your schema when running `bin/rails\n# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to\n# be faster and is potentially less error prone than running all of your\n# migrations from scratch. Old migrations may fail to apply correctly if those\n# migrations use external dependencies or application code.\n#\n# It's strongly recommended that you check this file into your version control system.\n\nActiveRecord::Schema.define(version: 2021_02_04_135044) do\n\n  # These are extensions that must be enabled in order to support this database\n  enable_extension \"plpgsql\"\n\n  create_table \"active_storage_attachments\", force: :cascade do |t|\n    t.string \"name\", null: false\n    t.string \"record_type\", null: false\n    t.bigint \"record_id\", null: false\n    t.bigint \"blob_id\", null: false\n    t.datetime \"created_at\", null: false\n    t.index [\"blob_id\"], name: \"index_active_storage_attachments_on_blob_id\"\n    t.index [\"record_type\", \"record_id\", \"name\", \"blob_id\"], name: \"index_active_storage_attachments_uniqueness\", unique: true\n  end\n\n  create_table \"active_storage_blobs\", force: :cascade do |t|\n    t.string \"key\", null: false\n    t.string \"filename\", null: false\n    t.string \"content_type\"\n    t.text \"metadata\"\n    t.bigint \"byte_size\", null: false\n    t.string \"checksum\", null: false\n    t.datetime \"created_at\", null: false\n    t.string \"service_name\", null: false\n    t.index [\"key\"], name: \"index_active_storage_blobs_on_key\", unique: true\n  end\n\n  create_table \"active_storage_variant_records\", force: :cascade do |t|\n    t.bigint \"blob_id\", null: false\n    t.string \"variation_digest\", null: false\n    t.index [\"blob_id\", \"variation_digest\"], name: \"index_active_storage_variant_records_uniqueness\", unique: true\n  end\n\n  create_table \"dummy_child_models\", force: :cascade do |t|\n    t.string \"title\"\n    t.text \"description\"\n    t.integer \"status\"\n    t.text \"some_data\"\n    t.text \"more_data\"\n    t.datetime \"created_at\", null: false\n    t.datetime \"updated_at\", null: false\n    t.bigint \"dummy_model_id\"\n    t.index [\"dummy_model_id\"], name: \"index_dummy_child_models_on_dummy_model_id\"\n  end\n\n  create_table \"dummy_models\", force: :cascade do |t|\n    t.string \"title\"\n    t.text \"description\"\n    t.integer \"status\"\n    t.text \"some_data\"\n    t.text \"more_data\"\n    t.datetime \"created_at\", null: false\n    t.datetime \"updated_at\", null: false\n  end\n\n  create_table \"test_models\", force: :cascade do |t|\n    t.string \"title\"\n    t.text \"description\"\n    t.integer \"status\"\n    t.text \"some_data\"\n    t.text \"more_data\"\n    t.datetime \"created_at\", null: false\n    t.datetime \"updated_at\", null: false\n    t.boolean \"some_boolean_value\"\n  end\n\n  add_foreign_key \"active_storage_attachments\", \"active_storage_blobs\", column: \"blob_id\"\n  add_foreign_key \"active_storage_variant_records\", \"active_storage_blobs\", column: \"blob_id\"\n  add_foreign_key \"dummy_child_models\", \"dummy_models\"\nend\n"
  },
  {
    "path": "spec/dummy/lib/assets/.keep",
    "content": ""
  },
  {
    "path": "spec/dummy/log/.keep",
    "content": ""
  },
  {
    "path": "spec/dummy/package.json",
    "content": "{\n  \"name\": \"dummy\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@babel/preset-env\": \"^7.16.7\",\n    \"@hotwired/turbo-rails\": \"^7.1.1\",\n    \"@rails/actioncable\": \"^6.0.0\",\n    \"@rails/ujs\": \"^6.0.0\",\n    \"@rails/webpacker\": \"^5.0.0\"\n  },\n  \"devDependencies\": {\n    \"webpack-dev-server\": \"^3.10.2\"\n  },\n  \"browserslist\": [\n    \"defaults\",\n    \"not IE 11\"\n  ]\n}\n"
  },
  {
    "path": "spec/dummy/postcss.config.js",
    "content": "module.exports = {\n  plugins: [\n    require('postcss-import'),\n    require('postcss-flexbugs-fixes'),\n    require('postcss-preset-env')({\n      autoprefixer: {\n        flexbox: 'no-2009'\n      },\n      stage: 3\n    })\n  ]\n}\n"
  },
  {
    "path": "spec/dummy/public/404.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>The page you were looking for doesn't exist (404)</title>\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n  <style>\n  .rails-default-error-page {\n    background-color: #EFEFEF;\n    color: #2E2F30;\n    text-align: center;\n    font-family: arial, sans-serif;\n    margin: 0;\n  }\n\n  .rails-default-error-page div.dialog {\n    width: 95%;\n    max-width: 33em;\n    margin: 4em auto 0;\n  }\n\n  .rails-default-error-page div.dialog > div {\n    border: 1px solid #CCC;\n    border-right-color: #999;\n    border-left-color: #999;\n    border-bottom-color: #BBB;\n    border-top: #B00100 solid 4px;\n    border-top-left-radius: 9px;\n    border-top-right-radius: 9px;\n    background-color: white;\n    padding: 7px 12% 0;\n    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);\n  }\n\n  .rails-default-error-page h1 {\n    font-size: 100%;\n    color: #730E15;\n    line-height: 1.5em;\n  }\n\n  .rails-default-error-page div.dialog > p {\n    margin: 0 0 1em;\n    padding: 1em;\n    background-color: #F7F7F7;\n    border: 1px solid #CCC;\n    border-right-color: #999;\n    border-left-color: #999;\n    border-bottom-color: #999;\n    border-bottom-left-radius: 4px;\n    border-bottom-right-radius: 4px;\n    border-top-color: #DADADA;\n    color: #666;\n    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);\n  }\n  </style>\n</head>\n\n<body class=\"rails-default-error-page\">\n  <!-- This file lives in public/404.html -->\n  <div class=\"dialog\">\n    <div>\n      <h1>The page you were looking for doesn't exist.</h1>\n      <p>You may have mistyped the address or the page may have moved.</p>\n    </div>\n    <p>If you are the application owner check the logs for more information.</p>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "spec/dummy/public/422.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>The change you wanted was rejected (422)</title>\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n  <style>\n  .rails-default-error-page {\n    background-color: #EFEFEF;\n    color: #2E2F30;\n    text-align: center;\n    font-family: arial, sans-serif;\n    margin: 0;\n  }\n\n  .rails-default-error-page div.dialog {\n    width: 95%;\n    max-width: 33em;\n    margin: 4em auto 0;\n  }\n\n  .rails-default-error-page div.dialog > div {\n    border: 1px solid #CCC;\n    border-right-color: #999;\n    border-left-color: #999;\n    border-bottom-color: #BBB;\n    border-top: #B00100 solid 4px;\n    border-top-left-radius: 9px;\n    border-top-right-radius: 9px;\n    background-color: white;\n    padding: 7px 12% 0;\n    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);\n  }\n\n  .rails-default-error-page h1 {\n    font-size: 100%;\n    color: #730E15;\n    line-height: 1.5em;\n  }\n\n  .rails-default-error-page div.dialog > p {\n    margin: 0 0 1em;\n    padding: 1em;\n    background-color: #F7F7F7;\n    border: 1px solid #CCC;\n    border-right-color: #999;\n    border-left-color: #999;\n    border-bottom-color: #999;\n    border-bottom-left-radius: 4px;\n    border-bottom-right-radius: 4px;\n    border-top-color: #DADADA;\n    color: #666;\n    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);\n  }\n  </style>\n</head>\n\n<body class=\"rails-default-error-page\">\n  <!-- This file lives in public/422.html -->\n  <div class=\"dialog\">\n    <div>\n      <h1>The change you wanted was rejected.</h1>\n      <p>Maybe you tried to change something you didn't have access to.</p>\n    </div>\n    <p>If you are the application owner check the logs for more information.</p>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "spec/dummy/public/500.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <title>We're sorry, but something went wrong (500)</title>\n  <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n  <style>\n  .rails-default-error-page {\n    background-color: #EFEFEF;\n    color: #2E2F30;\n    text-align: center;\n    font-family: arial, sans-serif;\n    margin: 0;\n  }\n\n  .rails-default-error-page div.dialog {\n    width: 95%;\n    max-width: 33em;\n    margin: 4em auto 0;\n  }\n\n  .rails-default-error-page div.dialog > div {\n    border: 1px solid #CCC;\n    border-right-color: #999;\n    border-left-color: #999;\n    border-bottom-color: #BBB;\n    border-top: #B00100 solid 4px;\n    border-top-left-radius: 9px;\n    border-top-right-radius: 9px;\n    background-color: white;\n    padding: 7px 12% 0;\n    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);\n  }\n\n  .rails-default-error-page h1 {\n    font-size: 100%;\n    color: #730E15;\n    line-height: 1.5em;\n  }\n\n  .rails-default-error-page div.dialog > p {\n    margin: 0 0 1em;\n    padding: 1em;\n    background-color: #F7F7F7;\n    border: 1px solid #CCC;\n    border-right-color: #999;\n    border-left-color: #999;\n    border-bottom-color: #999;\n    border-bottom-left-radius: 4px;\n    border-bottom-right-radius: 4px;\n    border-top-color: #DADADA;\n    color: #666;\n    box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);\n  }\n  </style>\n</head>\n\n<body class=\"rails-default-error-page\">\n  <!-- This file lives in public/500.html -->\n  <div class=\"dialog\">\n    <div>\n      <h1>We're sorry, but something went wrong.</h1>\n    </div>\n    <p>If you are the application owner check the logs for more information.</p>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "spec/rails_core_spec_helper.rb",
    "content": "# This file is copied to spec/ when you run 'rails generate rspec:install'\nrequire 'core_spec_helper'\nENV['RAILS_ENV'] ||= 'test'\n# require File.expand_path('../../config/environment', __dir__)\n# Prevent database truncation if the environment is production\nabort(\"The Rails environment is running in production mode!\") if Rails.env.production?\nrequire 'rspec/rails'\n\n# Add additional requires below this line. Rails is not loaded until this point!\n# Requires supporting ruby files with custom matchers and macros, etc, in\n# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are\n# run as spec files by default. This means that files in spec/support that end\n# in _spec.rb will both be required and run as specs, causing the specs to be\n# run twice. It is recommended that you do not name files matching this glob to\n# end with _spec.rb. You can configure this pattern with the --pattern\n# option on the command line or in ~/.rspec, .rspec or `.rspec-local`.\n#\n# The following line is provided for convenience purposes. It has the downside\n# of increasing the boot-up time by auto-requiring all files in the support\n# directory. Alternatively, in the individual `*_spec.rb` files, manually\n# require only the support files necessary.\n#\n# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }\n\n# Checks for pending migrations and applies them before tests are run.\n# If you are not using ActiveRecord, you can remove these lines.\nActiveRecord::Migrator.migrations_paths = [File.expand_path(\"../spec/dummy/db/migrate\", __dir__)]\nActiveRecord::Migrator.migrations_paths << File.expand_path('../db/migrate', __dir__)\nbegin\n  ActiveRecord::Migration.maintain_test_schema!\nrescue ActiveRecord::PendingMigrationError => e\n  puts e.to_s.strip\n  exit 1\nend\nRSpec.configure do |config|\n  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures\n  config.fixture_path = \"#{::Rails.root}/spec/fixtures\"\n\n  # If you're not using ActiveRecord, or you'd prefer not to run each of your\n  # examples within a transaction, remove the following line or assign false\n  # instead of true.\n  config.use_transactional_fixtures = true\n\n  # RSpec Rails can automatically mix in different behaviors to your tests\n  # based on their file location, for example enabling you to call `get` and\n  # `post` in specs under `spec/controllers`.\n  #\n  # You can disable this behavior by removing the line below, and instead\n  # explicitly tag your specs with their type, e.g.:\n  #\n  #     RSpec.describe UsersController, :type => :controller do\n  #       # ...\n  #     end\n  #\n  # The different available types are documented in the features, such as in\n  # https://relishapp.com/rspec/rspec-rails/docs\n  config.infer_spec_type_from_file_location!\n\n  # Filter lines from Rails gems in backtraces.\n  config.filter_rails_from_backtrace!\n  # arbitrary gems may also be filtered via:\n  # config.filter_gems_from_backtrace(\"gem name\")\nend\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "# file need to exist, otherwise specs will fail!\n"
  },
  {
    "path": "spec/test/core/base/component/argument_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class ComponentTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_argument_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"Argument\" do\n\n    it \"a component can access a simple argument, if no hash was given\" do\n\n      class SomeStaticComponent < Matestack::Ui::Component\n\n        def response\n          div id: \"my-component\" do\n            plain self.text\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            some_static_component \"foo from page\"\n          end\n        end\n\n      end\n\n      visit \"component_argument_spec/component_test\"\n\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"foo from page\")]')\n\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/conditional_rendering_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n      layout \"application_core\"\n\n      def my_action\n        render ExamplePage\n      end\n    end\n\n    Rails.application.routes.append do\n      scope \"component_conditional_rendering_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'conditional_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  describe \"conditional component\" do\n\n    it \"renders by default if '.render?' method is not overrided\" do\n      class DefaultRenderingComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            plain \"default rendering component\"\n          end\n        end\n\n      register_self_as(:default_rendering_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            default_rendering_component\n          end\n        end\n      end\n\n      visit \"component_conditional_rendering_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"default rendering component\")]')\n    end\n\n    it \"renders if '.render?' method is overrided and returns true\" do\n      class ConditionalRenderingComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            plain \"conditional rendering component\"\n          end\n        end\n\n        def render?\n          true\n        end\n\n      register_self_as(:conditional_rendering_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            conditional_rendering_component\n          end\n        end\n      end\n\n      visit \"component_conditional_rendering_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"conditional rendering component\")]')\n    end\n\n    it \"doesn't render if '.render?' method is overrided and returns false\" do\n      class ConditionalRenderingComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            plain \"conditional rendering component\"\n          end\n        end\n\n        def render?\n          false\n        end\n\n      register_self_as(:conditional_rendering_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            conditional_rendering_component\n          end\n        end\n      end\n\n      visit \"component_conditional_rendering_spec/component_test\"\n      expect(page).to_not have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"conditional rendering component\")]')\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/core_namespaces_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    module Components end\n\n    module Pages end\n\n    module Matestack::Ui::Core end\n\n    class ComponentTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render Pages::ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_core_namespaces_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'namespace_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"CORE component naming and namespaces\" do\n\n    it \"CORE components are resolved regarding the component registration\" do\n\n      #creating the namespace which is represented by \"CORE_ROOT/app/concepts/matestack/ui/core/component1\"\n      module Matestack::Ui::Core::Component1 \n      end\n\n      #defined in CORE_ROOT/app/concepts/matestack/ui/core/component1/component1.rb\n      class Matestack::Ui::Core::Component1::Component1 < Matestack::Ui::Component\n        def response\n          div id: \"core-component-1\" do\n            plain \"static component 1\"\n          end\n        end\n\n        register_self_as(:some_core_component)\n      end\n\n      #defined in CORE_ROOT/app/concepts/matestack/ui/core/component1/component2.rb\n      class Matestack::Ui::Core::Component1::Component2 < Matestack::Ui::Component\n        def response\n          div id: \"core-component-2\" do\n            plain \"static component 2\"\n          end\n        end\n\n        register_self_as(:some_other_core_component)\n      end\n\n      #defined in CORE_ROOT/app/concepts/matestack/ui/core/component1/component2.rb\n      class Matestack::Ui::Core::Component1::ThirdComponent < Matestack::Ui::Component\n        def response\n          div id: \"core-component-3\" do\n            plain \"static component 3\"\n          end\n        end\n\n        register_self_as(:third_core_component)\n      end\n\n      class Pages::ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            some_core_component\n            some_other_core_component\n            third_core_component\n            begin\n              component1\n            rescue\n              plain \"component1 can not be resolved as there is no more magic class discovery\"\n            end\n            begin\n              component1_component2\n            rescue\n              plain \"component1_component2 can not be resolved as there is no more magic class discovery\"\n            end\n            begin\n              component1_thirdComponent\n            rescue\n              plain \"component1_thirdComponent can not be resolved as there is no more magic class discovery\"\n            end\n          end\n        end\n      end\n\n      visit \"component_core_namespaces_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"core-component-1\" and contains(.,\"static component 1\")]')\n      expect(page).to have_content('component1 can not be resolved as there is no more magic class discovery')\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"core-component-2\" and contains(.,\"static component 2\")]')\n      expect(page).to have_content('component1_component2 can not be resolved as there is no more magic class discovery')\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"core-component-3\" and contains(.,\"static component 3\")]')\n      expect(page).to have_content('component1_thirdComponent can not be resolved as there is no more magic class discovery')\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/custom_namespaces_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    module Components end\n\n    module Pages end\n\n    module Matestack::Ui::Core end\n\n    class ComponentTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render Pages::ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_custom_namespaces_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'custom_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  # TODO: their whole naming is also not relevant/true anymore\n  describe \"CUSTOM component naming and namespaces\" do\n\n    it \"CUSTOM components are resolved regarding the component registration\" do\n\n      #creating the namespace which is represented by \"APP_ROOT/app/matestack/components\"\n      module Components end\n\n      #defined in \"APP_ROOT/app/matestack/components/component1.rb\n      class Components::Component1 < Matestack::Ui::Component\n\n        def response\n          div id: \"my-component-1\" do\n            plain \"my first component\"\n          end\n        end\n\n        register_self_as(:my_first_component)\n      end\n\n      #creating the namespace which is represented by \"APP_ROOT/app/matestack/components/namespace1\"\n      module Components::Namespace1 end\n\n      #defined in \"APP_ROOT/app/matestack/components/namespace1/component1.rb\n      class Components::Namespace1::Component1 < Matestack::Ui::Component\n\n        def response\n          div id: \"my-namespaced-component-1\" do\n            plain \"namespaced custom static component\"\n          end\n        end\n\n        register_self_as(:my_namespaced_component)\n\n      end\n\n      #defined in \"APP_ROOT/app/matestack/components/component1.rb\n      class Components::MyCamelcasedClassNameComponent < Matestack::Ui::Component\n\n        def response\n          div id: \"my-camelcased-class-name-component\" do\n            plain \"camelcased class name component\"\n          end\n        end\n\n        register_self_as(:my_camelcased_class_name_component)\n      end\n\n      class Pages::ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            my_first_component\n            my_namespaced_component\n            my_camelcased_class_name_component\n          end\n          begin\n            custom_component1\n          rescue\n            plain \"custom_component1 can not be resolved as there is no more magic class discovery\"\n          end\n          begin\n            custom_namespace1_component1\n          rescue\n            plain \"custom_namespace1_component1 can not be resolved as there is no more magic class discovery\"\n          end\n          begin\n            custom_myCamelcasedClassNameComponent\n          rescue\n            plain \"custom_myCamelcasedClassNameComponent can not be resolved as there is no more magic class discovery\"\n          end\n        end\n\n      end\n\n      visit \"component_custom_namespaces_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component-1\" and contains(.,\"my first component\")]')\n      expect(page).to have_content('custom_component1 can not be resolved as there is no more magic class discovery')\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-namespaced-component-1\" and contains(.,\"namespaced custom static component\")]')\n      expect(page).to have_content('custom_namespace1_component1 can not be resolved as there is no more magic class discovery')\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-camelcased-class-name-component\" and contains(.,\"camelcased class name component\")]')\n      expect(page).to have_content('custom_myCamelcasedClassNameComponent can not be resolved as there is no more magic class discovery')\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/options_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class ComponentTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_options_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'options_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"Options\" do\n\n    it \"components can take an options hash\" do\n\n      class SomeStaticComponent < Matestack::Ui::Component\n        optional :some_option, :some_other\n        def response\n          div id: \"my-component\" do\n            plain \"got some option: #{ctx.some_option} and some other option: #{ctx.some_other[:option]}\"\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            some_static_component some_option: \"hello!\", some_other: { option: \"world!\" }\n          end\n        end\n\n      end\n\n      visit \"component_options_spec/component_test\"\n\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"got some option: hello! and some other option: world!\")]')\n\n    end\n\n    it \"components can auto validate if options is given and raise error if not\" do\n\n      class SpecialComponent < Matestack::Ui::Component\n\n        required :some_option\n        optional :some_other\n\n        def response\n          div id: \"my-component\" do\n            plain \"got some option: #{ctx.some_option} and some other option: #{ctx.some_other[:option]}\"\n          end\n        end\n\n        register_self_as(:special_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            special_component some_other: { option: \"world!\" }\n          end\n        end\n\n      end\n\n      visit \"component_options_spec/component_test\"\n\n      expect(page).to have_content(\"required property 'some_option' is missing for 'SpecialComponent'\")\n    end\n\n    it \"components can manually validate if given options are correct and raise error if not\"\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/partials_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n      layout \"application_core\"\n\n      def my_action\n        render ExamplePage\n      end\n    end\n\n    Rails.application.routes.append do\n      scope \"component_partials_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'partials_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  describe \"Partials\" do\n\n    it \"components can use local partials to structure their response\" do\n      class SomeStaticComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            my_partial \"foo from component\"\n          end\n        end\n\n        def my_partial text\n          plain text\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            some_static_component\n          end\n        end\n\n      end\n\n      visit \"component_partials_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"foo from component\")]')\n    end\n\n    it \"components can use partials from included modules to structure their response\" do\n      module MySharedPartials\n        def my_partial text\n          plain text\n        end\n      end\n\n      class SomeStaticComponent < Matestack::Ui::Component\n        include MySharedPartials\n\n        def response\n          div id: \"my-component\" do\n            my_partial \"foo from component\"\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            some_static_component\n          end\n        end\n      end\n\n      visit \"component_partials_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"foo from component\")]')\n    end\n\n  end\n\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/prepare_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class ComponentTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_prepare_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'prepare_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"Prepare\" do\n\n    it \"a component can resolve data before rendering in a prepare method\" do\n\n      class SomeStaticComponent < Matestack::Ui::Component\n\n        def prepare\n          @some_data = \"some data\"\n        end\n\n        def response\n          div id: \"my-component\" do\n            plain @some_data\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            some_static_component \"foo from page\"\n          end\n        end\n\n      end\n\n      visit \"component_prepare_spec/component_test\"\n\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"some data\")]')\n\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/properties_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'Properties Mechanism', type: :feature, js: true do\n\n  before :all do\n    class PropertyComponent < Matestack::Ui::Component\n      required :title\n      required :foo\n      optional :description, :bar\n      optional :text\n\n      def response\n        paragraph ctx.title\n        paragraph ctx.foo\n        paragraph ctx.description\n        paragraph ctx.bar\n        paragraph ctx.text\n      end\n\n      register_self_as :property_component\n    end\n  end\n\n  describe 'missing requires' do\n    it 'should raise exception if required property is missing' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          property_component\n        end\n      end\n\n      visit '/example'\n      expect(page).to have_content(\"required property 'title' is missing for 'PropertyComponent'\")\n    end\n\n    it 'should raise exception if other required property is missing' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          property_component title: 'Title'\n        end\n      end\n\n      visit '/example'\n      expect(page).to have_content(\"required property 'foo' is missing for 'PropertyComponent'\")\n    end\n  end\n\n  describe 'defining properties' do\n    it 'should define instance methods for required properties' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          property_component title: 'Title', foo: 'Foo'\n        end\n      end\n      visit '/example'\n      expect(page).to have_content('Title')\n      expect(page).to have_content('Foo')\n      prop_component = PropertyComponent.new(nil, title: 'Title', foo: 'Foo')\n      expect(prop_component.context.respond_to?(:title)).to be(true)\n      expect(prop_component.context.respond_to?(:foo)).to be(true)\n    end\n\n    it 'should define context with instance methods for optional properties' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          property_component title: 'Title', foo: 'Foo', description: 'Description', bar: 'Bar'\n        end\n      end\n      visit '/example'\n      expect(page).to have_content('Description')\n      expect(page).to have_content('Bar')\n      prop_component = PropertyComponent.new(nil, title: 'Title', foo: 'Foo')\n      expect(prop_component.context.respond_to?(:description)).to be(true)\n      expect(prop_component.context.respond_to?(:bar)).to be(true)\n    end\n  end\n\n  it 'should be accesible in prepare' do\n    class SetupComponent < Matestack::Ui::Component\n      required :title, :desc\n      def prepare\n        @foo = ctx.title\n        @bar = ctx.desc\n      end\n      def response\n        plain @foo\n        paragraph @foo\n        paragraph @bar\n      end\n      register_self_as :setup_component\n    end\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        setup_component title: 'Foo', desc: 'Bar'\n      end\n    end\n\n    visit '/example'\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <p>Foo</p>\n      <p>Bar</p>\n    HTML\n    expect(stripped(static_output)).to include(stripped(expected_static_output))\n  end\n\n  it 'should work with slots' do\n    class SlotComponent < Matestack::Ui::Component\n      def response\n        div do\n          slot :first\n          slot :second\n        end\n      end\n      register_self_as :slot_component\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        slot_component slots: { first: method(:some_slot), second: method(:other_slot) }\n      end\n\n      def some_slot\n        paragraph 'Foo'\n      end\n\n      def other_slot\n        paragraph 'bar'\n      end\n    end\n\n    visit '/example'\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div>\n        <p>Foo</p>\n        <p>bar</p>\n      </div>\n    HTML\n    expect(stripped(static_output)).to include(stripped(expected_static_output))\n  end\n\n  it 'should inherit optional attributes' do\n    class Component < Matestack::Ui::Component\n      optional :foobar, :response\n      def response\n      end\n    end\n    class AnotherComponent < Component\n      optional :custom\n    end\n    another_component = AnotherComponent.new(nil, custom: 'hi', foobar: 'foobar', response: 'response')\n    component = Component.new(nil, foobar: 'Foobar', response: 'Response')\n    expect(another_component.context.respond_to? :custom).to be(true)\n    expect(another_component.context.custom).to eq('hi')\n    expect(another_component.context.respond_to? :foobar).to be(true)\n    expect(another_component.context.foobar).to eq('foobar')\n    expect(another_component.context.respond_to? :response).to be(true)\n    expect(another_component.context.response).to eq('response')\n    expect(component.context.respond_to? :foobar).to be(true)\n    expect(component.context.respond_to? :response).to be(true)\n  end\n\n  it 'should inherit required attributes' do\n    class Component < Matestack::Ui::Component\n      required :foobar, :response\n      def response\n      end\n    end\n    class AnotherComponent < Component\n      required :custom2\n    end\n    another_component = AnotherComponent.new(nil, custom2: 'hi', foobar: 'foobar', response: 'response')\n    component = Component.new(nil, foobar: 'Foobar', response: 'Response')\n    expect(another_component.context.respond_to? :custom2).to be(true)\n    expect(another_component.context.custom2).to eq('hi')\n    expect(another_component.context.respond_to? :foobar).to be(true)\n    expect(another_component.context.foobar).to eq('foobar')\n    expect(another_component.context.respond_to? :response).to be(true)\n    expect(another_component.context.response).to eq('response')\n    expect(component.context.respond_to? :foobar).to be(true)\n    expect(component.context.respond_to? :response).to be(true)\n  end\n\n  it 'should do something :D' do\n    class Component2 < Matestack::Ui::Component\n      optional :foobar\n    end\n    class AnotherComponent2 < Component2\n      optional :foobar\n    end\n    another_component = AnotherComponent2.new(nil, foobar: 'another_component')\n    expect(another_component.context.respond_to? :foobar).to be(true)\n    expect(another_component.context.foobar).to eq('another_component')\n    component = Component2.new(nil, foobar: 'component')\n    expect(component.context.respond_to? :foobar).to be(true)\n    expect(component.context.foobar).to eq('component')\n  end\n\n  it 'should create instance method with given alias name for required properties' do\n    class AliasPropertyComponent < Matestack::Ui::Component\n      required method: { as: :my_method }, response: { as: :test }\n      def response\n      end\n    end\n    class AnotherAliasPropertyComponent < Matestack::Ui::Component\n      required :bla, method: { as: :my_method }, response: { as: :test }\n      def response\n      end\n    end\n    component = AliasPropertyComponent.new(nil, method: 'Its my method', response: 'Response')\n    another_component = AnotherAliasPropertyComponent.new(nil, bla: 'hi', method: 'Its my method', response: 'Response')\n    expect(component.context.respond_to? :my_method).to be(true)\n    expect(component.context.my_method).to eq('Its my method')\n    expect(component.context.respond_to? :test).to be(true)\n    expect(component.context.test).to eq('Response')\n    expect(another_component.context.bla).to eq('hi')\n    expect(another_component.context.my_method).to eq('Its my method')\n    expect(another_component.context.test).to eq('Response')\n  end\n\n  it 'should create instance method with given alias name for optional properties' do\n    class OptionalAliasPropertyComponent < Matestack::Ui::Component\n      optional method: { as: :my_method }, response: { as: :test }\n      def response\n      end\n    end\n    class AnotherOptionalAliasPropertyComponent < Matestack::Ui::Component\n      optional :bla, method: { as: :my_method }, response: { as: :test }\n      def response\n      end\n    end\n    component = OptionalAliasPropertyComponent.new(nil, method: 'Its my method', response: 'Response')\n    another_component = AnotherOptionalAliasPropertyComponent.new(nil, bla: 'hi', method: 'its my method', response: 'response')\n    expect(component.context.respond_to? :my_method).to be(true)\n    expect(component.context.my_method).to eq('Its my method')\n    expect(component.context.respond_to? :test).to be(true)\n    expect(component.context.test).to eq('Response')\n    expect(another_component.context.bla).to eq('hi')\n    expect(another_component.context.my_method).to eq('its my method')\n    expect(another_component.context.test).to eq('response')\n    expect(component.context.test).to eq('Response')\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/slots_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_slots_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'slots_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"Slots\" do\n\n    it \"a page can fill slots of components with access to page instance scope\" do\n\n      class SomeStaticComponent < Matestack::Ui::Component\n        \n        def response\n          @foo = \"foo from component\"\n          div id: \"my-component\" do\n            slot :my_first_slot\n            slot :my_second_slot\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        \n        def response\n          @foo = \"foo from page\"\n          div do\n            some_static_component slots: { my_first_slot: method(:my_simple_slot), my_second_slot: method(:my_second_simple_slot) }\n          end\n        end\n\n        def my_simple_slot\n          span id: \"my_simple_slot\" do\n            plain \"some content\"\n          end\n        end\n\n        def my_second_simple_slot\n          span id: \"my_simple_slot\" do\n            plain @foo\n          end\n        end\n\n      end\n\n      visit \"component_slots_spec/component_test\"\n\n      static_output = page.html\n\n      expected_static_output = <<~HTML\n      <div>\n        <div id=\"my-component\">\n          <span id=\"my_simple_slot\">\n            some content\n          </span>\n          <span id=\"my_simple_slot\">\n            foo from page\n          </span>\n        </div>\n      </div>\n      HTML\n\n      expect(stripped(static_output)).to include(stripped(expected_static_output))\n\n    end\n\n    # todo: Add test to check if placeholder from component works on page if no slot input is defined there\n\n    it \"a component can fill slots of components with access to component instance scope\" do\n\n      class SomeStaticComponent < Matestack::Ui::Component\n        \n        def response\n          @foo = \"foo from component\"\n          div id: \"my-component\" do\n            other_component slots: {\n              my_slot_from_component: method(:my_slot_from_component),\n              my_slot_from_page: slots[:my_slot_from_page]\n            }\n          end\n        end\n\n        def my_slot_from_component\n          span id: \"my-slot-from-component\" do\n            plain @foo\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class OtherComponent < Matestack::Ui::Component\n        \n        def response\n          @foo = \"foo from other component\"\n          div id: \"my-other-component\" do\n            slot :my_slot_from_component\n            slot :my_slot_from_page\n            plain @foo\n          end\n        end\n\n        register_self_as(:other_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        \n        def response\n          @foo = \"foo from page\"\n          div id: \"page-div\" do\n            some_static_component slots: { my_slot_from_page: method(:my_slot_from_page) }\n          end\n        end\n\n        def my_slot_from_page\n          span id: \"my-slot-from-page\" do\n            plain @foo\n          end\n        end\n\n      end\n\n      visit \"component_slots_spec/component_test\"\n\n      static_output = page.html\n\n      expected_static_output = <<~HTML\n        <div id=\"page-div\">\n          <div id=\"my-component\">\n            <div id=\"my-other-component\">\n              <span id=\"my-slot-from-component\">\n                foo from component\n              </span>\n              <span id=\"my-slot-from-page\">\n                foo from page\n              </span>\n              foo from other component\n            </div>\n          </div>\n        </div>\n      HTML\n\n      expect(stripped(static_output)).to include(stripped(expected_static_output))\n\n    end\n\n  end\n\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/static_rendering_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n      layout \"application_core\"\n\n      def my_action\n        render ExamplePage\n      end\n    end\n\n    Rails.application.routes.append do\n      scope \"component_static_rendering_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'static_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  describe \"static components\" do\n\n    it \"can render static content without any javascript involved if inherit from 'Matestack::Ui::Component'\" do\n      class SomeStaticComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            plain \"static component\"\n          end\n        end\n\n      register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            some_static_component\n          end\n        end\n      end\n\n      visit \"component_static_rendering_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"static component\")]')\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/url_params_access_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class ComponentTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"component_url_params_access_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'url_params_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"Request Access\" do\n\n    it \"a component can access request informations\" do\n\n      class SomeStaticComponent < Matestack::Ui::Component\n\n        def response\n            div id: \"my-component\" do\n              # TODO: rather than accessing plain instance variables\n              # I'd recommend a method based interface (easier to adjust, test, maintain if state is moved elsewhere etc.)\n              plain params[:foo]\n            end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          div id: \"div-on-page\" do\n            some_static_component\n          end\n        end\n\n      end\n\n      visit \"component_url_params_access_spec/component_test?foo=bar\"\n\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"bar\")]')\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/view_context_access_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class SomeLayout < Matestack::Ui::Layout\n      def response\n        yield\n      end\n    end\n\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n      matestack_layout SomeLayout\n\n      def my_action\n        render ExamplePage\n      end\n    end\n\n    Rails.application.routes.append do\n      scope \"component_view_context_access_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'access_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  describe \"View Context Access\" do\n\n    it \"a component can access view context scope\" do\n      class SomeStaticComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            if view_context.view_renderer.instance_of?(ActionView::Renderer)\n              plain \"has access to ActionView Context\"\n            end\n            plain link_to \"Test Link\", \"/some/page\" # calling an ActionView Url Helper here\n            plain time_ago_in_words(3.minutes.from_now) # calling an ActionView Date Helper here\n            plain \"root_path: #{root_path}\" # calling a Path Helper here\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div id: \"div-on-page\" do\n            some_static_component\n          end\n        end\n      end\n\n      visit \"component_view_context_access_spec/component_test\"\n      expect(page).to have_content(\"has access to ActionView Context\")\n      expect(page).to have_content(\"Test Link\")\n      expect(page).to have_content(\"3 minutes\")\n      expect(page).to have_content(\"root_path: /\")\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/component/yield_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Component\", type: :feature, js: true do\n\n  before :all do\n\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n    end\n\n    Rails.application.routes.append do\n      scope \"component_yield_spec\" do\n        get '/component_test', to: 'component_test#my_action', as: 'yield_component_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n\n  end\n\n  describe \"Yield\" do\n\n    it \"components can yield a block with access to scope, where block is defined\" do\n      class SomeStaticComponent < Matestack::Ui::Component\n        def response\n          div id: \"my-component\" do\n            yield\n          end\n        end\n\n        register_self_as(:some_static_component)\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n\n        def response\n          @foo = \"foo from page\"\n          div id: \"div-on-page\" do\n            some_static_component do\n              plain @foo\n            end\n          end\n        end\n      end\n\n      visit \"component_yield_spec/component_test\"\n      expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component\" and contains(.,\"foo from page\")]')\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/layout/layout_resolving_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Layout Resolving\", type: :feature, js: true do\n\n  before :all do\n    Rails.application.routes.append do\n      scope \"layout_resolving_spec\" do\n        get '/example_a', to: 'render_test_a#example'\n        get '/second_example_a', to: 'render_test_a#second_example'\n        get '/example_b', to: 'render_test_b#example'\n        get '/second_example_b', to: 'render_test_b#second_example'\n        get '/example_c', to: 'render_test_c#example'\n        get '/second_example_c', to: 'render_test_c#second_example'\n        get '/example_d', to: 'render_test_d#example'\n        get '/second_example_d', to: 'render_test_d#second_example'\n        get '/example_e', to: 'render_test_e#example'\n        get '/second_example_e', to: 'render_test_e#second_example'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  it \"does not wrap a Page with a layout when no Layout is explicitly specified\" do\n\n    class ExamplePage < Matestack::Ui::Page\n\n      def response\n        div do\n          plain \"hello from page\"\n        end\n      end\n\n    end\n\n    class RenderTestAController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def example\n        render ExamplePage\n      end\n\n    end\n\n    visit \"layout_resolving_spec/example_a\"\n\n    text = find(:xpath, '//body/div[1]').text\n    expect(text).to eq(\"hello from page\")\n  end\n\n  it \"wraps a Page with a specific Layout when explicitly specified on controller action level\" do\n    module ExampleApp\n    end\n\n    class ExampleApp::Layout < Matestack::Ui::Layout\n      def response\n        div class: \"my-app-layout\" do\n          yield\n        end\n      end\n    end\n\n    class ExampleApp::SomeOtherExampleLayout < Matestack::Ui::Layout\n      def response\n        div class: \"my-other-app-layout\" do\n          yield\n        end\n      end\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div do\n          plain \"hello from page\"\n        end\n      end\n    end\n\n    # otherwise the matestack_layout_class class var would be set as specified in the former spec\n    class RenderTestBController < ActionController::Base\n      layout \"application_core\"\n      include Matestack::Ui::Core::Helper\n\n      def example\n        render ExamplePage, matestack_layout: ExampleApp::Layout\n      end\n\n      def second_example\n        render ExamplePage, matestack_layout: ExampleApp::SomeOtherExampleLayout\n      end\n    end\n\n    visit \"layout_resolving_spec/example_b\"\n    text = find(:xpath, '//body/div[@class=\"my-app-layout\"]/div[1]').text\n\n    visit \"layout_resolving_spec/second_example_b\"\n    text = find(:xpath, '//body/div[@class=\"my-other-app-layout\"]/div[1]').text\n    expect(text).to eq(\"hello from page\")\n  end\n\n  it \"wraps a Page with a specific Layout when explicitly specified on controller (top) level\" do\n    module ExampleApp\n    end\n\n    class ExampleApp::Layout < Matestack::Ui::Layout\n      def response\n        div class: \"my-app-layout\" do\n          yield\n        end\n      end\n    end\n\n    class ExampleApp::SomeOtherExampleLayout < Matestack::Ui::Layout\n      def response\n        div class: \"my-other-app-layout\" do\n          yield\n        end\n      end\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div do\n          plain \"hello from page\"\n        end\n      end\n    end\n\n    # otherwise the matestack_layout_class class var would be set as specified in the former spec\n    class RenderTestCController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n      layout \"application_core\"\n      matestack_layout ExampleApp::Layout\n\n      def example\n        render ExamplePage\n      end\n\n      def second_example\n        render ExamplePage, matestack_layout: ExampleApp::SomeOtherExampleLayout # top level defined app can be overwritten on action level\n      end\n    end\n\n    visit \"layout_resolving_spec/example_c\"\n    text = find(:xpath, '//body/div[@class=\"my-app-layout\"]/div[1]').text\n\n    visit \"layout_resolving_spec/second_example_c\"\n    text = find(:xpath, '//body/div[@class=\"my-other-app-layout\"]/div[1]').text\n    expect(text).to eq(\"hello from page\")\n\n  end\n\n  describe \"is compatible with 0.7.x namespacing approach\" do\n\n    it \"when app is defined on controller (top) level\" do\n      module Layouts end\n      class Layouts::ExampleLayout < Matestack::Ui::Layout\n        def response\n          div class: \"my-app-layout\" do\n            yield\n          end\n        end\n      end\n\n      class Layouts::SomeOtherExampleLayout < Matestack::Ui::Layout\n        def response\n          div class: \"my-other-app-layout\" do\n            yield\n          end\n        end\n      end\n\n      module Pages end\n      module Pages::ExampleLayout end\n      module Pages::SomeOtherExampleLayout end\n\n      class Pages::ExampleLayout::ExamplePage < Matestack::Ui::Page\n        def response\n          div do\n            plain \"hello from example page\"\n          end\n        end\n      end\n\n      class Pages::SomeOtherExampleLayout::ExamplePage < Matestack::Ui::Page\n        def response\n          div do\n            plain \"hello from some other example page\"\n          end\n        end\n      end\n\n      # otherwise the matestack_layout_class class var would be set as specified in the former spec\n\n      class RenderTestEController < ActionController::Base\n        include Matestack::Ui::Core::Helper\n        layout \"application_core\"\n\n        def example\n          render Pages::ExampleLayout::ExamplePage, matestack_layout: Layouts::ExampleLayout\n        end\n\n        def second_example\n          render Pages::SomeOtherExampleLayout::ExamplePage, matestack_layout: Layouts::SomeOtherExampleLayout\n        end\n      end\n\n      visit \"layout_resolving_spec/example_e\"\n      text = find(:xpath, '//body/div[@class=\"my-app-layout\"]/div[1]').text\n\n      visit \"layout_resolving_spec/second_example_e\"\n      text = find(:xpath, '//body/div[@class=\"my-other-app-layout\"]/div[1]').text\n      expect(text).to eq(\"hello from some other example page\")\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/layout/layout_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"App\", type: :feature, js: true do\n\n  before :all do\n    Rails.application.routes.append do\n      scope \"app_layout_spec\" do\n        get 'layout_page1', to: 'example_app_pages#page1', as: 'layout_page1'\n        get 'layout_page2', to: 'example_app_pages#page2', as: 'layout_page2'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  it \"can wrap pages with a layout\" do\n    module ExampleApp\n    end\n\n    class ExampleApp::App < Matestack::Ui::Layout\n      def response\n        div class: \"root-div-from-layout\" do\n          h1 \"My Example App Layout\", size: 1\n          main do\n            yield\n          end\n        end\n      end\n    end\n\n    module ExampleApp::Pages\n    end\n\n    class ExampleApp::Pages::ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"my-div-on-page-1\" do\n          h2 \"This is Page 1\", size: 2\n        end\n      end\n    end\n\n    class ExampleApp::Pages::SecondExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"my-div-on-page-2\" do\n          h2 \"This is Page 2\", size: 2\n        end\n      end\n    end\n\n    class ExampleAppPagesController < ExampleController\n      include Matestack::Ui::Core::Helper\n      matestack_layout ExampleApp::App\n\n      def page1\n        render ExampleApp::Pages::ExamplePage\n      end\n\n      def page2\n        render ExampleApp::Pages::SecondExamplePage\n      end\n    end\n\n    visit \"app_layout_spec/layout_page1\"\n    expect(page).to have_xpath('//div[@class=\"root-div-from-layout\"]/h1[contains(.,\"My Example App Layout\")]')\n    expect(page).to have_xpath('//div[@class=\"root-div-from-layout\"]/main/div[@id=\"my-div-on-page-1\"]/h2[contains(.,\"This is Page 1\")]')\n    visit \"app_layout_spec/layout_page2\"\n    expect(page).to have_xpath('//div[@class=\"root-div-from-layout\"]/h1[contains(.,\"My Example App Layout\")]')\n    expect(page).to have_xpath('//div[@class=\"root-div-from-layout\"]/main/div[@id=\"my-div-on-page-2\"]/h2[contains(.,\"This is Page 2\")]')\n  end\n\n  it 'can use a layout file' do\n    module ExampleApp\n    end\n\n    class ExampleApp::App < Matestack::Ui::Layout\n      layout 'application_core'\n\n      def response\n        div class: \"root-div-from-layout\" do\n          h1 \"My Example App Layout\", size: 1\n          main do\n            yield\n          end\n        end\n      end\n    end\n\n    module ExampleApp::Pages\n    end\n\n    class ExampleApp::Pages::ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"my-div-on-page-1\" do\n          h2 \"This is Page 1\", size: 2\n        end\n      end\n    end\n\n    class ExampleAppPagesController < ExampleController\n      include Matestack::Ui::Core::Helper\n      layout false\n      matestack_layout ExampleApp::App\n\n      def page1\n        render ExampleApp::Pages::ExamplePage\n      end\n    end\n\n    visit \"app_layout_spec/layout_page1\"\n\n    expect(page).to have_xpath('//div[@class=\"root-div-from-layout\"]/h1[contains(.,\"My Example App Layout\")]')\n    expect(page).to have_xpath('//div[@class=\"root-div-from-layout\"]/main/div[@id=\"my-div-on-page-1\"]/h2[contains(.,\"This is Page 1\")]')\n    expect(page).to have_selector('div#from-rails-core-layout', visible: false)\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/page/controller_instance_access_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n  before :all do\n    Rails.application.routes.append do\n      scope \"page_controller_instance_spec\" do\n        get '/page_test', to: 'page_test#my_action', as: 'page_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  it \"should not be able to access controller instance variables\" do\n    class ExamplePage < Matestack::Ui::Page\n      optional :bar\n      def response\n        div do\n          plain ctx.bar\n        end\n        plain @foo\n      end\n    end\n\n    class PageTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        @bar = \"foo\"\n        @foo = 'bar'\n        render ExamplePage, bar: @bar\n      end\n\n    end\n\n    visit \"page_controller_instance_spec/page_test\"\n    expect(page).to have_content(\"foo\")\n    expect(page).not_to have_content(\"bar\")\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/page/orchestrates_components_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n  before :all do\n    class PageTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"page_orchestrates_components_spec\" do\n        get '/page_test', to: 'page_test#my_action', as: 'orchestrates_page_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  it \"orchestrates components and can be used as a controller action response\" do\n\n    class ExamplePage < Matestack::Ui::Page\n\n      def response\n        div do\n          plain \"Hello World from Example Page!\"\n        end\n      end\n\n    end\n    \n    visit \"page_orchestrates_components_spec/page_test\"\n\n    expect(page).to have_content(\"Hello World from Example Page!\")\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/page/partials_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n  before :all do\n    class PageTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"page_partials_spec\" do\n        get '/page_test', to: 'page_test#my_action', as: 'partials_page_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  it \"can structure the response using local partials\" do\n\n    class ExamplePage < Matestack::Ui::Page\n\n      def response\n        div do\n        my_simple_partial\n        my_partial_with_param \"foo\"\n        my_partial_with_partial\n        end\n      end\n\n      def my_simple_partial\n        span id: \"my_simple_partial\" do\n          plain \"some content\"\n        end\n      end\n\n      def my_partial_with_param some_param\n        span id: \"my_partial_with_param\" do\n          plain \"content with param: #{some_param}\"\n        end\n      end\n\n      def my_partial_with_partial\n        span id: \"my_partial_with_partial\" do\n          my_simple_partial\n        end\n      end\n\n    end\n\n    visit \"page_partials_spec/page_test\"\n\n    static_output = page.html\n\n    expected_static_output = <<~HTML\n    <div>\n\n      <span id=\"my_simple_partial\">\n        some content\n      </span>\n\n      <span id=\"my_partial_with_param\">\n        content with param: foo\n      </span>\n\n      <span id=\"my_partial_with_partial\">\n\n        <span id=\"my_simple_partial\">\n          some content\n        </span>\n\n      </span>\n\n    </div>\n    HTML\n\n    expect(stripped(static_output)).to include(stripped(expected_static_output))\n  end\n\n  it \"can structure the response using partials from included modules\" do\n\n    module MySharedPartials\n\n      def my_partial_with_param some_param\n        span id: \"my_partial_with_param\" do\n          plain \"content with param: #{some_param}\"\n        end\n      end\n\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n\n      include MySharedPartials\n\n      def response\n        div do\n          my_simple_partial\n          my_partial_with_param \"foo\"\n          my_partial_with_partial\n        end\n      end\n\n      def my_simple_partial\n        span id: \"my_simple_partial\" do\n          plain \"some content\"\n        end\n      end\n\n      def my_partial_with_partial\n        span id: \"my_partial_with_partial\" do\n          my_simple_partial\n        end\n      end\n\n    end\n\n    visit \"page_partials_spec/page_test\"\n\n    static_output = page.html\n\n    expected_static_output = <<~HTML\n    <div>\n\n      <span id=\"my_simple_partial\">\n        some content\n      </span>\n\n      <span id=\"my_partial_with_param\">\n        content with param: foo\n      </span>\n\n      <span id=\"my_partial_with_partial\">\n\n        <span id=\"my_simple_partial\">\n          some content\n        </span>\n\n      </span>\n\n    </div>\n    HTML\n\n\n    expect(stripped(static_output)).to include(stripped(expected_static_output))\n\n  end\n\n\nend\n"
  },
  {
    "path": "spec/test/core/base/page/prepare_spec.rb",
    "content": "# require 'rails_core_spec_helper' \n# include CoreSpecUtils\n\n# describe \"Page\", type: :feature, js: true do\n\n#   before :all do\n#     class PageTestController < ActionController::Base\n#       layout \"application_core\"\n\n#       include Matestack::Ui::Core::Helper\n\n#       def my_action\n#         render ExamplePage\n#       end\n\n#     end\n\n#     Rails.application.routes.append do\n#       scope \"page_prepare_spec\" do\n#         get '/page_test', to: 'page_test#my_action', as: 'preparepage_test_action'\n#       end\n#     end\n#     Rails.application.reload_routes!\n\n#   end\n\n#   describe \"Prepare\" do\n\n#     it \"a component can resolve data before rendering in a prepare method\" do\n\n#       class ExamplePage < Matestack::Ui::Page\n\n#         def prepare\n#           @hello = \"Hello World from Example Page!\"\n#         end\n\n#         def response\n#           div do\n#             plain @hello\n#           end\n#         end\n\n#       end\n\n#       visit \"page_prepare_spec/page_test\"\n\n#       expect(page).to have_content(\"Hello World from Example Page!\")\n#     end\n\n#   end\n\n# end\n"
  },
  {
    "path": "spec/test/core/base/page/slots_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n  before :all do\n    class PageTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"page_slots_spec\" do\n        get '/page_test', to: 'page_test#my_action', as: 'slots_page_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n\n  it \"can fill slots of components with access to page instance scope\" do\n\n    class SlotTestComponent < Matestack::Ui::Component\n\n      def prepare\n        @foo = \"foo from component\"\n      end\n\n      def response\n        div id: \"my-component\" do\n          slot :my_first_slot\n          slot :my_second_slot\n        end\n      end\n\n      register_self_as(:slot_test_component)\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n\n      def response\n        @foo = \"foo from page\"\n        div do\n          slot_test_component slots: { my_first_slot: method(:my_simple_slot), my_second_slot: method(:my_second_simple_slot) }\n        end\n      end\n\n      def my_simple_slot\n        span id: \"my_simple_slot\" do\n          plain \"some content\"\n        end\n      end\n\n      def my_second_simple_slot\n        span id: \"my_simple_slot\" do\n          plain @foo\n        end\n      end\n\n    end\n\n    visit \"page_slots_spec/page_test\"\n\n    expect(page).to have_selector(\"div > div#my-component > span#my_simple_slot\", text: \"some content\")\n    expect(page).to have_selector(\"div > div#my-component > span#my_simple_slot\", text: \"foo from page\")\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/page/url_params_access_spec.rb",
    "content": "require 'rails_core_spec_helper' \ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n  before :all do\n    class PageTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"page_url_params_access_spec\" do\n        get '/page_test', to: 'page_test#my_action', as: 'url_params_page_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n  it \"can access url params\" do\n\n    class ExamplePage < Matestack::Ui::Page\n\n      def response\n        div do\n          plain \"foo: #{params[:foo]}\"\n        end\n      end\n\n    end\n\n    visit \"page_url_params_access_spec/page_test/?foo=bar\"\n\n    expect(page).to have_content(\"foo: bar\")\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/base/page/view_context_access_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe \"Page\", type: :feature, js: true do\n\n  before :all do\n    class PageTestController < ActionController::Base\n      layout \"application_core\"\n\n      include Matestack::Ui::Core::Helper\n\n      def my_action\n        render ExamplePage\n      end\n\n    end\n\n    Rails.application.routes.append do\n      scope \"page_view_context_access_spec\" do\n        get '/page_test', to: 'page_test#my_action', as: 'view_context_page_test_action'\n      end\n    end\n    Rails.application.reload_routes!\n  end\n\n\n  it \"can access ActionView Context\" do\n\n    class ExamplePage < Matestack::Ui::Page\n\n      def response\n        div do\n          if view_context.view_renderer.instance_of?(ActionView::Renderer)\n            plain \"has access to ActionView Context\"\n          end\n          plain link_to \"Test Link\", \"/some/page\" # calling an ActionView Url Helper here\n          plain time_ago_in_words(3.minutes.from_now) # calling an ActionView Date Helper here\n          plain \"root_path: #{root_path}\" # calling a Path Helper here\n        end\n      end\n\n    end\n\n    visit \"page_view_context_access_spec/page_test\"\n\n    expect(page).to have_content(\"has access to ActionView Context\")\n    expect(page).to have_content(\"Test Link\")\n    expect(page).to have_content(\"3 minutes\")\n    expect(page).to have_content(\"root_path: /\")\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/custom_component_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'Creating custom components', type: :feature, js: true do\n\n  before :all do\n    module Components end\n\n    module Pages end\n\n    module Matestack::Ui::Core end\n\n    class SomeLayout < Matestack::Ui::Layout\n      def response\n        yield\n      end\n    end\n\n    class ComponentTestController < ActionController::Base\n      include Matestack::Ui::Core::Helper\n      matestack_layout SomeLayout\n\n      def my_action\n        render(ExamplePage)\n      end\n    end\n\n    Rails.application.routes.append do\n      get '/custom_component_test', to: 'component_test#my_action'\n    end\n    Rails.application.reload_routes!\n  end\n\n  it 'by orchestrating existing static core components' do\n    module Components end\n\n    class Components::CrazyComponent < Matestack::Ui::Component\n      def response\n        div id: 'my-component-1' do\n          plain \"I'm a static component!\"\n        end\n      end\n\n      register_self_as(:crazy_component)\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: 'div-on-page' do\n          crazy_component\n        end\n      end\n    end\n\n    visit '/custom_component_test'\n    expect(page).to have_xpath('//div[@id=\"div-on-page\"]/div[@id=\"my-component-1\" and contains(.,\"I\\'m a static component!\")]')\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/html_rendering/action_view_integration.rb",
    "content": "require 'rails_core_spec_helper'\n\ndescribe 'Action View Integration', type: :feature do\n  include CoreSpecUtils\n\n  it \"using non-block view helpers via plain\" do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        link_to \"Test Link without plain\", \"/some/page\" # calling an ActionView Url Helper here\n        plain link_to \"Test Link\", \"/some/page\" # calling an ActionView Url Helper here\n\n        span id: \"time-ago-in-words-example\" do\n          plain time_ago_in_words(3.minutes.from_now) # calling an ActionView Date Helper here\n        end\n\n        span id: \"path-helper-example\" do\n          plain \"root_path: #{root_path}\" # calling a Path Helper here\n        end\n      end\n    end\n\n    visit \"/example\"\n\n    expect(page).not_to have_selector(\"a[href='/some/page']\", text: \"Test Link without plain\")\n    expect(page).to have_selector(\"a[href='/some/page']\", text: \"Test Link\")\n    expect(page).to have_selector(\"span#time-ago-in-words-example\", text: \"3 minutes\")\n    expect(page).to have_selector(\"span#path-helper-example\", text: \"root_path: /\")\n  end\n\n  it \"using block view helpers via plain do ... end and matestack_to_s\" do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        # not working, missing plain wrapper and matestack_to_s\n        link_to \"/some/page\" do\n          span do\n            plain \"link content in block without wrapping plain and matestack_to_s\"\n          end\n        end\n        # not working, missing matestack_to_s\n        plain do\n          link_to \"/some/page\" do\n            span do\n              plain \"link content in block with wrapping plain but without matestack_to_s\"\n            end\n          end\n        end\n        # working\n        plain do\n          link_to \"/some/page\" do\n            matestack_to_s do\n              span do\n                plain \"link content in block with wrapping plain and matestack_to_s\"\n              end\n            end\n          end\n        end\n      end\n    end\n\n    visit \"/example\"\n\n    expect(page).not_to have_selector(\"a[href='/some/page'] > span\", text: \"link content in block without wrapping plain and matestack_to_s\")\n    expect(page).not_to have_selector(\"a[href='/some/page'] > span\", text: \"link content in block with wrapping plain but without matestack_to_s\")\n    expect(page).to have_selector(\"a[href='/some/page'] > span\", text: \"link content in block with wrapping plain and matestack_to_s\")\n  end\n\n  it \"using block view helpers via plain do ... end and matestack_to_s and block variables\" do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        plain do\n          form_with url: \"/some_path\" do |f|\n            matestack_to_s do\n              plain f.text_field :foo\n              br\n              div class: \"some-input-wrapper\" do\n                plain f.text_field :bar\n              end\n              br\n              some_partial_rendering_view_helpers(f)\n              br\n              some_partial\n              br\n              plain f.submit\n            end\n          end\n        end\n      end\n\n      def some_partial\n        div class: \"some-partial\" do\n          plain \"text from partial\"\n        end\n      end\n\n      def some_partial_rendering_view_helpers f\n        div class: \"some-input-wrapper-in-partial\" do\n          plain f.text_field :baz\n        end\n      end\n    end\n\n    visit \"/example\"\n\n    expect(page).to have_selector(\"form[action='/some_path'] > input#foo[type='text']\")\n    expect(page).to have_selector(\"form[action='/some_path'] > div.some-input-wrapper > input#bar[type='text']\")\n    expect(page).to have_selector(\"form[action='/some_path'] > div.some-input-wrapper-in-partial > input#baz[type='text']\")\n    expect(page).to have_selector(\"form[action='/some_path'] > div.some-partial\", text: \"text from partial\")\n    expect(page).to have_selector(\"form[action='/some_path'] > input[type='submit']\")\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/html_rendering/default_tags_spec.rb",
    "content": "require 'rails_core_spec_helper'\n\ndescribe 'Default Tags Rendering', type: :feature do\n  include CoreSpecUtils\n\n  describe 'Plain Text Rendering' do\n\n    it \"plain text\" do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          plain \"Hello World!\"\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"body\", text: \"Hello World!\")\n    end\n\n    it \"doesn't allow script injection\" do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          plain XSS::EVIL_SCRIPT\n        end\n      end\n      visit \"/example\"\n      expect(page.html).to include(XSS::ESCAPED_EVIL_SCRIPT)\n    end\n\n    it \"allows injection when you say #html_safe\" do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          plain XSS::EVIL_SCRIPT.html_safe\n        end\n      end\n\n      # gotta accept our injected alert\n      accept_alert do\n        visit \"/example\"\n      end\n      # the script tag seems removed afterwards so we can't check against it here\n    end\n\n  end\n\n  describe \"Unescaped Rendering\" do\n\n    it \"`unescape` allows the insertion of pure HTML\" do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          unescape <<~HTML\n            <h1>Hello World</h1>\n            <script>alert('Really Hello!')</script>\n          HTML\n        end\n      end\n      accept_alert do\n        visit \"/example\"\n      end\n      expect(page).to have_selector(\"h1\", text: \"Hello World\")\n    end\n\n  end\n\n  describe 'Simple void Tags not supporting child Tags' do\n\n    tags = [:area, :base, :basefont, :br, :hr, :iframe, :img, :input, :link, :meta,\n      :param, :command, :keygen, :source, :embed]\n\n    tags.each do |tag|\n      it \"<#{tag.to_s}>\" do\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" })\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", visible: :all)\n      end\n    end\n\n  end\n\n  describe 'Simple Tags supporing child Tags, plain text or no child at all' do\n\n    tags = [:a, :abbr, :acronym, :address, :applet, :article, :aside, :audio, :b,\n      :bdi, :bdo, :big, :blockquote, :body, :button, :canvas, :center, :cite, :code, :data,\n      :datalist, :dd, :del, :details, :dfn, :dialog,\n      :dir, :div, :dl, :dt, :em, :fieldset, :figcaption, :figure, :font, :footer, :form,\n      :h1, :h2, :h3, :h4, :h5, :h6, :header, :html, :i, :ins, :kbd, :label, :legend, :li, :main, :map,\n      :mark, :meter, :nav, :object, :ol, :optgroup, :option, :output, :picture, :pre,\n      :progress, :q, :rp, :rt, :ruby, :s, :samp, :section, :small, :span, :strike, :strong,\n      :sub, :summary, :sup, :time, :tt, :u, :ul, :var, :video]\n\n\n    tags.each do |tag|\n      it \"<#{tag.to_s}>\" do\n        # no inner html at all\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" })\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).not_to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'][text='']\", text: \"\", visible: :all)\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"\", visible: :all)\n\n        # inner html as plain text via first non-hash argument\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, \"plain text content\", foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" })\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).not_to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'][text='plain text content']\", text: \"plain text content\", visible: :all)\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"plain text content\", visible: :all)\n\n        # inner html as plain text via text key in hash argument\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }, text: \"plain text content\")\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).not_to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'][text='plain text content']\", text: \"plain text content\", visible: :all)\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"plain text content\", visible: :all)\n\n        # inner html via block\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }) do\n              # using span as an example for a child tag (can be any tag, if parent tag is supporting it)\n              span do\n                plain \"block content\"\n              end\n            end\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'] span\", text: \"block content\", visible: :all)\n\n        # inner html via block, text key gets ignored\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }, text: \"plain text content gets ignored\") do\n              span do\n                plain \"block content\"\n              end\n            end\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'] span\", text: \"block content\", visible: :all)\n        expect(page).not_to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"plain text content gets ignored\", visible: :all)\n\n        # inner html via block, text via first argument gets ignored\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            self.send(params[:tag].to_s, \"plain text content gets ignored\", foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }) do\n              span do\n                plain \"block content\"\n              end\n            end\n          end\n        end\n        visit \"/example?tag=#{tag.to_s}\"\n        expect(page).to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'] span\", text: \"block content\", visible: :all)\n        expect(page).not_to have_selector(\"#{tag.to_s}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"plain text content gets ignored\", visible: :all)\n      end\n    end\n\n    it '<p> aliased via `paragraph`' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          paragraph \"plain text content via first argument\", foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }\n          paragraph foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }, text: \"plain text content\"\n          paragraph foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" } do\n            span do\n              plain \"block content\"\n            end\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).not_to have_selector(\"p[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'][text='plain text content via first argument']\", text: \"plain text content via first argument\", visible: true)\n      expect(page).to have_selector(\"p[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"plain text content via first argument\", visible: true)\n      expect(page).not_to have_selector(\"p[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'][text='plain text content']\", text: \"plain text content\", visible: true)\n      expect(page).to have_selector(\"p[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"plain text content\", visible: true)\n      expect(page).to have_selector(\"p[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'] span\", text: \"block content\", visible: true)\n    end\n\n    it '<h{x}> aliased via `heading size: {x}`' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          (1..6).each do |i|\n            heading \"Heading #{i}\", size: i, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" }\n          end\n          (1..6).each do |i|\n            heading size: i, foo: 'foo-value', \"bar-attr\": 'bar-value', data: { baz: \"baz-value\" } do\n              span do\n                plain \"Heading Block Content #{i}\"\n              end\n            end\n          end\n        end\n      end\n      visit \"/example\"\n      (1..6).each do |i|\n        expect(page).not_to have_selector(\"h#{i}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'][text='Heading #{i}']\", text: \"Heading #{i}\", visible: true)\n        expect(page).to have_selector(\"h#{i}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value']\", text: \"Heading #{i}\", visible: true)\n\n        expect(page).to have_selector(\"h#{i}[foo='foo-value'][bar-attr='bar-value'][data-baz='baz-value'] span\", text: \"Heading Block Content #{i}\", visible: true)\n      end\n    end\n\n  end\n\n  describe 'Tags with processed attributes' do\n\n    it '<a> path -> href' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          a \"Link Text 1\", path: \"https://matestack.io\", title: \"Link 1\"\n          a \"Link Text 2\", href: \"https://matestack.io\", title: \"Link 2\"\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"a[title='Link 1'][href='https://matestack.io']\", text: \"Link Text 1\")\n      expect(page).to have_selector(\"a[title='Link 2'][href='https://matestack.io']\", text: \"Link Text 2\")\n    end\n\n    it '<img> path -> src via Asset Pipeline' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          img src: \"#{ActionController::Base.helpers.asset_path('matestack-logo.png')}\", width: 500, height: 300, alt: \"logo_1\"\n          img path: \"matestack-logo.png\", width: 500, height: 300, alt: \"logo_2\"\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\n        \"img[alt='logo_1'][height='300'][width='500'][src='#{ActionController::Base.helpers.asset_path('matestack-logo.png')}']\"\n      )\n      expect(page).to have_selector(\n        \"img[alt='logo_2'][height='300'][width='500'][src='#{ActionController::Base.helpers.asset_path('matestack-logo.png')}']\"\n      )\n    end\n\n  end\n\n  describe 'Context dependent Tags' do\n\n    describe 'Table Tags' do\n\n      it '<table> and children' do\n        class ExamplePage < Matestack::Ui::Page\n          def response\n            table class: 'foo' do\n              caption do\n                plain \"Test Table\"\n              end\n              colgroup do\n                col span:\"2\", style:\"background-color:red\"\n                col style:\"background-color:yellow\"\n              end\n              thead class: 'head' do\n                tr class: 'bar' do\n                  th 'First'\n                  th 'Matestack'\n                  th 'Table'\n                end\n              end\n              tbody class: 'body' do\n                tr do\n                  td 'One'\n                  td 'Two'\n                  td 'Three'\n                end\n                tr do\n                  td 'Uno'\n                  td 'Dos'\n                  td 'Tres'\n                end\n              end\n              tfoot class: 'foot' do\n                tr do\n                  td 'Eins'\n                  td 'Zwei'\n                  td 'Drei'\n                end\n              end\n            end\n          end\n        end\n        visit \"/example\"\n\n        expect(page).to have_selector(\"table[class='foo'] > caption\", text: \"Test Table\", visible: true)\n\n        expect(page).to have_selector(\"table[class='foo'] > colgroup > col[span='2'][style='background-color:red']\", text: \"\", visible: :all)\n        expect(page).to have_selector(\"table[class='foo'] > colgroup > col[style='background-color:yellow']\", text: \"\", visible: :all)\n\n        expect(page).to have_selector(\"table[class='foo'] > thead[class='head'] > tr[class='bar'] th\", text: \"First\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > thead[class='head'] > tr[class='bar'] th\", text: \"Matestack\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > thead[class='head'] > tr[class='bar'] th\", text: \"Table\", visible: true)\n\n        expect(page).to have_selector(\"table[class='foo'] > tbody[class='body'] > tr > td\", text: \"One\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tbody[class='body'] > tr > td\", text: \"Two\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tbody[class='body'] > tr > td\", text: \"Three\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tbody[class='body'] > tr > td\", text: \"Uno\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tbody[class='body'] > tr > td\", text: \"Dos\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tbody[class='body'] > tr > td\", text: \"Tres\", visible: true)\n\n        expect(page).to have_selector(\"table[class='foo'] > tfoot[class='foot'] > tr > td\", text: \"Eins\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tfoot[class='foot'] > tr > td\", text: \"Zwei\", visible: true)\n        expect(page).to have_selector(\"table[class='foo'] > tfoot[class='foot'] > tr > td\", text: \"Drei\", visible: true)\n      end\n    end\n\n    it '<svg> and Children' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          svg width: \"100\", height: \"100\" do\n            # svg child tags currently not supported, using documented custom tag rendering approach\n            plain tag(:circle, cx: \"50\", cy: \"50\", r: \"40\", stroke: \"green\", \"stroke-width\": \"4\", fill: \"yellow\")\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"svg[width='100'][height='100'] circle[cx='50'][cy='50'][r='40'][stroke='green'][stroke-width='4'][fill='yellow']\", text: \"\", visible: true)\n    end\n\n    it '<select> with <options>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          select do\n            option \"One\", value: 1\n            option \"Two\", value: 2\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"select option[value='1']\", text: \"One\", visible: true)\n      expect(page).to have_selector(\"select option[value='2']\", text: \"Two\", visible: true)\n    end\n\n    it '<track> in <audio> or <video>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          video width: \"320\", height: \"240\", controls: true do\n            track src: \"fgsubtitles_en.vtt\", kind: \"subtitles\", srclang: \"en\", label: \"English\"\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"video[width='320'][height='240'][controls] track[src='fgsubtitles_en.vtt']\", text: \"\", visible: :all)\n    end\n\n  end\n\n  describe 'Head only Tags' do\n\n    it '<head>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          head do\n\n          end\n        end\n      end\n      visit \"/example?only_page=true\"\n      expect(page).to have_selector(\"head\", text: \"\", visible: :all)\n    end\n\n    it '<style>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          style type: \"text/css\" do\n            plain \"h1 {color:red;}\"\n          end\n        end\n      end\n      visit \"/example?only_page=true\"\n      expect(page).to have_selector(\"style[type='text/css']\", text: \"h1 {color:red;}\", visible: false)\n    end\n\n    it '<title>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          title do\n            plain \"My App\"\n          end\n        end\n      end\n      visit \"/example?only_page=true\"\n      expect(page).to have_selector(\"title\", text: \"My App\", visible: false)\n    end\n\n  end\n\n  describe 'Tags supporting only Text as Child' do\n\n    it '<noscript>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          noscript do\n            plain \"no script\"\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"noscript\", text: \"no script\", visible: false)\n    end\n\n    it '<wbr>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          paragraph do\n            plain \"some\"\n            wbr\n            plain \"text\"\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"p\", text: \"some text\", visible: true)\n      expect(page).to have_selector(\"p wbr\", visible: false)\n    end\n\n    it '<textarea>' do\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          textarea rows:\"4\", cols: \"50\" do\n            plain \"some placeholder text\"\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"textarea[rows='4'][cols='50']\", text: \"some placeholder text\", visible: true)\n    end\n\n  end\n\n  describe 'invisible tags' do\n\n    it '<script>' do\n      # don't know how to expect the script tag -> it's removed by the headless browser and content not rendered\n      #\n      # class ExamplePage < Matestack::Ui::Page\n      #   def response\n      #     script do\n      #       plain \"some script\"\n      #     end\n      #   end\n      # end\n      # visit \"/example\"\n      # expect(page).to have_selector(\"script\", text: \"some script\", visible: false)\n    end\n\n    it '<template>' do\n      # template tag is removed by browser, content will be visible\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          div class: \"template-wrapper\" do\n            template do\n              plain \"some placeholder text\" # will be converted to a fragment by the browser\n            end\n          end\n        end\n      end\n      visit \"/example\"\n      expect(page).to have_selector(\"div[class='template-wrapper'] > template\", visible: :all)\n    end\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/html_rendering/link_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'a Component', type: :feature, js: true do\n\n  it 'Example 1 - Text Option' do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"foo\", class: \"bar\" do\n          a 'here', href: \"https://matestack.org\"\n        end\n      end\n    end\n\n    visit \"/example\"\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div id=\"foo\" class=\"bar\">\n        <a href=\"https://matestack.org\">here</a>\n      </div>\n    HTML\n    expect(stripped(static_output)).to ( include(stripped(expected_static_output)) )\n  end\n\n  it 'Example 2 - Yield' do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"foo\", class: \"bar\" do\n          a path: \"https://matestack.org\", title: \"The matestack website\" do\n            plain 'here'\n          end\n        end\n      end\n    end\n\n    visit \"/example\"\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div id=\"foo\" class=\"bar\">\n        <a title=\"The matestack website\" href=\"https://matestack.org\">here</a>\n      </div>\n    HTML\n    expect(stripped(static_output)).to ( include(stripped(expected_static_output)) )\n  end\n\n  it 'Example 3 - Target' do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"foo\", class: \"bar\" do\n          a href: \"https://matestack.org\", target: \"_blank\" do\n            plain 'here'\n          end\n        end\n      end\n    end\n\n    visit \"/example\"\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div id=\"foo\" class=\"bar\">\n        <a href=\"https://matestack.org\" target=\"_blank\">here</a>\n      </div>\n    HTML\n    expect(stripped(static_output)).to ( include(stripped(expected_static_output)) )\n  end\n\n  it 'Example 4 - Rails Routing' do\n    Rails.application.routes.append do\n      get '/some_link_test_path', to: 'page_test#my_action', as: 'link_test'\n    end\n    Rails.application.reload_routes!\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"foo\", class: \"bar\" do\n          a href: link_test_path do\n            plain 'here'\n          end\n        end\n      end\n    end\n\n    visit \"/example\"\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div id=\"foo\" class=\"bar\">\n        <a href=\"/some_link_test_path\">here</a>\n      </div>\n    HTML\n    expect(stripped(static_output)).to ( include(stripped(expected_static_output)) )\n  end\n\n  it 'Example 6 - Rails Routing using symbols with params' do\n    Rails.application.routes.append do\n      get '/some_link_test_path/:number', to: 'page_test#my_action', as: 'link_test_with_param'\n    end\n    Rails.application.reload_routes!\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: \"foo\", class: \"bar\" do\n          a href: link_test_with_param_path(number: 1), text: 'Call API endpoint 1'\n        end\n      end\n    end\n\n    visit \"/example\"\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div id=\"foo\" class=\"bar\">\n        <a href=\"/some_link_test_path/1\">Call API endpoint 1</a>\n      </div>\n    HTML\n    expect(stripped(static_output)).to ( include(stripped(expected_static_output)) )\n  end\n\n  it \"behaves correctly with anchor links (no reload, retain anchor)\" do\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        a href: \"#someanchor\", text: \"go to anchor\", id: \"my-link\"\n        br times: 200\n        div id: \"someanchor\" do\n          plain \"hello!\"\n        end\n        div id: \"my-div\" do\n          plain \"#{DateTime.now.strftime('%Q')}\"\n        end\n      end\n    end\n\n    visit \"/example\"\n    element = page.find(\"#my-div\")\n    before_content = element.text\n    # don't you rerender on me!\n    expect(ExamplePage).not_to receive(:new)\n    page.click_link(\"my-link\")\n    # if the page reloaded we'd have different content here but as we don't want reloads\n    # we want the same\n    expect(page).to have_css(\"#my-div\", text: before_content)\n    expect(page.current_url).to end_with(\"#someanchor\")\n  end\n\n  describe \"with an App\" do\n\n    after :each do\n      class ExamplePage < Matestack::Ui::Page\n        # as the test suites work with redefining classes and this\n        # hack here was used to set a specific app easily,\n        # we need to \"restore\" previous state\n        def set_app_class\n          super\n        end\n      end\n    end\n\n    it \"behaves correctly with anchor links (no reload, retain anchor) even inside an app\" do\n      class MyTestApp < Matestack::Ui::Layout\n        def response\n          page_content\n        end\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          a href: \"#someanchor\", text: \"go to anchor\", id: \"my-link\"\n          br times: 200\n          div id: \"someanchor\" do\n            plain \"hello!\"\n          end\n          div id: \"my-div\" do\n            plain \"#{DateTime.now.strftime('%Q')}\"\n          end\n        end\n\n        # Hacky/instable but easy way to set my custom App for this page\n        def set_app_class\n          @app_class = MyTestApp\n        end\n      end\n\n      visit \"/example\"\n      element = page.find(\"#my-div\")\n      before_content = element.text\n      # don't you rerender on me!\n      expect(ExamplePage).not_to receive(:new)\n      page.click_link(\"my-link\")\n      # if the page reloaded we'd have different content here but as we don't want reloads\n      # we want the same\n      expect(page).to have_css(\"#my-div\", text: before_content)\n      expect(page.current_url).to end_with(\"#someanchor\")\n    end\n\n    it \"just changing the search string will still reload the page\" do\n      class MyTestApp < Matestack::Ui::Layout\n        def response\n          page_content\n        end\n      end\n\n      class ExamplePage < Matestack::Ui::Page\n        def response\n          a href: \"?a=true\", text: \"go to anchor\", id: \"my-link\"\n          br times: 200\n          div id: \"my-div\" do\n            plain \"#{DateTime.now.strftime('%Q')}\"\n          end\n        end\n\n        # Hacky/instable but easy way to set my custom App for this page\n        def set_app_class\n          @app_class = MyTestApp\n        end\n      end\n\n      visit \"/example\"\n      element = page.find(\"#my-div\")\n      before_content = element.text\n      page.click_link(\"my-link\")\n      expect(page).to have_css(\"#my-div\")\n      expect(page).to have_no_css(\"#my-div\", text: before_content)\n      expect(page.current_url).to end_with(\"?a=true\")\n    end\n  end\nend\n"
  },
  {
    "path": "spec/test/core/rails_render_spec.rb",
    "content": "require 'rails_core_spec_helper'\ninclude CoreSpecUtils\n\ndescribe 'Rails View Component', type: :feature, js: true do\n\n  after :all do\n    class ExampleController < ApplicationController\n      def page\n        render ExamplePage\n      end\n    end\n  end\n\n  it 'renders given view on to page' do\n    class ExampleController < ApplicationController\n      def page\n        @title = 'Test Title'\n        render ExamplePage\n      end\n    end\n\n    class ExamplePage < Matestack::Ui::Page\n      def response\n        div id: 'page' do\n          rails_render template: 'demo/header'\n          rails_render partial: 'demo/header'\n        end\n      end\n    end\n    visit '/example'\n    static_output = page.html\n    expected_static_output = <<~HTML\n      <div id=\"page\">\n        <header>\n          <h1>Rails View</h1>\n          <p>Test Title</p>\n        </header>\n        <header>\n          <h1>Rails Partial</h1>\n          <p>Test Title</p>\n        </header>\n      </div>\n    HTML\n    expect(stripped(static_output)).to include(stripped(expected_static_output))\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/support/capybara.rb",
    "content": "require 'capybara/rspec'\nrequire 'capybara/rails'\nrequire \"selenium/webdriver\"\n\nrequire \"matestack/ui/core\"\n\nCapybara.server_port = 33123\nCapybara.server_host = \"0.0.0.0\"\n\nCapybara.app = Dummy::Application\n\nCapybara.register_driver :selenium do |app|\n  chrome_options = Selenium::WebDriver::Chrome::Options.new.tap do |o|\n    o.add_argument '--headless'\n    o.add_argument '--no-sandbox'\n    o.add_argument '--disable-dev-shm-usage'\n    o.add_argument '--disable-gpu'\n    o.add_argument '--enable-features=NetworkService,NetworkServiceInProcess'\n  end\n  Capybara::Selenium::Driver.new(app, browser: :chrome, options: chrome_options)\nend\nCapybara.default_driver = :selenium"
  },
  {
    "path": "spec/test/core/support/core_spec_utils.rb",
    "content": "module CoreSpecUtils\n\n  def stripped(html_string)\n    html_string\n      .gsub(/>\\s+</, \"><\")\n      .gsub(\"\\n\", \"\")\n      .gsub(/\\s+/, \"\") # TODO: this removes all white space even button text like \"Render me!\" becomes \"Renderme!\" which I don't is as designed\n      .gsub(\"<br>\", \"<br/>\") # TODO Tobi get your browser together\n  end\n\n  def path_exists?(path_as_symbol)\n  \tRails.application.routes.url_helpers.method_defined?(path_as_symbol)\n  end\n\n  # Because of how this is handled in tests (include CoreSpecUtils) this actually\n  # ends up on Object so the method is available on a class level which\n  # for tests allows a relatively convenient access\n  def register_component(dsl_method, component_class)\n    # Matestack::Ui::Component.register({ dsl_method => component_class })\n    Matestack::Ui::Core::Base.define_method(dsl_method) do |text = nil, options = {}, &block|\n      component_class.call(text, options, &block)\n    end\n  end\n\n  # even more test convenience\n  def register_self_as(dsl_method)\n    register_component(dsl_method, self)\n  end\n\n  def matestack_render(reset_app: true, page: MatestackWrapperPage, &block)\n    page.define_method(:response, block)\n    visit matestack_components_test_path\n    reset_matestack_layout if reset_app\n  end\n\n  def matestack_layout(&block)\n    MatestackWrapperLayout.define_method(:app_body, block)\n  end\n\n  def reset_matestack_layout\n    MatestackWrapperLayout.define_method(:app_body) do\n    end\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/support/example_controller.rb",
    "content": "require_relative 'layout'\n\nclass ExampleController < ApplicationController\n  include Matestack::Ui::Core::Helper\n\n  layout \"application_core\"\n  matestack_layout Layout\n\n  def page\n    render ExamplePage\n  end\n\n  def base\n    render BaseExamplePage\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/support/layout.rb",
    "content": "# used in specs only, look for the demo app here: ./demo/app.rb\n\nclass Layout < Matestack::Ui::Layout\n\n  def response\n    yield\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/support/matestack_components_controller.rb",
    "content": "require_relative 'matestack_wrapper_layout'\nrequire_relative 'matestack_wrapper_page'\n\nclass MatestackComponentsController < ApplicationController\n  include Matestack::Ui::Core::Helper\n\n  matestack_layout MatestackWrapperLayout\n\n  def matestack_components_test\n    render MatestackWrapperPage\n  end\n\n  def matestack_transition_test\n    render MatestackTransitionPage\n  end\nend\n"
  },
  {
    "path": "spec/test/core/support/matestack_wrapper_layout.rb",
    "content": "class MatestackWrapperLayout < Matestack::Ui::Layout\n  def response\n    app_body\n    yield\n  end\n\n  def app_body\n\n  end\n\nend\n"
  },
  {
    "path": "spec/test/core/support/matestack_wrapper_page.rb",
    "content": "class MatestackWrapperPage < Matestack::Ui::Page\n  def response\n  end\nend\n"
  },
  {
    "path": "spec/test/core/support/test_controller.rb",
    "content": "class TestController < ActionController::Base\n  before_action :check_params\n\n  def check_params\n    expect_params(params.permit!.to_h)\n  end\n\n  def expect_params(params)\n  end\nend\n"
  },
  {
    "path": "spec/test/core/support/xss.rb",
    "content": "module XSS\n  EVIL_SCRIPT = \"<script>alert('hello');</script>\"\n  ESCAPED_EVIL_SCRIPT = \"&lt;script&gt;alert('hello');&lt;/script&gt;\"\nend\n"
  },
  {
    "path": "spec/test/core/xss_spec.rb",
    "content": "require 'rails_core_spec_helper'\n\ndescribe \"XSS behavior\", type: :feature, js: true do\n  include CoreSpecUtils\n\n  describe \"injection in heading as an example\" do\n    it \"escapes the evil script\" do\n      matestack_render do\n        h1 XSS::EVIL_SCRIPT\n      end\n      expect(page).to have_selector('h1', text: XSS::EVIL_SCRIPT)\n      expect_alert false\n    end\n\n    it \"does not escape when we specifically say #html_safe\" do\n      matestack_render do\n        h1 XSS::EVIL_SCRIPT.html_safe\n      end\n      # gotta accept our injected alert\n      accept_alert do\n        expect_alert true\n      end\n    end\n\n    # note that `heading do \"string\" end` doesn't work and you\n    # should rather use `heading do plain \"string\" end`\n    # Why the hell is this tested then?\n    # Well if that behavior changed I'd like to have a reminder\n    # here to catch it. Call me overly cautious.\n    it \"escaping won't be broken in block form (if it worked)\" do\n      matestack_render do\n        h1 do\n          XSS::EVIL_SCRIPT\n        end\n      end\n      expect_alert false\n      static_output = page.html\n      expect(static_output).not_to include(\"alert(\")\n    end\n\n    it \"escapes the evil when injecting into attributes\" do\n      matestack_render do\n        h1 \"Be Safe!\", id: \"something-\\\">#{XSS::EVIL_SCRIPT}\"\n      end\n      expect_alert false\n      # expect(page.html).to include(\"id=\\\"something-&quot;&gt;&lt;script&gt;alert('hello');&lt;/script&gt;\")\n    end\n  end\n\n\n\n  def expect_alert(alert)\n    @alert = true\n    begin\n      page.driver.browser.switch_to.alert\n    rescue\n      @alert = false\n    end\n    expect(@alert).to be(alert)\n  end\nend\n"
  }
]