comfy_middle_seat 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.codeclimate.yml +4 -0
- data/.gitattributes +3 -0
- data/.github/dependabot.yml +7 -0
- data/.github/issue_template.md +19 -0
- data/.github/pull_request_template.md +6 -0
- data/.github/workflows/claude-code-review.yml +46 -0
- data/.github/workflows/claude.yml +148 -0
- data/.github/workflows/coveralls.yml +53 -0
- data/.github/workflows/rubyonrails.yml +94 -0
- data/.gitignore +25 -0
- data/.rubocop.yml +82 -0
- data/.travis.yml +44 -0
- data/CHANGELOG.md +147 -0
- data/CONTRIBUTING.md +42 -0
- data/Gemfile +44 -0
- data/LICENSE +20 -0
- data/README.md +158 -0
- data/Rakefile +206 -0
- data/app/assets/builds/.keep +0 -0
- data/app/assets/config/manifest.js +1 -0
- data/app/assets/fonts/comfy/admin/cms/lib/redactor-font.eot +0 -0
- data/app/assets/javascripts/comfy/admin/cms/application.js +27 -0
- data/app/assets/javascripts/comfy/admin/cms/base.js +48 -0
- data/app/assets/javascripts/comfy/admin/cms/categories.js +17 -0
- data/app/assets/javascripts/comfy/admin/cms/codemirror.js +43 -0
- data/app/assets/javascripts/comfy/admin/cms/custom.js +1 -0
- data/app/assets/javascripts/comfy/admin/cms/diff.js +12 -0
- data/app/assets/javascripts/comfy/admin/cms/file_link.js +96 -0
- data/app/assets/javascripts/comfy/admin/cms/file_upload.js +229 -0
- data/app/assets/javascripts/comfy/admin/cms/files_modal.js +97 -0
- data/app/assets/javascripts/comfy/admin/cms/page_fragments.js +22 -0
- data/app/assets/javascripts/comfy/admin/cms/slugify.js +34 -0
- data/app/assets/javascripts/comfy/admin/cms/sortable_list.js +49 -0
- data/app/assets/javascripts/comfy/admin/cms/timepicker.js +38 -0
- data/app/assets/javascripts/comfy/admin/cms/wysiwyg.js +91 -0
- data/app/assets/javascripts/comfy/vendor/diff/diff_match_patch.min.js +49 -0
- data/app/assets/javascripts/comfy/vendor/diff/pretty_text_diff.js +88 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr.min.js +2 -0
- data/app/assets/javascripts/comfy/vendor/fontawesome.js +5 -0
- data/app/assets/javascripts/comfy/vendor/redactor/definedlinks.js +50 -0
- data/app/assets/javascripts/comfy/vendor/redactor/filemanager.js +79 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ar.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/az.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ba.js +79 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/bg.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/by.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ca.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/cs.js +87 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/da.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/de.js +80 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/el.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/en.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/eo.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/es.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/es_AR.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/fa.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/fi.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/fr.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ge.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/gr.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/he.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/hr.js +78 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/hu.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/id.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/it.js +78 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ja.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/kn.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ko.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/lt.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/lv.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/mk.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/nb.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/nl.js +80 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/pl.js +78 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/pt-BR.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/pt.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ro.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ru.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/sk.js +76 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/sl.js +79 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/sq.js +79 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/sr-CIR.js +79 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/sr-LAT.js +79 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/sv.js +74 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/th.js +74 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/tr.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/ua.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/uk.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/vi.js +74 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/zh-CN.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/zh-TW.js +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/imagemanager.js +68 -0
- data/app/assets/javascripts/comfy/vendor/redactor/table.js +348 -0
- data/app/assets/javascripts/comfy/vendor/redactor/video.js +82 -0
- data/app/assets/javascripts/comfy/vendor/redactor.js +9563 -0
- data/app/assets/stylesheets/comfy/admin/cms/application.sass +11 -0
- data/app/assets/stylesheets/comfy/admin/cms/base.sass +256 -0
- data/app/assets/stylesheets/comfy/admin/cms/codemirror_overrides.sass +19 -0
- data/app/assets/stylesheets/comfy/admin/cms/custom.sass +1 -0
- data/app/assets/stylesheets/comfy/admin/cms/redactor_overrides.sass +22 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_alert.scss +51 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_badge.scss +54 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_breadcrumb.scss +41 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_button-group.scss +163 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_buttons.scss +137 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_card.scss +289 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_carousel.scss +197 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_close.scss +41 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_code.scss +48 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_custom-forms.scss +507 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_dropdown.scss +191 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_forms.scss +330 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_functions.scss +86 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_grid.scss +52 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_images.scss +42 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_input-group.scss +193 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_jumbotron.scss +17 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_list-group.scss +149 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_media.scss +8 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_mixins.scss +47 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_modal.scss +229 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_nav.scss +120 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_navbar.scss +294 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_pagination.scss +73 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_popover.scss +171 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_print.scss +141 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_progress.scss +43 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_reboot.scss +483 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_root.scss +19 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_spinners.scss +55 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_tables.scss +185 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_toasts.scss +44 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_tooltip.scss +115 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_transitions.scss +20 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_type.scss +125 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_utilities.scss +17 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/_variables.scss +1123 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/bootstrap-grid.scss +29 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/bootstrap-reboot.scss +12 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/bootstrap.scss +44 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_alert.scss +13 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_background-variant.scss +21 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_badge.scss +17 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_border-radius.scss +63 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_box-shadow.scss +20 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_breakpoints.scss +123 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_buttons.scss +107 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_caret.scss +62 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_clearfix.scss +7 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_deprecate.scss +10 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_float.scss +14 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_forms.scss +192 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_gradients.scss +45 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_grid-framework.scss +66 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_grid.scss +51 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_hover.scss +37 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_image.scss +36 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_list-group.scss +21 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_lists.scss +7 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_nav-divider.scss +10 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_pagination.scss +22 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_reset-text.scss +17 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_resize.scss +6 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_screen-reader.scss +33 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_size.scss +7 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_table-row.scss +39 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_text-emphasis.scss +16 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_text-hide.scss +11 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_text-truncate.scss +8 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_transition.scss +16 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/mixins/_visibility.scss +8 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_align.scss +8 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_background.scss +19 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_borders.scss +75 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_clearfix.scss +3 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_display.scss +26 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_embed.scss +39 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_flex.scss +51 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_float.scss +11 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_overflow.scss +5 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_position.scss +32 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_screenreaders.scss +11 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_shadows.scss +6 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_sizing.scss +20 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_spacing.scss +73 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_stretched-link.scss +19 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_text.scss +72 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/utilities/_visibility.scss +13 -0
- data/app/assets/stylesheets/comfy/vendor/bootstrap/vendor/_rfs.scss +204 -0
- data/app/assets/stylesheets/comfy/vendor/fontawesome.css +343 -0
- data/app/assets/stylesheets/comfy/vendor/redactor.css +948 -0
- data/app/controllers/application_controller.rb +5 -0
- data/app/controllers/comfy/admin/base_controller.rb +20 -0
- data/app/controllers/comfy/admin/cms/base_controller.rb +54 -0
- data/app/controllers/comfy/admin/cms/categories_controller.rb +38 -0
- data/app/controllers/comfy/admin/cms/files_controller.rb +140 -0
- data/app/controllers/comfy/admin/cms/layouts_controller.rb +69 -0
- data/app/controllers/comfy/admin/cms/pages_controller.rb +193 -0
- data/app/controllers/comfy/admin/cms/revisions/base_controller.rb +48 -0
- data/app/controllers/comfy/admin/cms/revisions/layout_controller.rb +16 -0
- data/app/controllers/comfy/admin/cms/revisions/page_controller.rb +28 -0
- data/app/controllers/comfy/admin/cms/revisions/snippet_controller.rb +16 -0
- data/app/controllers/comfy/admin/cms/revisions/translation_controller.rb +29 -0
- data/app/controllers/comfy/admin/cms/sites_controller.rb +68 -0
- data/app/controllers/comfy/admin/cms/snippets_controller.rb +66 -0
- data/app/controllers/comfy/admin/cms/translations_controller.rb +117 -0
- data/app/controllers/comfy/cms/assets_controller.rb +38 -0
- data/app/controllers/comfy/cms/base_controller.rb +35 -0
- data/app/controllers/comfy/cms/content_controller.rb +90 -0
- data/app/controllers/concerns/comfy/paginate.rb +11 -0
- data/app/controllers/concerns/comfy/reorder_action.rb +19 -0
- data/app/helpers/comfy/admin/cms_helper.rb +50 -0
- data/app/helpers/comfy/cms_helper.rb +71 -0
- data/app/models/comfy/cms/categorization.rb +23 -0
- data/app/models/comfy/cms/category.rb +22 -0
- data/app/models/comfy/cms/file.rb +65 -0
- data/app/models/comfy/cms/fragment.rb +65 -0
- data/app/models/comfy/cms/layout.rb +119 -0
- data/app/models/comfy/cms/page.rb +182 -0
- data/app/models/comfy/cms/revision.rb +10 -0
- data/app/models/comfy/cms/site.rb +93 -0
- data/app/models/comfy/cms/snippet.rb +43 -0
- data/app/models/comfy/cms/translation.rb +47 -0
- data/app/models/concerns/comfy/cms/with_categories.rb +51 -0
- data/app/models/concerns/comfy/cms/with_fragments.rb +123 -0
- data/app/views/comfy/admin/cms/categories/_categories.html.haml +4 -0
- data/app/views/comfy/admin/cms/categories/_edit.html.haml +7 -0
- data/app/views/comfy/admin/cms/categories/_form.html.haml +5 -0
- data/app/views/comfy/admin/cms/categories/_index.html.haml +28 -0
- data/app/views/comfy/admin/cms/categories/_show.html.haml +15 -0
- data/app/views/comfy/admin/cms/categories/create.js.erb +7 -0
- data/app/views/comfy/admin/cms/categories/destroy.js.erb +8 -0
- data/app/views/comfy/admin/cms/categories/edit.js.erb +3 -0
- data/app/views/comfy/admin/cms/categories/update.js.erb +6 -0
- data/app/views/comfy/admin/cms/files/_file.html.haml +31 -0
- data/app/views/comfy/admin/cms/files/_form.html.haml +26 -0
- data/app/views/comfy/admin/cms/files/_modal.html.haml +3 -0
- data/app/views/comfy/admin/cms/files/destroy.js.erb +4 -0
- data/app/views/comfy/admin/cms/files/edit.html.haml +5 -0
- data/app/views/comfy/admin/cms/files/index.html.haml +31 -0
- data/app/views/comfy/admin/cms/files/new.html.haml +5 -0
- data/app/views/comfy/admin/cms/fragments/_form_fragment_attachments.html.haml +23 -0
- data/app/views/comfy/admin/cms/fragments/_form_fragments.html.haml +38 -0
- data/app/views/comfy/admin/cms/layouts/_form.html.haml +20 -0
- data/app/views/comfy/admin/cms/layouts/_index_branch.html.haml +26 -0
- data/app/views/comfy/admin/cms/layouts/edit.html.haml +9 -0
- data/app/views/comfy/admin/cms/layouts/index.html.haml +10 -0
- data/app/views/comfy/admin/cms/layouts/new.html.haml +5 -0
- data/app/views/comfy/admin/cms/pages/_form.html.haml +31 -0
- data/app/views/comfy/admin/cms/pages/_index_branch.html.haml +44 -0
- data/app/views/comfy/admin/cms/pages/edit.html.haml +14 -0
- data/app/views/comfy/admin/cms/pages/index.html.haml +13 -0
- data/app/views/comfy/admin/cms/pages/new.html.haml +5 -0
- data/app/views/comfy/admin/cms/pages/toggle_branch.js.erb +19 -0
- data/app/views/comfy/admin/cms/revisions/_sidebar.html.haml +2 -0
- data/app/views/comfy/admin/cms/revisions/show.html.haml +36 -0
- data/app/views/comfy/admin/cms/sites/_form.html.haml +15 -0
- data/app/views/comfy/admin/cms/sites/edit.html.haml +5 -0
- data/app/views/comfy/admin/cms/sites/index.html.haml +28 -0
- data/app/views/comfy/admin/cms/sites/new.html.haml +5 -0
- data/app/views/comfy/admin/cms/snippets/_form.html.haml +19 -0
- data/app/views/comfy/admin/cms/snippets/edit.html.haml +9 -0
- data/app/views/comfy/admin/cms/snippets/index.html.haml +33 -0
- data/app/views/comfy/admin/cms/snippets/new.html.haml +5 -0
- data/app/views/comfy/admin/cms/translations/_form.html.haml +20 -0
- data/app/views/comfy/admin/cms/translations/_sidebar.html.haml +19 -0
- data/app/views/comfy/admin/cms/translations/edit.html.haml +10 -0
- data/app/views/comfy/admin/cms/translations/new.html.haml +5 -0
- data/app/views/kaminari/comfy/_first_page.html.haml +3 -0
- data/app/views/kaminari/comfy/_gap.html.haml +2 -0
- data/app/views/kaminari/comfy/_last_page.html.haml +3 -0
- data/app/views/kaminari/comfy/_next_page.html.haml +2 -0
- data/app/views/kaminari/comfy/_page.html.haml +2 -0
- data/app/views/kaminari/comfy/_paginator.html.haml +11 -0
- data/app/views/kaminari/comfy/_prev_page.html.haml +2 -0
- data/app/views/layouts/comfy/admin/cms/_body.html.haml +14 -0
- data/app/views/layouts/comfy/admin/cms/_flash.html.haml +4 -0
- data/app/views/layouts/comfy/admin/cms/_footer_js.html.haml +6 -0
- data/app/views/layouts/comfy/admin/cms/_head.html.haml +19 -0
- data/app/views/layouts/comfy/admin/cms/_left.html.haml +46 -0
- data/app/views/layouts/comfy/admin/cms/_right.html.haml +5 -0
- data/app/views/layouts/comfy/admin/cms.html.haml +4 -0
- data/bin/bundle +3 -0
- data/bin/rails +4 -0
- data/bin/rake +4 -0
- data/bin/setup +36 -0
- data/bin/update +31 -0
- data/bin/yarn +11 -0
- data/comfy_middle_seat.gemspec +35 -0
- data/config/application.rb +62 -0
- data/config/boot.rb +5 -0
- data/config/cable.yml +10 -0
- data/config/cms_routes.rb +8 -0
- data/config/database.yml +40 -0
- data/config/environment.rb +7 -0
- data/config/environments/development.rb +81 -0
- data/config/environments/production.rb +93 -0
- data/config/environments/test.rb +74 -0
- data/config/initializers/comfortable_media_surfer.rb +122 -0
- data/config/initializers/content_security_policy.rb +27 -0
- data/config/initializers/filter_parameter_logging.rb +10 -0
- data/config/initializers/inflections.rb +18 -0
- data/config/initializers/json.rb +11 -0
- data/config/initializers/new_framework_defaults_7_0.rb +144 -0
- data/config/initializers/new_framework_defaults_7_1.rb +225 -0
- data/config/initializers/permissions_policy.rb +15 -0
- data/config/locales/ar.yml +268 -0
- data/config/locales/ca.yml +268 -0
- data/config/locales/cs.yml +268 -0
- data/config/locales/da.yml +268 -0
- data/config/locales/de.yml +268 -0
- data/config/locales/en.yml +268 -0
- data/config/locales/es.yml +268 -0
- data/config/locales/fi.yml +268 -0
- data/config/locales/fr.yml +268 -0
- data/config/locales/gr.yml +268 -0
- data/config/locales/hr.yml +268 -0
- data/config/locales/it.yml +268 -0
- data/config/locales/ja.yml +268 -0
- data/config/locales/nb.yml +268 -0
- data/config/locales/nl.yml +268 -0
- data/config/locales/pl.yml +268 -0
- data/config/locales/pt-BR.yml +268 -0
- data/config/locales/ru.yml +268 -0
- data/config/locales/sk.yml +268 -0
- data/config/locales/sv.yml +268 -0
- data/config/locales/tr.yml +268 -0
- data/config/locales/uk.yml +268 -0
- data/config/locales/zh-CN.yml +268 -0
- data/config/locales/zh-TW.yml +268 -0
- data/config/puma.rb +43 -0
- data/config/storage.yml +35 -0
- data/config.ru +6 -0
- data/db/cms_seeds/sample-site/files/_default.jpg.yml +5 -0
- data/db/cms_seeds/sample-site/files/default.jpg +0 -0
- data/db/cms_seeds/sample-site/layouts/default/content.html +16 -0
- data/db/cms_seeds/sample-site/layouts/default/nested/content.html +14 -0
- data/db/cms_seeds/sample-site/pages/index/child_a/content.html +7 -0
- data/db/cms_seeds/sample-site/pages/index/child_b/child_a/content.html +6 -0
- data/db/cms_seeds/sample-site/pages/index/child_b/content.html +6 -0
- data/db/cms_seeds/sample-site/pages/index/cms logo.png +0 -0
- data/db/cms_seeds/sample-site/pages/index/content.es.html +6 -0
- data/db/cms_seeds/sample-site/pages/index/content.fr.html +6 -0
- data/db/cms_seeds/sample-site/pages/index/content.html +25 -0
- data/db/cms_seeds/sample-site/pages/index/footer.png +0 -0
- data/db/cms_seeds/sample-site/pages/index/header.png +0 -0
- data/db/cms_seeds/sample-site/snippets/default.html +8 -0
- data/db/migrate/00_create_active_storage_tables.active_storage.rb +50 -0
- data/db/migrate/01_create_cms.rb +142 -0
- data/db/migrate/02_add_markdown_to_snippets.rb +5 -0
- data/gemfiles/7.2.gemfile +36 -0
- data/gemfiles/8.0.gemfile +36 -0
- data/gemfiles/8.1.gemfile +36 -0
- data/lib/comfortable_media_surfer/access_control/admin_authentication.rb +22 -0
- data/lib/comfortable_media_surfer/access_control/admin_authorization.rb +10 -0
- data/lib/comfortable_media_surfer/access_control/public_authentication.rb +10 -0
- data/lib/comfortable_media_surfer/access_control/public_authorization.rb +10 -0
- data/lib/comfortable_media_surfer/configuration.rb +138 -0
- data/lib/comfortable_media_surfer/content/block.rb +12 -0
- data/lib/comfortable_media_surfer/content/params_parser.rb +149 -0
- data/lib/comfortable_media_surfer/content/renderer.rb +146 -0
- data/lib/comfortable_media_surfer/content/tag.rb +48 -0
- data/lib/comfortable_media_surfer/content/tags/asset.rb +57 -0
- data/lib/comfortable_media_surfer/content/tags/audio.rb +39 -0
- data/lib/comfortable_media_surfer/content/tags/breadcrumbs.rb +43 -0
- data/lib/comfortable_media_surfer/content/tags/checkbox.rb +27 -0
- data/lib/comfortable_media_surfer/content/tags/children.rb +52 -0
- data/lib/comfortable_media_surfer/content/tags/date.rb +19 -0
- data/lib/comfortable_media_surfer/content/tags/datetime.rb +42 -0
- data/lib/comfortable_media_surfer/content/tags/file.rb +70 -0
- data/lib/comfortable_media_surfer/content/tags/file_link.rb +58 -0
- data/lib/comfortable_media_surfer/content/tags/files.rb +41 -0
- data/lib/comfortable_media_surfer/content/tags/fragment.rb +64 -0
- data/lib/comfortable_media_surfer/content/tags/helper.rb +53 -0
- data/lib/comfortable_media_surfer/content/tags/image.rb +56 -0
- data/lib/comfortable_media_surfer/content/tags/markdown.rb +22 -0
- data/lib/comfortable_media_surfer/content/tags/mixins/file_content.rb +42 -0
- data/lib/comfortable_media_surfer/content/tags/number.rb +18 -0
- data/lib/comfortable_media_surfer/content/tags/page_file_link.rb +86 -0
- data/lib/comfortable_media_surfer/content/tags/partial.rb +47 -0
- data/lib/comfortable_media_surfer/content/tags/siblings.rb +66 -0
- data/lib/comfortable_media_surfer/content/tags/snippet.rb +36 -0
- data/lib/comfortable_media_surfer/content/tags/template.rb +42 -0
- data/lib/comfortable_media_surfer/content/tags/text.rb +18 -0
- data/lib/comfortable_media_surfer/content/tags/textarea.rb +19 -0
- data/lib/comfortable_media_surfer/content/tags/wysiwyg.rb +19 -0
- data/lib/comfortable_media_surfer/content/tags.rb +29 -0
- data/lib/comfortable_media_surfer/content.rb +11 -0
- data/lib/comfortable_media_surfer/engine.rb +24 -0
- data/lib/comfortable_media_surfer/error.rb +24 -0
- data/lib/comfortable_media_surfer/extensions/acts_as_tree.rb +114 -0
- data/lib/comfortable_media_surfer/extensions/has_revisions.rb +68 -0
- data/lib/comfortable_media_surfer/extensions.rb +8 -0
- data/lib/comfortable_media_surfer/form_builder.rb +43 -0
- data/lib/comfortable_media_surfer/render_methods.rb +106 -0
- data/lib/comfortable_media_surfer/routing.rb +87 -0
- data/lib/comfortable_media_surfer/seeds/file/exporter.rb +37 -0
- data/lib/comfortable_media_surfer/seeds/file/importer.rb +55 -0
- data/lib/comfortable_media_surfer/seeds/layout/exporter.rb +38 -0
- data/lib/comfortable_media_surfer/seeds/layout/importer.rb +60 -0
- data/lib/comfortable_media_surfer/seeds/page/exporter.rb +88 -0
- data/lib/comfortable_media_surfer/seeds/page/importer.rb +245 -0
- data/lib/comfortable_media_surfer/seeds/snippet/exporter.rb +32 -0
- data/lib/comfortable_media_surfer/seeds/snippet/importer.rb +47 -0
- data/lib/comfortable_media_surfer/seeds.rb +110 -0
- data/lib/comfortable_media_surfer/version.rb +3 -0
- data/lib/comfortable_media_surfer/view_hooks.rb +33 -0
- data/lib/comfortable_media_surfer.rb +56 -0
- data/lib/comfy_middle_seat/version.rb +5 -0
- data/lib/comfy_middle_seat.rb +3 -0
- data/lib/generators/comfy/cms/README +21 -0
- data/lib/generators/comfy/cms/assets_generator.rb +16 -0
- data/lib/generators/comfy/cms/cms_generator.rb +69 -0
- data/lib/generators/comfy/cms/controllers_generator.rb +15 -0
- data/lib/generators/comfy/cms/models_generator.rb +15 -0
- data/lib/generators/comfy/cms/views_generator.rb +15 -0
- data/lib/generators/comfy/scaffold/scaffold_generator.rb +79 -0
- data/lib/generators/comfy/scaffold/templates/controller.rb.tt +62 -0
- data/lib/generators/comfy/scaffold/templates/migration.rb.tt +11 -0
- data/lib/generators/comfy/scaffold/templates/model.rb.tt +21 -0
- data/lib/generators/comfy/scaffold/templates/tests/controller.rb.tt +115 -0
- data/lib/generators/comfy/scaffold/templates/tests/fixture.yml.tt +4 -0
- data/lib/generators/comfy/scaffold/templates/tests/model.rb.tt +26 -0
- data/lib/generators/comfy/scaffold/templates/views/_form.haml.tt +7 -0
- data/lib/generators/comfy/scaffold/templates/views/edit.haml.tt +5 -0
- data/lib/generators/comfy/scaffold/templates/views/index.haml.tt +21 -0
- data/lib/generators/comfy/scaffold/templates/views/new.haml.tt +5 -0
- data/lib/generators/comfy/scaffold/templates/views/show.haml.tt +4 -0
- data/lib/tasks/cms_assets.rake +19 -0
- data/lib/tasks/cms_seeds.rake +40 -0
- data/package-lock.json +989 -0
- data/package.json +23 -0
- data/public/favicon.ico +0 -0
- data/rakelib/create_release.rake +82 -0
- metadata +665 -0
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Contribute your code to ComfortableMediaSurfer in 5 easy steps:
|
|
4
|
+
|
|
5
|
+
### 1. Fork it
|
|
6
|
+
|
|
7
|
+
Fork the project. Optionally, create a branch you want to work on.
|
|
8
|
+
|
|
9
|
+
### 2. Get it running locally
|
|
10
|
+
|
|
11
|
+
- Install gem dependencies with `bundle install`
|
|
12
|
+
- There's nothing to configure, by default database is SQLite so it will be
|
|
13
|
+
created for you. Just run `bundle exec rake db:migrate`
|
|
14
|
+
- Prepare the environment by running `rails comfy:compile_assets`, and
|
|
15
|
+
`rake db:test:prepare`
|
|
16
|
+
- Make sure that existing tests are passing by running `bundle exec rake test`.
|
|
17
|
+
This uses six isolated workers by default, merges their coverage, and records
|
|
18
|
+
per-file runtimes in `tmp/parallel_runtime_test.log` for future balancing.
|
|
19
|
+
Set `PARALLEL_WORKERS` to tune the worker count, or run
|
|
20
|
+
`bundle exec rake test:serial` for a serial coverage run.
|
|
21
|
+
- There are system tests that can be run with `bundle exec rake test:system`.
|
|
22
|
+
You need to have `chromedriver` installed for that.
|
|
23
|
+
- You should be able to start the app via `bin/rails s` and navigate to http://localhost:3000/admin
|
|
24
|
+
and log in with username 'user' and password 'pass'
|
|
25
|
+
|
|
26
|
+
### 3. Hack away
|
|
27
|
+
|
|
28
|
+
- Create a few small pull requests instead of a humoungous one. I can merge small stuff faster.
|
|
29
|
+
- When adding new code just make sure it follows the same style as the existing code.
|
|
30
|
+
- Avoid adding 3rd party dependencies if you can.
|
|
31
|
+
- Tests please, but nothing complicated. UnitTest / Fixtures all the way. Make sure all tests pass.
|
|
32
|
+
- Run `bundle exec rubocop` and fix any issues raised.
|
|
33
|
+
|
|
34
|
+
### 4. Make a pull request
|
|
35
|
+
|
|
36
|
+
- If you never done it before read this: https://help.github.com/articles/using-pull-requests
|
|
37
|
+
- When PR is submitted check if Github actions CI ran all tests successfully
|
|
38
|
+
|
|
39
|
+
### 5. Done!
|
|
40
|
+
|
|
41
|
+
If everything is good your changes will be merged into master branch. Eventually
|
|
42
|
+
a new version of gem will be published.
|
data/Gemfile
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
source 'https://rubygems.org'
|
|
4
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
|
5
|
+
|
|
6
|
+
gemspec
|
|
7
|
+
|
|
8
|
+
gem 'rails', '~> 8.1.0'
|
|
9
|
+
|
|
10
|
+
group :development, :test do
|
|
11
|
+
gem 'autoprefixer-rails', '~> 10.4.21.0'
|
|
12
|
+
gem 'byebug', '~> 13.0.0', platforms: %i[mri mingw x64_mingw]
|
|
13
|
+
gem 'gem-release'
|
|
14
|
+
gem 'image_processing', '>= 1.12.2'
|
|
15
|
+
gem 'propshaft', '~> 1.3.1'
|
|
16
|
+
gem 'sqlite3', '>= 2.1'
|
|
17
|
+
# gem 'mysql2', '~> 0.5'
|
|
18
|
+
# gem 'pg', '~> 1.5.4'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
group :development do
|
|
22
|
+
gem 'listen', '~> 3.10.0'
|
|
23
|
+
gem 'web-console', '~> 4.2'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
group :test do
|
|
27
|
+
gem 'brakeman'
|
|
28
|
+
gem 'bundler-audit', '~> 0.9.1'
|
|
29
|
+
gem 'coveralls_reborn', '~> 0.29.0', require: false
|
|
30
|
+
gem 'cuprite', '>= 0.15'
|
|
31
|
+
gem 'diffy'
|
|
32
|
+
gem 'equivalent-xml', '~> 0.6.0'
|
|
33
|
+
gem 'minitest', '< 6.0.0'
|
|
34
|
+
gem 'minitest-reporters', '>= 1.6.1'
|
|
35
|
+
gem 'mocha', '>= 2.3.0', require: false
|
|
36
|
+
gem 'ostruct'
|
|
37
|
+
gem 'parallel_tests', '~> 5.7', require: false
|
|
38
|
+
gem 'puma'
|
|
39
|
+
gem 'rails-controller-testing', '~> 1.0.5'
|
|
40
|
+
gem 'rubocop', require: false
|
|
41
|
+
gem 'rubocop-minitest'
|
|
42
|
+
gem 'rubocop-rails'
|
|
43
|
+
gem 'simplecov', '~> 0.22.0', require: false
|
|
44
|
+
end
|
data/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2010-2019 Oleg Khabarov, (c) 2024 Shakacode LLC
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
[](https://github.com/avonderluft/comfy-middle-seat/actions/workflows/rubyonrails.yml)
|
|
2
|
+
[](https://rubygems.org/gems/comfy_middle_seat)
|
|
3
|
+
[](https://rubygems.org/gems/comfy_middle_seat)
|
|
4
|
+
[](https://github.com/avonderluft/comfy-middle-seat/releases)
|
|
5
|
+
|
|
6
|
+
# Comfy Middle Seat
|
|
7
|
+
|
|
8
|
+
Comfy Middle Seat is a Rails CMS (Content Management System) engine, published as `comfy_middle_seat`. It keeps the Comfortable Media Surfer implementation and pays homage to the original Comfortable Mexican Sofa—with the same C.M.S. initials and a new place to sit.
|
|
9
|
+
|
|
10
|
+
The `ComfortableMediaSurfer` Ruby namespace, configuration, and internal paths remain unchanged. Only the gem's public name changes; there is no need to rename existing Surfer initializers or database tables.
|
|
11
|
+
|
|
12
|
+
## Project History
|
|
13
|
+
|
|
14
|
+
- **[Comfortable Mexican Sofa](https://github.com/comfy/comfortable-mexican-sofa)**, created by Oleg Khabarov, is the original Rails CMS on which this project is built.
|
|
15
|
+
- **[Comfortable Media Surfer](https://github.com/shakacode/comfortable-media-surfer)** revived Sofa under ShakaCode, continuing its development for modern Rails applications.
|
|
16
|
+
- **Comfy Middle Seat** is a fork of Comfortable Media Surfer, published under a new gem name while retaining its implementation and API.
|
|
17
|
+
|
|
18
|
+
See the [CHANGELOG](CHANGELOG.md) for the inherited development history, and the original [Sofa releases](https://github.com/comfy/comfortable-mexican-sofa/releases) and [Surfer releases](https://github.com/shakacode/comfortable-media-surfer/releases) for earlier releases.
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- Simple drop-in integration with Rails 7.2+ apps with minimal configuration
|
|
23
|
+
* The CMS keeps clear from the rest of your application
|
|
24
|
+
* Powerful page templating capability using [Content Tags](https://github.com/shakacode/comfortable-media-surfer/wiki/Docs:-Content-Tags)
|
|
25
|
+
* [Multiple Sites](https://github.com/shakacode/comfortable-media-surfer/wiki/Docs:-Sites) from a single installation
|
|
26
|
+
* Multi-Language Support (i18n) (ca, cs, da, de, en, es, fi, fr, gr, hr, it, ja, nb, nl, pl, pt-BR, ru, sv, tr, uk, zh-CN, zh-TW) and page localization.
|
|
27
|
+
* [CMS Seeds](https://github.com/shakacode/comfortable-media-surfer/wiki/Docs:-CMS-Seeds) for initial content population
|
|
28
|
+
* [Revision History](https://github.com/shakacode/comfortable-media-surfer/wiki/Docs:-Revisions) to revert changes
|
|
29
|
+
* [Extendable Admin Area](https://github.com/shakacode/comfortable-media-surfer/wiki/HowTo:-Reusing-Admin-Area) built with [Bootstrap 4](http://getbootstrap.com) (responsive design). Using [CodeMirror](http://codemirror.net) for HTML and Markdown highlighing and [Redactor](http://imperavi.com/redactor) as the WYSIWYG editor.
|
|
30
|
+
|
|
31
|
+
## Dependencies
|
|
32
|
+
|
|
33
|
+
- File attachments are handled by [ActiveStorage](https://github.com/rails/rails/tree/master/activestorage). Make sure that you can run appropriate migrations by running: `rails active_storage:install`
|
|
34
|
+
- Image resizing is done with with [ImageMagick](http://www.imagemagick.org/script/download.php), so make sure it's installed.
|
|
35
|
+
- Pagination is handled by [kaminari](https://github.com/amatsuda/kaminari).
|
|
36
|
+
|
|
37
|
+
## Compatibility
|
|
38
|
+
|
|
39
|
+
On Ruby 3.2+, 4.x, Rails 7.2+, 8.x
|
|
40
|
+
|
|
41
|
+
## Installation
|
|
42
|
+
|
|
43
|
+
Add gem definition to your Gemfile:
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
gem "comfy_middle_seat", "~> 3.1.0"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Then from the Rails project's root run:
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
bundle install
|
|
53
|
+
rails generate comfy:cms
|
|
54
|
+
rails db:migrate
|
|
55
|
+
rails comfy:compile_assets
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Now take a look inside your `config/routes.rb` file. You'll see where routes attach for the admin area and content serving. Make sure that content serving route appears as a very last item or it will make all other routes to be inaccessible.
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
comfy_route :cms_admin, path: "/admin"
|
|
62
|
+
comfy_route :cms, path: "/"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Converting from Comfortable Media Surfer, Comfortable Mexican Sofa, or Occams
|
|
66
|
+
|
|
67
|
+
### From Surfer to Middle Seat
|
|
68
|
+
|
|
69
|
+
Replace `comfortable_media_surfer` in your Gemfile with `comfy_middle_seat` and run `bundle install`. Do not include both gems. Existing `ComfortableMediaSurfer` configuration and database tables remain unchanged.
|
|
70
|
+
|
|
71
|
+
### From Sofa to Middle Seat
|
|
72
|
+
|
|
73
|
+
The database structure is the same. Your Sofa project will also need to be upgraded to >= Rails 7.x
|
|
74
|
+
Then you should simply be able to update your Gemfile thus, and run bundle
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
gem 'comfy_middle_seat', '~> 3.1.0'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### From Occams to Middle Seat
|
|
81
|
+
|
|
82
|
+
Again the project must be >= Rails 7.x. Since the schema is different, executing this SQL should get you set for Middle Seat
|
|
83
|
+
|
|
84
|
+
```sql
|
|
85
|
+
ALTER TABLE occams_cms_categories RENAME TO comfy_cms_categories;
|
|
86
|
+
ALTER TABLE occams_cms_categorizations RENAME TO comfy_cms_categorizations;
|
|
87
|
+
ALTER TABLE occams_cms_files RENAME TO comfy_cms_files;
|
|
88
|
+
ALTER TABLE occams_cms_fragments RENAME TO comfy_cms_fragments;
|
|
89
|
+
ALTER TABLE occams_cms_layouts RENAME TO comfy_cms_layouts;
|
|
90
|
+
ALTER TABLE occams_cms_pages RENAME TO comfy_cms_pages;
|
|
91
|
+
ALTER TABLE occams_cms_revisions RENAME TO comfy_cms_revisions;
|
|
92
|
+
ALTER TABLE occams_cms_sites RENAME TO comfy_cms_sites;
|
|
93
|
+
ALTER TABLE occams_cms_snippets RENAME TO comfy_cms_snippets;
|
|
94
|
+
ALTER TABLE occams_cms_translations RENAME TO comfy_cms_translations;
|
|
95
|
+
UPDATE comfy_cms_categories SET categorized_type = 'Comfy::Cms::Page' WHERE categorized_type = 'Occams::Cms::Page';
|
|
96
|
+
UPDATE comfy_cms_categorizations SET categorized_type = 'Comfy::Cms::Page' WHERE categorized_type = 'Occams::Cms::Page';
|
|
97
|
+
UPDATE comfy_cms_fragments SET record_type = 'Comfy::Cms::Page' WHERE record_type = 'Occams::Cms::Page';
|
|
98
|
+
UPDATE comfy_cms_fragments SET record_type = 'Comfy::Cms::Layout' WHERE record_type = 'Occams::Cms::Layout';
|
|
99
|
+
UPDATE comfy_cms_fragments SET record_type = 'Comfy::Cms::Snippet' WHERE record_type = 'Occams::Cms::Snippet';
|
|
100
|
+
UPDATE comfy_cms_revisions SET record_type = 'Comfy::Cms::Page' WHERE record_type = 'Occams::Cms::Page';
|
|
101
|
+
UPDATE comfy_cms_revisions SET record_type = 'Comfy::Cms::Layout' WHERE record_type = 'Occams::Cms::Layout';
|
|
102
|
+
UPDATE comfy_cms_revisions SET record_type = 'Comfy::Cms::Snippet' WHERE record_type = 'Occams::Cms::Snippet';
|
|
103
|
+
UPDATE active_storage_attachments SET record_type = 'Comfy::Cms::File' WHERE record_type = 'Occams::Cms::File';
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Quick Start Guide
|
|
107
|
+
|
|
108
|
+
After finishing installation you should be able to navigate to http://localhost:3000/admin
|
|
109
|
+
|
|
110
|
+
Default username and password is 'user' and 'pass'. You probably want to change it right away. Admin credentials (among other things) can be found and changed in your app's CMS initializer: `config/initializers/comfortable_media_surfer.rb`. The initializer retains its Surfer name for compatibility.
|
|
111
|
+
|
|
112
|
+
Before creating pages and populating them with content we need to create a Site. Site defines a hostname, content path and its language.
|
|
113
|
+
|
|
114
|
+
After creating a Site, you need to make a Layout. Layout is the template of your pages; it defines some reusable content (like header and footer, for example) and places where the content goes. A very simple layout can look like this:
|
|
115
|
+
|
|
116
|
+
```html
|
|
117
|
+
<html>
|
|
118
|
+
<body>
|
|
119
|
+
<h1>{{ cms:text title }}</h1>
|
|
120
|
+
{{ cms:wysiwyg content }}
|
|
121
|
+
</body>
|
|
122
|
+
</html>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Once you have a layout, you may start creating pages and populating content. It's that easy.
|
|
126
|
+
|
|
127
|
+
## Documentation
|
|
128
|
+
|
|
129
|
+
The [Comfortable Media Surfer Wiki](https://github.com/shakacode/comfortable-media-surfer/wiki) remains the upstream reference for the inherited CMS features, including [Content Tags](https://github.com/shakacode/comfortable-media-surfer/wiki/Docs:-Content-Tags). The feature links above also point to that wiki. When following its installation instructions, use the `comfy_middle_seat` gem; Ruby examples using `ComfortableMediaSurfer` retain that namespace.
|
|
130
|
+
|
|
131
|
+
## Add-ons
|
|
132
|
+
|
|
133
|
+
If you want to add a Blog functionality to your app take a look at
|
|
134
|
+
[ComfyBlog](https://github.com/comfy/comfy-blog).
|
|
135
|
+
|
|
136
|
+

|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
#### Contributing
|
|
140
|
+
|
|
141
|
+
Comfy Middle Seat can run like any Rails application in development. It's as easy to work on as any other Rails app. For more detail see [CONTRIBUTING](CONTRIBUTING.md). The inherited development instructions may still refer to Comfortable Media Surfer.
|
|
142
|
+
|
|
143
|
+
#### Testing
|
|
144
|
+
|
|
145
|
+
- `bin/rails db:migrate RAILS_ENV=test`
|
|
146
|
+
- `rake db:test:prepare`
|
|
147
|
+
- `rake test`
|
|
148
|
+
|
|
149
|
+
#### Acknowledgements
|
|
150
|
+
|
|
151
|
+
- To [Oleg Khabarov](https://github.com/GBH) and the contributors to [Comfortable Mexican Sofa](https://github.com/comfy/comfortable-mexican-sofa), the original CMS.
|
|
152
|
+
- To [ShakaCode](https://github.com/shakacode) and the contributors to [Comfortable Media Surfer](https://github.com/shakacode/comfortable-media-surfer), whose revival this fork builds on.
|
|
153
|
+
- To [Roman Almeida](https://github.com/nasmorn) for contributing OEM License for [Redactor Text Editor](http://imperavi.com/redactor).
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
Copyright 2010-2019 Oleg Khabarov, 2024-2026 ShakaCode LLC, 2026 Andrew vonderLuft
|
|
158
|
+
Released under the [MIT license](LICENSE)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'config/application'
|
|
4
|
+
require 'open3'
|
|
5
|
+
require 'parallel_tests/tasks'
|
|
6
|
+
require 'rake/testtask'
|
|
7
|
+
require 'stringio'
|
|
8
|
+
|
|
9
|
+
Rails.application.load_tasks
|
|
10
|
+
|
|
11
|
+
module ComfortableMediaSurferTestOutput
|
|
12
|
+
SUMMARY = %r{(?<assertions>\d+) assertions, (?<errors>\d+) errors, (?<failures>\d+) failures, (?<skips>\d+) skips?, (?<tests>\d+) tests}
|
|
13
|
+
COLORS = { green: 32, yellow: 33, red: 31, cyan: 36 }.freeze
|
|
14
|
+
|
|
15
|
+
class Progress
|
|
16
|
+
def initialize(io)
|
|
17
|
+
@io = io
|
|
18
|
+
@line = +''
|
|
19
|
+
@pending = +''
|
|
20
|
+
@awaiting_blank = false
|
|
21
|
+
@expecting_progress = false
|
|
22
|
+
@printing_progress = false
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def feed(chunk)
|
|
26
|
+
chunk.each_char { |character| consume(character) }
|
|
27
|
+
flush
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def finish
|
|
31
|
+
flush
|
|
32
|
+
@io.puts if @printing_progress
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def consume(character)
|
|
38
|
+
return if character == "\r"
|
|
39
|
+
return finish_line if character == "\n"
|
|
40
|
+
|
|
41
|
+
if @expecting_progress && character.match?(%r{[.EFS]})
|
|
42
|
+
@printing_progress = true
|
|
43
|
+
@pending << character
|
|
44
|
+
elsif @printing_progress
|
|
45
|
+
flush
|
|
46
|
+
@io.puts
|
|
47
|
+
@printing_progress = false
|
|
48
|
+
@expecting_progress = false
|
|
49
|
+
@line = +character
|
|
50
|
+
else
|
|
51
|
+
@expecting_progress = false if @expecting_progress
|
|
52
|
+
@line << character
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def finish_line
|
|
57
|
+
flush
|
|
58
|
+
if @printing_progress
|
|
59
|
+
@io.puts
|
|
60
|
+
@expecting_progress = false
|
|
61
|
+
elsif @line.start_with?('# Running tests')
|
|
62
|
+
@awaiting_blank = true
|
|
63
|
+
elsif @awaiting_blank && @line.empty?
|
|
64
|
+
@expecting_progress = true
|
|
65
|
+
@awaiting_blank = false
|
|
66
|
+
end
|
|
67
|
+
@line.clear
|
|
68
|
+
@printing_progress = false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def flush
|
|
72
|
+
return if @pending.empty?
|
|
73
|
+
|
|
74
|
+
@io.print ComfortableMediaSurferTestOutput.progress_color(@pending)
|
|
75
|
+
@io.flush
|
|
76
|
+
@pending.clear
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
module_function
|
|
81
|
+
|
|
82
|
+
def capture(env, command)
|
|
83
|
+
output = +''
|
|
84
|
+
errors = +''
|
|
85
|
+
status = nil
|
|
86
|
+
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
87
|
+
progress = Progress.new($stdout)
|
|
88
|
+
|
|
89
|
+
Open3.popen3(env, *command) do |stdin, stdout, stderr, wait_thread|
|
|
90
|
+
stdin.close
|
|
91
|
+
error_reader = Thread.new { stderr.read }
|
|
92
|
+
loop do
|
|
93
|
+
chunk = stdout.readpartial(4096)
|
|
94
|
+
output << chunk
|
|
95
|
+
progress.feed(chunk)
|
|
96
|
+
end
|
|
97
|
+
rescue EOFError
|
|
98
|
+
errors = error_reader.value
|
|
99
|
+
status = wait_thread.value
|
|
100
|
+
ensure
|
|
101
|
+
progress.finish
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at
|
|
105
|
+
[output, errors, status, elapsed]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def color(text, name)
|
|
109
|
+
return text unless $stdout.tty? && !ENV.key?('NO_COLOR')
|
|
110
|
+
|
|
111
|
+
"\e[#{COLORS.fetch(name)}m#{text}\e[0m"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def progress_color(text)
|
|
115
|
+
return text unless $stdout.tty? && !ENV.key?('NO_COLOR')
|
|
116
|
+
|
|
117
|
+
highlighted = text.gsub('S', "\e[33mS\e[32m")
|
|
118
|
+
.gsub(%r{[EF]}) { |character| "\e[31m#{character}\e[32m" }
|
|
119
|
+
"\e[32m#{highlighted}\e[0m"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def summary(output)
|
|
123
|
+
counts = output.match(SUMMARY)
|
|
124
|
+
raise 'Could not read the parallel test summary' unless counts
|
|
125
|
+
|
|
126
|
+
"#{counts[:tests]} tests, #{counts[:assertions]} assertions, " \
|
|
127
|
+
"#{counts[:failures]} failures, #{counts[:errors]} errors, " \
|
|
128
|
+
"#{counts[:skips]} #{counts[:skips] == '1' ? 'skip' : 'skips'}"
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def run_parallel
|
|
132
|
+
workers = ENV.fetch('PARALLEL_WORKERS', '6')
|
|
133
|
+
skip_coverage = ENV.fetch('SKIP_COV', nil)
|
|
134
|
+
FileUtils.rm_rf('coverage')
|
|
135
|
+
FileUtils.mkdir_p('tmp')
|
|
136
|
+
Rake::Task['parallel:prepare'].invoke(workers)
|
|
137
|
+
|
|
138
|
+
env = {
|
|
139
|
+
'PARALLEL_COVERAGE' => skip_coverage ? nil : 'true',
|
|
140
|
+
'RECORD_RUNTIME' => 'true',
|
|
141
|
+
'SKIP_COV' => skip_coverage,
|
|
142
|
+
'NO_COLOR' => '1',
|
|
143
|
+
'TMPDIR' => ENV.fetch('COMFY_TEST_TMPDIR', '/tmp')
|
|
144
|
+
}
|
|
145
|
+
command = [
|
|
146
|
+
'bundle', 'exec', 'parallel_test', 'test',
|
|
147
|
+
'--type', 'test',
|
|
148
|
+
'--exclude-pattern', 'test/system/',
|
|
149
|
+
'-n', workers
|
|
150
|
+
]
|
|
151
|
+
|
|
152
|
+
puts color("Running tests (#{workers} workers)…", :cyan)
|
|
153
|
+
stdout, stderr, status, elapsed = capture(env, command)
|
|
154
|
+
unless status.success?
|
|
155
|
+
$stdout.write(stdout)
|
|
156
|
+
$stderr.write(stderr)
|
|
157
|
+
raise "Parallel tests failed with status #{status.exitstatus}"
|
|
158
|
+
end
|
|
159
|
+
$stderr.write(stderr) unless stderr.empty?
|
|
160
|
+
puts color(summary(stdout), :green)
|
|
161
|
+
puts color(format('Completed in %.1f seconds', elapsed), :cyan)
|
|
162
|
+
|
|
163
|
+
report_coverage unless skip_coverage
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def report_coverage
|
|
167
|
+
require 'simplecov'
|
|
168
|
+
SimpleCov.coverage_dir File.expand_path('coverage', __dir__)
|
|
169
|
+
result = SimpleCov::ResultMerger.merged_result
|
|
170
|
+
quietly { SimpleCov::Formatter::HTMLFormatter.new.format(result) }
|
|
171
|
+
coverage = format('Coverage: %<percent>.2f%% (%<covered>d/%<total>d) — coverage/index.html',
|
|
172
|
+
percent: result.covered_percent, covered: result.covered_lines, total: result.total_lines)
|
|
173
|
+
puts color(coverage, :green)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def quietly
|
|
177
|
+
previous = $stdout
|
|
178
|
+
$stdout = StringIO.new
|
|
179
|
+
yield
|
|
180
|
+
ensure
|
|
181
|
+
$stdout = previous
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
namespace :test do
|
|
186
|
+
task :prepare_serial do
|
|
187
|
+
FileUtils.rm_rf('coverage')
|
|
188
|
+
ENV['TMPDIR'] = ENV.fetch('COMFY_TEST_TMPDIR', '/tmp')
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
desc 'Run tests serially with coverage'
|
|
192
|
+
Rake::TestTask.new(:serial) do |task|
|
|
193
|
+
task.libs << 'test' << 'lib'
|
|
194
|
+
task.test_files = Rake::FileList['test/**/*_test.rb'].exclude('test/system/**/*_test.rb')
|
|
195
|
+
task.warning = false
|
|
196
|
+
end
|
|
197
|
+
Rake::Task['test:serial'].enhance(['test:prepare_serial'])
|
|
198
|
+
|
|
199
|
+
desc 'Run tests in isolated processes'
|
|
200
|
+
task(:parallel) { ComfortableMediaSurferTestOutput.run_parallel }
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
Rake::Task[:test].clear
|
|
204
|
+
|
|
205
|
+
desc 'Run tests in parallel (default: 6 workers)'
|
|
206
|
+
task test: 'test:parallel'
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//= link_tree ../builds
|
|
Binary file
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import jQuery from "jquery";
|
|
2
|
+
import ujs from "@rails/ujs";
|
|
3
|
+
|
|
4
|
+
window.jQuery = window.$ = jQuery;
|
|
5
|
+
ujs.start();
|
|
6
|
+
|
|
7
|
+
import "bootstrap/js/src/tab";
|
|
8
|
+
import "bootstrap/js/src/collapse";
|
|
9
|
+
|
|
10
|
+
import "../../vendor/diff/diff_match_patch.min";
|
|
11
|
+
import "../../vendor/diff/pretty_text_diff";
|
|
12
|
+
import "../../vendor/fontawesome";
|
|
13
|
+
|
|
14
|
+
import "./base";
|
|
15
|
+
import "./categories";
|
|
16
|
+
import "./codemirror";
|
|
17
|
+
import "./diff";
|
|
18
|
+
import "./file_link";
|
|
19
|
+
import "./file_upload";
|
|
20
|
+
import "./files_modal";
|
|
21
|
+
import "./page_fragments";
|
|
22
|
+
import "./sortable_list";
|
|
23
|
+
import "./slugify";
|
|
24
|
+
import "./timepicker";
|
|
25
|
+
import "./wysiwyg";
|
|
26
|
+
|
|
27
|
+
import "./custom";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
if (!window.CMS) window.CMS = {};
|
|
3
|
+
const CMS = window.CMS;
|
|
4
|
+
|
|
5
|
+
// TODO(glebm): Use the battle-tested universal onPageLoad code and enable Turbolinks+async in the demo app.
|
|
6
|
+
// See: https://gist.github.com/glebm/2496daf445877055447a6fac46509d9a
|
|
7
|
+
const isTurbolinks = "Turbolinks" in window && window.Turbolinks.supported;
|
|
8
|
+
if (isTurbolinks) {
|
|
9
|
+
document.addEventListener("turbolinks:load", () => {
|
|
10
|
+
window.CMS.init();
|
|
11
|
+
});
|
|
12
|
+
document.addEventListener("turbolinks:before-cache", () => {
|
|
13
|
+
window.CMS.dispose();
|
|
14
|
+
});
|
|
15
|
+
} else {
|
|
16
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
17
|
+
window.CMS.init();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
CMS.init = () => {
|
|
22
|
+
CMS.current_path = window.location.pathname;
|
|
23
|
+
CMS.slugify();
|
|
24
|
+
CMS.codemirror.init();
|
|
25
|
+
CMS.wysiwyg.init();
|
|
26
|
+
CMS.sortableList.init();
|
|
27
|
+
CMS.timepicker.init();
|
|
28
|
+
CMS.pageFragments();
|
|
29
|
+
CMS.categories();
|
|
30
|
+
CMS.files.init();
|
|
31
|
+
CMS.fileLinks();
|
|
32
|
+
CMS.fileUpload.init();
|
|
33
|
+
CMS.diff();
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
CMS.dispose = () => {
|
|
37
|
+
CMS.codemirror.dispose();
|
|
38
|
+
CMS.wysiwyg.dispose();
|
|
39
|
+
CMS.files.dispose();
|
|
40
|
+
CMS.fileLinks.dispose();
|
|
41
|
+
CMS.fileUpload.dispose();
|
|
42
|
+
CMS.sortableList.dispose();
|
|
43
|
+
CMS.timepicker.dispose();
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
CMS.getLocale = () =>
|
|
47
|
+
document.querySelector('meta[name="cms-locale"]').content;
|
|
48
|
+
})();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
window.CMS.categories = (root = document) => {
|
|
3
|
+
const widget = root.querySelector('.categories-widget');
|
|
4
|
+
if (widget === null) return;
|
|
5
|
+
const readSection = widget.querySelector('.read');
|
|
6
|
+
const editSection = widget.querySelector('.editable');
|
|
7
|
+
widget.querySelector('.read button.toggle-cat-edit').addEventListener('click', () => {
|
|
8
|
+
readSection.style.display = 'none';
|
|
9
|
+
editSection.style.display = 'block';
|
|
10
|
+
});
|
|
11
|
+
widget.querySelector('.editable button.toggle-cat-edit').addEventListener('click', () => {
|
|
12
|
+
editSection.style.display = 'none';
|
|
13
|
+
readSection.style.display = 'block';
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
})();
|
|
17
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import jQuery from "jquery";
|
|
2
|
+
import CodeMirror from "codemirror";
|
|
3
|
+
import "codemirror/mode/markdown/markdown";
|
|
4
|
+
import "codemirror/mode/htmlmixed/htmlmixed";
|
|
5
|
+
|
|
6
|
+
(() => {
|
|
7
|
+
const codeMirrorInstances = [];
|
|
8
|
+
window.CMS.codemirror = {
|
|
9
|
+
init(root = document) {
|
|
10
|
+
for (const textarea of root.querySelectorAll(
|
|
11
|
+
"textarea[data-cms-cm-mode]"
|
|
12
|
+
)) {
|
|
13
|
+
const codemirror = CodeMirror.fromTextArea(textarea, {
|
|
14
|
+
mode: textarea.dataset.cmsCmMode,
|
|
15
|
+
tabSize: 2,
|
|
16
|
+
lineWrapping: true,
|
|
17
|
+
autoCloseTags: true,
|
|
18
|
+
lineNumbers: true,
|
|
19
|
+
viewportMargin: Infinity,
|
|
20
|
+
});
|
|
21
|
+
codeMirrorInstances.push(codemirror);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const tabsRoot =
|
|
25
|
+
root.id === "form-fragments"
|
|
26
|
+
? root
|
|
27
|
+
: root.querySelector("#form-fragments");
|
|
28
|
+
jQuery(tabsRoot)
|
|
29
|
+
.find('a[data-toggle="tab"]')
|
|
30
|
+
.on("shown.bs.tab", () => {
|
|
31
|
+
for (const codemirror of codeMirrorInstances) {
|
|
32
|
+
codemirror.refresh();
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
dispose() {
|
|
37
|
+
for (const codemirror of codeMirrorInstances) {
|
|
38
|
+
codemirror.toTextArea();
|
|
39
|
+
}
|
|
40
|
+
codeMirrorInstances.length = 0;
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// Custom JS for the admin area
|