comfortable_media_surfer 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.codeclimate.yml +4 -0
- data/.gitattributes +2 -0
- data/.github/issue_template.md +19 -0
- data/.github/pull_request_template.md +6 -0
- data/.github/workflows/coveralls.yml +40 -0
- data/.github/workflows/rubyonrails.yml +51 -0
- data/.gitignore +21 -0
- data/.rubocop.yml +75 -0
- data/.travis.yml +44 -0
- data/CONTRIBUTING.md +35 -0
- data/Gemfile +38 -0
- data/LICENSE +20 -0
- data/README.md +109 -0
- data/Rakefile +5 -0
- data/app/assets/config/manifest.js +0 -0
- data/app/assets/fonts/comfy/admin/cms/lib/redactor-font.eot +0 -0
- data/app/assets/javascripts/comfy/admin/cms/application.js +39 -0
- data/app/assets/javascripts/comfy/admin/cms/base.js +46 -0
- data/app/assets/javascripts/comfy/admin/cms/categories.js +17 -0
- data/app/assets/javascripts/comfy/admin/cms/codemirror.js +31 -0
- data/app/assets/javascripts/comfy/admin/cms/custom.js +1 -0
- data/app/assets/javascripts/comfy/admin/cms/diff.js +10 -0
- data/app/assets/javascripts/comfy/admin/cms/file_link.js +67 -0
- data/app/assets/javascripts/comfy/admin/cms/file_upload.js +194 -0
- data/app/assets/javascripts/comfy/admin/cms/files_modal.js +40 -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 +40 -0
- data/app/assets/javascripts/comfy/admin/cms/timepicker.js +30 -0
- data/app/assets/javascripts/comfy/admin/cms/wysiwyg.js +72 -0
- data/app/assets/javascripts/comfy/vendor/Moxie.swf +0 -0
- data/app/assets/javascripts/comfy/vendor/Moxie.xap +0 -0
- data/app/assets/javascripts/comfy/vendor/bootstrap.bundle.min.js +7 -0
- data/app/assets/javascripts/comfy/vendor/bootstrap.bundle.min.js.map +1 -0
- data/app/assets/javascripts/comfy/vendor/codemirror/addon/edit/closetag.js +169 -0
- data/app/assets/javascripts/comfy/vendor/codemirror/mode/css/css.js +832 -0
- data/app/assets/javascripts/comfy/vendor/codemirror/mode/htmlmixed/htmlmixed.js +152 -0
- data/app/assets/javascripts/comfy/vendor/codemirror/mode/javascript/javascript.js +875 -0
- data/app/assets/javascripts/comfy/vendor/codemirror/mode/markdown/markdown.js +861 -0
- data/app/assets/javascripts/comfy/vendor/codemirror/mode/xml/xml.js +394 -0
- data/app/assets/javascripts/comfy/vendor/codemirror.js +9653 -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 +76 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ar.js +52 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/bg.js +65 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/bn.js +65 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ca.js +83 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/cs.js +70 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/cy.js +92 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/da.js +71 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/de.js +70 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/default.js +80 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/eo.js +73 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/es.js +69 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/et.js +73 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/fa.js +68 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/fi.js +69 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/fr.js +75 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/gr.js +74 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/he.js +57 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/hi.js +65 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/hr.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/hu.js +72 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/id.js +61 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/it.js +70 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ja.js +57 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ko.js +60 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/lt.js +72 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/lv.js +67 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/mk.js +69 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/mn.js +67 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ms.js +68 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/my.js +69 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/nl.js +75 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/no.js +73 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/pa.js +65 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/pl.js +68 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/pt-BR.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/pt.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ro.js +69 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/ru.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/si.js +65 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/sk.js +70 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/sl.js +70 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/sq.js +65 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/sr.js +69 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/sv.js +70 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/th.js +72 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/tr.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/uk.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/vn.js +66 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/zh-CN.js +61 -0
- data/app/assets/javascripts/comfy/vendor/flatpickr/i18n/zh-TW.js +61 -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/moxie.min.js +16 -0
- data/app/assets/javascripts/comfy/vendor/plupload.dev.js +2497 -0
- data/app/assets/javascripts/comfy/vendor/redactor/definedlinks.js +53 -0
- data/app/assets/javascripts/comfy/vendor/redactor/filemanager.js +64 -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 +76 -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 +75 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/nl.js +80 -0
- data/app/assets/javascripts/comfy/vendor/redactor/i18n/pl.js +76 -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 +57 -0
- data/app/assets/javascripts/comfy/vendor/redactor/table.js +337 -0
- data/app/assets/javascripts/comfy/vendor/redactor/video.js +77 -0
- data/app/assets/javascripts/comfy/vendor/redactor.js +9561 -0
- data/app/assets/javascripts/comfy/vendor/sortable.min.js +5 -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/codemirror.css +346 -0
- data/app/assets/stylesheets/comfy/vendor/flatpickr.min.css +13 -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 +139 -0
- data/app/controllers/comfy/admin/cms/layouts_controller.rb +68 -0
- data/app/controllers/comfy/admin/cms/pages_controller.rb +163 -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 +65 -0
- data/app/controllers/comfy/admin/cms/translations_controller.rb +105 -0
- data/app/controllers/comfy/cms/assets_controller.rb +38 -0
- data/app/controllers/comfy/cms/base_controller.rb +26 -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 +20 -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 +14 -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 +58 -0
- data/app/models/comfy/cms/layout.rb +114 -0
- data/app/models/comfy/cms/page.rb +173 -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 +42 -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 +10 -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 +13 -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/comfortable_media_surfer.gemspec +37 -0
- data/config/application.rb +59 -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 +80 -0
- data/config/environments/production.rb +99 -0
- data/config/environments/test.rb +74 -0
- data/config/initializers/assets.rb +14 -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 +9 -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 +262 -0
- data/config/locales/ca.yml +262 -0
- data/config/locales/cs.yml +262 -0
- data/config/locales/da.yml +262 -0
- data/config/locales/de.yml +262 -0
- data/config/locales/en.yml +262 -0
- data/config/locales/es.yml +262 -0
- data/config/locales/fi.yml +262 -0
- data/config/locales/fr.yml +262 -0
- data/config/locales/gr.yml +262 -0
- data/config/locales/hr.yml +262 -0
- data/config/locales/it.yml +262 -0
- data/config/locales/ja.yml +262 -0
- data/config/locales/nb.yml +262 -0
- data/config/locales/nl.yml +262 -0
- data/config/locales/pl.yml +262 -0
- data/config/locales/pt-BR.yml +262 -0
- data/config/locales/ru.yml +262 -0
- data/config/locales/sk.yml +262 -0
- data/config/locales/sv.yml +262 -0
- data/config/locales/tr.yml +262 -0
- data/config/locales/uk.yml +262 -0
- data/config/locales/zh-CN.yml +262 -0
- data/config/locales/zh-TW.yml +262 -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/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 +143 -0
- data/gemfiles/6.1.gemfile +31 -0
- data/gemfiles/7.0.gemfile +31 -0
- data/gemfiles/7.1.gemfile +31 -0
- data/gemfiles/7.2.gemfile +31 -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 +29 -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 +79 -0
- data/lib/comfortable_media_surfer/seeds/file/exporter.rb +37 -0
- data/lib/comfortable_media_surfer/seeds/file/importer.rb +59 -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 +217 -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 +112 -0
- data/lib/comfortable_media_surfer/version.rb +5 -0
- data/lib/comfortable_media_surfer/view_hooks.rb +33 -0
- data/lib/comfortable_media_surfer.rb +56 -0
- data/lib/generators/comfy/cms/README +28 -0
- data/lib/generators/comfy/cms/assets_generator.rb +16 -0
- data/lib/generators/comfy/cms/cms_generator.rb +67 -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_seeds.rake +40 -0
- data/public/favicon.ico +0 -0
- data/rakelib/create_release.rake +81 -0
- metadata +797 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
5
|
+
|
6
|
+
gemspec path: '../'
|
7
|
+
|
8
|
+
gem 'rails', '~> 7.1.0', '>= 7.1.1'
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem 'autoprefixer-rails', '~> 10.4.16.0'
|
12
|
+
gem 'byebug', '~> 11.1.0', platforms: %i[mri mingw x64_mingw]
|
13
|
+
gem 'image_processing', '>= 1.12.0'
|
14
|
+
gem 'sqlite3', '~> 1.6.7'
|
15
|
+
end
|
16
|
+
|
17
|
+
group :test do
|
18
|
+
gem 'brakeman', '~> 6.1.2'
|
19
|
+
gem 'bundler-audit', '~> 0.9.1'
|
20
|
+
gem 'coveralls_reborn', '~> 0.28.0', require: false
|
21
|
+
gem 'cuprite', '>= 0.15'
|
22
|
+
gem 'equivalent-xml', '~> 0.6.0'
|
23
|
+
gem 'minitest', '>= 5.23.0'
|
24
|
+
gem 'minitest-reporters', '>= 1.6.1'
|
25
|
+
gem 'mocha', '>= 2.3.0', require: false
|
26
|
+
gem 'rails-controller-testing', '~> 1.0.5'
|
27
|
+
gem 'rubocop', '~> 1.63.0', require: false
|
28
|
+
gem 'rubocop-minitest'
|
29
|
+
gem 'rubocop-rails'
|
30
|
+
gem 'simplecov', '~> 0.22.0', require: false
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
5
|
+
|
6
|
+
gemspec path: '../'
|
7
|
+
|
8
|
+
gem 'rails', '~> 7.2.0', '>= 7.2.2'
|
9
|
+
|
10
|
+
group :development, :test do
|
11
|
+
gem 'autoprefixer-rails', '~> 10.4.16.0'
|
12
|
+
gem 'byebug', '~> 11.1.0', platforms: %i[mri mingw x64_mingw]
|
13
|
+
gem 'image_processing', '>= 1.12.0'
|
14
|
+
gem 'sqlite3', '~> 1.6.7'
|
15
|
+
end
|
16
|
+
|
17
|
+
group :test do
|
18
|
+
gem 'brakeman', '~> 6.1.2'
|
19
|
+
gem 'bundler-audit', '~> 0.9.1'
|
20
|
+
gem 'coveralls_reborn', '~> 0.28.0', require: false
|
21
|
+
gem 'cuprite', '>= 0.15'
|
22
|
+
gem 'equivalent-xml', '~> 0.6.0'
|
23
|
+
gem 'minitest', '>= 5.23.0'
|
24
|
+
gem 'minitest-reporters', '>= 1.6.1'
|
25
|
+
gem 'mocha', '>= 2.3.0', require: false
|
26
|
+
gem 'rails-controller-testing', '~> 1.0.5'
|
27
|
+
gem 'rubocop', '~> 1.63.0', require: false
|
28
|
+
gem 'rubocop-minitest'
|
29
|
+
gem 'rubocop-rails'
|
30
|
+
gem 'simplecov', '~> 0.22.0', require: false
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ComfortableMediaSurfer::AccessControl
|
4
|
+
module AdminAuthentication
|
5
|
+
# Set username and password in config/initializers/comfortable_media_surfer.rb
|
6
|
+
# Like this:
|
7
|
+
# ComfortableMediaSurfer::AccessControl::AdminAuthentication.username = 'myname'
|
8
|
+
# ComfortableMediaSurfer::AccessControl::AdminAuthentication.password = 'mypassword'
|
9
|
+
|
10
|
+
mattr_accessor :username,
|
11
|
+
:password
|
12
|
+
|
13
|
+
# Simple http_auth. When implementing some other form of authentication
|
14
|
+
# this method should return +true+ if everything is great, or redirect user
|
15
|
+
# to some other page, thus denying access to cms admin section.
|
16
|
+
def authenticate
|
17
|
+
authenticate_or_request_with_http_basic do |username, password|
|
18
|
+
self.username == username && self.password == password
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ComfortableMediaSurfer::Configuration
|
4
|
+
# Don't like ComfortableMediaSurfer? Set it to whatever you like. :(
|
5
|
+
attr_accessor :cms_title
|
6
|
+
|
7
|
+
# Controller that is inherited from CmsAdmin::BaseController
|
8
|
+
# 'ApplicationController' is the default
|
9
|
+
attr_accessor :admin_base_controller
|
10
|
+
|
11
|
+
# Controller that Comfy::Cms::BaseController will inherit from
|
12
|
+
# 'ApplicationController' is the default
|
13
|
+
attr_accessor :public_base_controller
|
14
|
+
|
15
|
+
# Module that will handle authentication to access cms-admin area
|
16
|
+
attr_accessor :admin_auth
|
17
|
+
|
18
|
+
# Module that will handle authorization against admin cms resources
|
19
|
+
attr_accessor :admin_authorization
|
20
|
+
|
21
|
+
# Module that will handle authentication for public pages
|
22
|
+
attr_accessor :public_auth
|
23
|
+
|
24
|
+
# Module that will handle authorization against public resources
|
25
|
+
attr_accessor :public_authorization
|
26
|
+
|
27
|
+
# When arriving at /cms-admin you may chose to redirect to arbirtary path,
|
28
|
+
# for example '/cms-admin/users'
|
29
|
+
attr_accessor :admin_route_redirect
|
30
|
+
|
31
|
+
# With each page load, files will be synched with the database. Database entries are
|
32
|
+
# destroyed if there's no corresponding file. Seeds are disabled by default.
|
33
|
+
attr_accessor :enable_seeds
|
34
|
+
|
35
|
+
# Path where seeds can be located.
|
36
|
+
attr_accessor :seeds_path
|
37
|
+
|
38
|
+
# Number of revisions kept. Default is 25. If you wish to disable: set this to 0.
|
39
|
+
attr_accessor :revisions_limit
|
40
|
+
|
41
|
+
# Locale definitions. If you want to define your own locale merge
|
42
|
+
# {:locale => 'Locale Title'} with this.
|
43
|
+
attr_accessor :locales
|
44
|
+
|
45
|
+
# Admin interface will respect the locale of the site being managed. However you can
|
46
|
+
# force it to English by setting this to `:en`
|
47
|
+
attr_accessor :admin_locale
|
48
|
+
|
49
|
+
# A class that is included as a sweeper to admin base controller if it's set
|
50
|
+
attr_accessor :admin_cache_sweeper
|
51
|
+
|
52
|
+
# Not allowing erb code to be run inside page content. False by default.
|
53
|
+
# @return [Boolean]
|
54
|
+
attr_accessor :allow_erb
|
55
|
+
|
56
|
+
# Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default
|
57
|
+
# all helpers are allowed except `eval`, `send`, `call` and few others. Empty array
|
58
|
+
# will prevent rendering of all helpers.
|
59
|
+
attr_accessor :allowed_helpers
|
60
|
+
|
61
|
+
# Whitelist of partials paths that can be used via {{cms:partial}} tag. All partials
|
62
|
+
# are accessible by default. Empty array will prevent rendering of all partials.
|
63
|
+
attr_accessor :allowed_partials
|
64
|
+
|
65
|
+
# Whitelist of template paths that can be used via {{cms:template}} tag. All templates
|
66
|
+
# are accessible by default. Empty array will prevent rendering of all templates.
|
67
|
+
attr_accessor :allowed_templates
|
68
|
+
|
69
|
+
# Site aliases, if you want to have aliases for your site. Good for harmonizing
|
70
|
+
# production env with dev/testing envs.
|
71
|
+
# e.g. config.site_aliases = {'host.com' => 'host.inv', 'host_a.com' => ['host.lvh.me', 'host.dev']}
|
72
|
+
# Default is nil (not used)
|
73
|
+
attr_accessor :hostname_aliases
|
74
|
+
|
75
|
+
# Reveal partials that can be overwritten in the admin area.
|
76
|
+
# Default is false.
|
77
|
+
attr_accessor :reveal_cms_partials
|
78
|
+
|
79
|
+
# Auto-setting parameter derived from the routes
|
80
|
+
attr_accessor :public_cms_path
|
81
|
+
|
82
|
+
# Customize returned content from `page.to_json`
|
83
|
+
# Default is set to `methods: [:content], except: [:content_cache]`
|
84
|
+
# For example: include fragments into json data with `config.page_to_json_options = { include: [:fragments] }`
|
85
|
+
attr_accessor :page_to_json_options
|
86
|
+
|
87
|
+
# Configuration defaults
|
88
|
+
def initialize
|
89
|
+
@cms_title = 'ComfortableMediaSurfer CMS Engine'
|
90
|
+
@admin_base_controller = 'ApplicationController'
|
91
|
+
@public_base_controller = 'ApplicationController'
|
92
|
+
@admin_auth = 'ComfortableMediaSurfer::AccessControl::AdminAuthentication'
|
93
|
+
@admin_authorization = 'ComfortableMediaSurfer::AccessControl::AdminAuthorization'
|
94
|
+
@public_auth = 'ComfortableMediaSurfer::AccessControl::PublicAuthentication'
|
95
|
+
@public_authorization = 'ComfortableMediaSurfer::AccessControl::PublicAuthorization'
|
96
|
+
@seed_data_path = nil
|
97
|
+
@admin_route_redirect = ''
|
98
|
+
@enable_sitemap = true
|
99
|
+
@enable_seeds = false
|
100
|
+
@seeds_path = File.expand_path('db/cms_seeds', Rails.root)
|
101
|
+
@revisions_limit = 25
|
102
|
+
@locales = {
|
103
|
+
'ar' => 'عربي',
|
104
|
+
'ca' => 'Català',
|
105
|
+
'cs' => 'Česky',
|
106
|
+
'da' => 'Dansk',
|
107
|
+
'de' => 'Deutsch',
|
108
|
+
'en' => 'English',
|
109
|
+
'es' => 'Español',
|
110
|
+
'fi' => 'Suomi',
|
111
|
+
'fr' => 'Français',
|
112
|
+
'gr' => 'Ελληνικά',
|
113
|
+
'hr' => 'Hrvatski',
|
114
|
+
'it' => 'Italiano',
|
115
|
+
'ja' => '日本語',
|
116
|
+
'nb' => 'Norsk',
|
117
|
+
'nl' => 'Nederlands',
|
118
|
+
'pl' => 'Polski',
|
119
|
+
'pt-BR' => 'Português Brasileiro',
|
120
|
+
'ru' => 'Русский',
|
121
|
+
'sk' => 'Slovensky',
|
122
|
+
'sv' => 'Svenska',
|
123
|
+
'tr' => 'Türkçe',
|
124
|
+
'uk' => 'Українська',
|
125
|
+
'zh-CN' => '简体中文',
|
126
|
+
'zh-TW' => '正體中文'
|
127
|
+
}
|
128
|
+
@admin_locale = nil
|
129
|
+
@admin_cache_sweeper = nil
|
130
|
+
@allow_erb = false
|
131
|
+
@allowed_helpers = nil
|
132
|
+
@allowed_partials = nil
|
133
|
+
@hostname_aliases = nil
|
134
|
+
@reveal_cms_partials = false
|
135
|
+
@public_cms_path = nil
|
136
|
+
@page_to_json_options = { methods: [:content], except: [:content_cache] }
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# wtf does this mean
|
4
|
+
# it means that all nodes between this must be moved into here
|
5
|
+
# {{cms:block}} some content {{cms:end_block}}
|
6
|
+
class ComfortableMediaSurfer::Content::Block < ComfortableMediaSurfer::Content::Tag
|
7
|
+
attr_writer :nodes
|
8
|
+
|
9
|
+
def nodes
|
10
|
+
@nodes ||= []
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
|
5
|
+
class ComfortableMediaSurfer::Content::ParamsParser
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
STRING_LITERAL = %r{'[^']*'|"[^"]*"}
|
9
|
+
IDENTIFIER = %r{[a-z0-9][\w\-/.]*}i
|
10
|
+
HASH_KEY = %r{#{IDENTIFIER}:}
|
11
|
+
COMMA = %r{,}
|
12
|
+
HASH_OPEN = %r{\{}
|
13
|
+
HASH_CLOSE = %r{\}}
|
14
|
+
ARRAY_OPEN = %r{\[}
|
15
|
+
ARRAY_CLOSE = %r{\]}
|
16
|
+
INTEGER = %r{\b[0-9]+\b}i
|
17
|
+
|
18
|
+
# @param <String> string
|
19
|
+
def initialize(string = '')
|
20
|
+
@string = string
|
21
|
+
end
|
22
|
+
|
23
|
+
# Takes CMS content tag parameters and converts them into array of strings,
|
24
|
+
# hashes and arrays.
|
25
|
+
#
|
26
|
+
# @return [Array<String, {String => String}>]
|
27
|
+
# @raise [Error] if the given `text` is malformed.
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
# new("a, b, c").parse
|
31
|
+
# #=> ["a", "b", "c"]
|
32
|
+
#
|
33
|
+
# new("a, b: c, d: e").parse
|
34
|
+
# #=> ["a", {"b" => "c", "d" => "e"}]
|
35
|
+
#
|
36
|
+
# new("a, b: {c: [d, e]}").parse
|
37
|
+
# #=> ["a", {"b" => {"c" => ["d", "e"]}}]
|
38
|
+
#
|
39
|
+
def params
|
40
|
+
@tokens = tokenize(@string)
|
41
|
+
parse_params
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Contructs root-level list of arguments sent via content tag
|
47
|
+
def parse_params
|
48
|
+
params = []
|
49
|
+
while (token = @tokens.shift)
|
50
|
+
params << parse_value(token)
|
51
|
+
end
|
52
|
+
params
|
53
|
+
end
|
54
|
+
|
55
|
+
# Gets token value. Will trigger parsing of hash and array structures
|
56
|
+
def parse_value(token)
|
57
|
+
case token&.first
|
58
|
+
when :string
|
59
|
+
token[1]
|
60
|
+
when :hash_key
|
61
|
+
@tokens.unshift(token)
|
62
|
+
parse_hash
|
63
|
+
when :hash_open
|
64
|
+
parse_hash
|
65
|
+
when :array_open
|
66
|
+
parse_array
|
67
|
+
else
|
68
|
+
raise Error, "Invalid params: #{@string}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Hash constructor method. Will handle nested hashes as well
|
73
|
+
def parse_hash
|
74
|
+
opens = 1
|
75
|
+
hash = {}
|
76
|
+
|
77
|
+
while (token = @tokens.shift)
|
78
|
+
case token&.first
|
79
|
+
when :hash_key
|
80
|
+
hash[token[1]] = parse_value(@tokens.shift)
|
81
|
+
when :hash_close
|
82
|
+
opens -= 1
|
83
|
+
when :hash_open
|
84
|
+
opens += 1
|
85
|
+
else
|
86
|
+
raise Error, "Invalid params: #{@string}"
|
87
|
+
end
|
88
|
+
|
89
|
+
return hash if opens.zero?
|
90
|
+
end
|
91
|
+
|
92
|
+
# We're can't really detect unclosed hashes as we can construct them without
|
93
|
+
# opening brakets. For example, `a: b, c: d` is same as `{a: b, c: d}` and
|
94
|
+
# `{a: b, c: d` is also ends up to be a valid hash. It will error out if
|
95
|
+
# unclosed hash is followed by some other unexpected token. Like: `{a: b, c`
|
96
|
+
hash
|
97
|
+
end
|
98
|
+
|
99
|
+
# Array construction method. Will handle nested arrays
|
100
|
+
def parse_array
|
101
|
+
opens = 1
|
102
|
+
array = []
|
103
|
+
while (token = @tokens.shift)
|
104
|
+
case token&.first
|
105
|
+
when :array_close
|
106
|
+
opens -= 1
|
107
|
+
else
|
108
|
+
array << parse_value(token)
|
109
|
+
end
|
110
|
+
|
111
|
+
return array if opens.zero?
|
112
|
+
end
|
113
|
+
|
114
|
+
raise Error, "Unclosed array param: #{@string}"
|
115
|
+
end
|
116
|
+
|
117
|
+
# Tokenizing input string into a list of touples
|
118
|
+
# Also args_string is stripped of "smart" quotes coming from wysiwyg
|
119
|
+
#
|
120
|
+
# @param [String] args_string
|
121
|
+
# @return [Array<String>] tokens
|
122
|
+
def tokenize(args_string)
|
123
|
+
args_string = args_string.tr('“”‘’', %q(""''))
|
124
|
+
ss = StringScanner.new(args_string)
|
125
|
+
tokens = []
|
126
|
+
loop do
|
127
|
+
ss.skip(%r{\s*})
|
128
|
+
break if ss.eos?
|
129
|
+
|
130
|
+
# commas are just separators like spaces
|
131
|
+
next if ss.scan(COMMA)
|
132
|
+
|
133
|
+
tokens <<
|
134
|
+
if (t = ss.scan(STRING_LITERAL)) then [:string, t[1...-1]]
|
135
|
+
elsif (t = ss.scan(HASH_KEY)) then [:hash_key, t[0...-1]]
|
136
|
+
elsif (t = ss.scan(INTEGER)) then [:string, t.to_i]
|
137
|
+
elsif (t = ss.scan(IDENTIFIER)) then [:string, t]
|
138
|
+
elsif (t = ss.scan(HASH_OPEN)) then [:hash_open, t]
|
139
|
+
elsif (t = ss.scan(HASH_CLOSE)) then [:hash_close, t]
|
140
|
+
elsif (t = ss.scan(ARRAY_OPEN)) then [:array_open, t]
|
141
|
+
elsif (t = ss.scan(ARRAY_CLOSE)) then [:array_close, t]
|
142
|
+
else
|
143
|
+
raise Error, "Unexpected char: #{ss.getch}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
tokens
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strscan'
|
4
|
+
|
5
|
+
# Processing content follows these stages:
|
6
|
+
#
|
7
|
+
# string - Text with tags. like this: "some {{cms:fragment content}} text"
|
8
|
+
# tokenization - Splits string into a list of strings and hashes that define tags
|
9
|
+
# Example: ["some ", {tag_class: "fragment", tag_params: ""}, " text"]
|
10
|
+
# nodefying - Initializes Tag instances from tag hashes and returns list
|
11
|
+
# like this: ["some ", (FragmentTagInstance), " text"]
|
12
|
+
# rendering - Recursively iterates through nodes. Tag instances get their
|
13
|
+
# `render` method called. Result of that is tokenized, nodefied
|
14
|
+
# and rendered once again until there are no tags to expand.
|
15
|
+
# Resulting list is flattened and joined into a final rendered string.
|
16
|
+
#
|
17
|
+
class ComfortableMediaSurfer::Content::Renderer
|
18
|
+
class SyntaxError < StandardError; end
|
19
|
+
class Error < StandardError; end
|
20
|
+
|
21
|
+
MAX_DEPTH = 100
|
22
|
+
|
23
|
+
# tags are in this format: {{ cms:tag_class params }}
|
24
|
+
TAG_REGEX = %r{\{\{\s*?cms:(?<class>\w+)(?<params>.*?)\}\}}
|
25
|
+
|
26
|
+
class << self
|
27
|
+
# @return [Hash<String, Class<ComfortableMediaSurfer::Content::Tag>>]
|
28
|
+
def tags
|
29
|
+
@tags ||= {}
|
30
|
+
end
|
31
|
+
|
32
|
+
# @param [String] name
|
33
|
+
# @param [Class<ComfortableMediaSurfer::Content::Tag>] klass
|
34
|
+
def register_tag(name, klass)
|
35
|
+
tags[name.to_s] = klass
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [Comfy::Cms::WithFragments, nil] context
|
40
|
+
def initialize(context)
|
41
|
+
@context = context
|
42
|
+
@depth = 0
|
43
|
+
end
|
44
|
+
|
45
|
+
# This is how we render content out. Takes context (cms page) and content
|
46
|
+
# nodes
|
47
|
+
# @param [Array<String, ComfortableMediaSurfer::Content::Tag>]
|
48
|
+
# @param [Boolean] allow_erb
|
49
|
+
def render(nodes, allow_erb = ComfortableMediaSurfer.config.allow_erb)
|
50
|
+
if (@depth += 1) > MAX_DEPTH
|
51
|
+
raise Error, 'Deep tag nesting or recursive nesting detected'
|
52
|
+
end
|
53
|
+
|
54
|
+
nodes.map do |node|
|
55
|
+
case node
|
56
|
+
when String
|
57
|
+
sanitize_erb(node, allow_erb)
|
58
|
+
else
|
59
|
+
tokens = tokenize(node.render)
|
60
|
+
nodes = nodes(tokens)
|
61
|
+
render(nodes, allow_erb || node.allow_erb?)
|
62
|
+
end
|
63
|
+
end.flatten.join
|
64
|
+
end
|
65
|
+
|
66
|
+
def sanitize_erb(string, allow_erb)
|
67
|
+
if allow_erb
|
68
|
+
string.to_s
|
69
|
+
else
|
70
|
+
string.to_s.gsub('<%', '<%').gsub('%>', '%>')
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Splitting text with tags into tokens we can process down the line
|
75
|
+
# @return [Array<String, {Symbol => String}>]
|
76
|
+
def tokenize(string)
|
77
|
+
tokens = []
|
78
|
+
ss = StringScanner.new(string.to_s)
|
79
|
+
while (string = ss.scan_until(TAG_REGEX))
|
80
|
+
text = string.sub(ss[0], '')
|
81
|
+
tokens << text unless text.empty?
|
82
|
+
tokens << {
|
83
|
+
tag_class: ss[:class],
|
84
|
+
tag_params: ss[:params].strip,
|
85
|
+
source: ss[0]
|
86
|
+
}
|
87
|
+
end
|
88
|
+
text = ss.rest
|
89
|
+
tokens << text if text.present?
|
90
|
+
tokens
|
91
|
+
end
|
92
|
+
|
93
|
+
# Constructing node tree for content. It's a list of strings and tags with
|
94
|
+
# their own `nodes` method that has array of strings and tags with their own
|
95
|
+
# `nodes` method that... you get the idea.
|
96
|
+
# @param [Array<String, {Symbol => String}>] tokens
|
97
|
+
# @return [Array<String, ComfortableMediaSurfer::Content::Tag>]
|
98
|
+
def nodes(tokens)
|
99
|
+
nodes = [[]]
|
100
|
+
tokens.each do |token|
|
101
|
+
case token
|
102
|
+
|
103
|
+
# tag signature
|
104
|
+
when Hash
|
105
|
+
case tag_class = token[:tag_class]
|
106
|
+
|
107
|
+
# This handles {{cms:end}} tag. Stopping collecting block nodes.
|
108
|
+
when 'end'
|
109
|
+
if nodes.count == 1
|
110
|
+
raise SyntaxError, 'closing unopened block'
|
111
|
+
end
|
112
|
+
|
113
|
+
nodes.pop
|
114
|
+
|
115
|
+
else
|
116
|
+
# @type [Class<ComfortableMediaSurfer::Content::Tag>]
|
117
|
+
klass = self.class.tags[tag_class] ||
|
118
|
+
raise(SyntaxError, "Unrecognized tag: #{token[:source]}")
|
119
|
+
|
120
|
+
# @type [ComfortableMediaSurfer::Content::Tag]
|
121
|
+
tag = klass.new(
|
122
|
+
context: @context,
|
123
|
+
params: ComfortableMediaSurfer::Content::ParamsParser.new(token[:tag_params]).params,
|
124
|
+
source: token[:source]
|
125
|
+
)
|
126
|
+
nodes.last << tag
|
127
|
+
|
128
|
+
# If it's a block tag we start collecting nodes into it
|
129
|
+
if tag.is_a?(ComfortableMediaSurfer::Content::Block)
|
130
|
+
nodes << tag.nodes
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# text
|
135
|
+
else
|
136
|
+
nodes.last << token
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
if nodes.count > 1
|
141
|
+
raise SyntaxError, 'unclosed block detected'
|
142
|
+
end
|
143
|
+
|
144
|
+
nodes.flatten
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ComfortableMediaSurfer::Content::Tag
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
# @type [Comfy::Cms::WithFragments]
|
7
|
+
attr_reader :context
|
8
|
+
|
9
|
+
# @type [Array<String, {String => String}>] params
|
10
|
+
attr_reader :params
|
11
|
+
|
12
|
+
# @type [String, nil] source
|
13
|
+
attr_reader :source
|
14
|
+
|
15
|
+
# @param [Comfy::Cms::WithFragments] context
|
16
|
+
# @param [Array<String, {String => String}>] params
|
17
|
+
# @param [String, nil] source
|
18
|
+
def initialize(context:, params: [], source: nil)
|
19
|
+
@context = context
|
20
|
+
@params = params
|
21
|
+
@source = source
|
22
|
+
end
|
23
|
+
|
24
|
+
# Making sure we don't leak erb from tags by accident.
|
25
|
+
# Tag classes can override this, like partials/helpers tags.
|
26
|
+
def allow_erb?
|
27
|
+
ComfortableMediaSurfer.config.allow_erb
|
28
|
+
end
|
29
|
+
|
30
|
+
# Normally it's a {(String)}. However, if tag content has tags,
|
31
|
+
# we need to expand them and that produces potentially more stuff.
|
32
|
+
# @return [Array<String, ComfortableMediaSurfer::Content::Tag>]
|
33
|
+
def nodes
|
34
|
+
template = ComfortableMediaSurfer::Content::Renderer.new(@context)
|
35
|
+
tokens = template.tokenize(content)
|
36
|
+
template.nodes(tokens)
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [String]
|
40
|
+
def content
|
41
|
+
raise Error, 'This is a base class. It holds no content'
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [String]
|
45
|
+
def render
|
46
|
+
content
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This tag allows for linking of js and css content defined on the layout.
|
4
|
+
# Looks something like this:
|
5
|
+
# {{cms:asset layout_identifier, type: css, as: tag}}
|
6
|
+
#
|
7
|
+
# `type` - css | js - what we're outputting here
|
8
|
+
# `as` - url (default) | tag - output url or wrap it in the appropriate tag
|
9
|
+
#
|
10
|
+
class ComfortableMediaSurfer::Content::Tags::Asset < ComfortableMediaSurfer::Content::Tag
|
11
|
+
attr_reader :identifier, :type, :as
|
12
|
+
|
13
|
+
def initialize(context:, params: [], source: nil)
|
14
|
+
super
|
15
|
+
|
16
|
+
options = params.extract_options!
|
17
|
+
@identifier = params[0]
|
18
|
+
@type = options['type']
|
19
|
+
@as = options['as'] || 'url'
|
20
|
+
|
21
|
+
return if @identifier.present?
|
22
|
+
|
23
|
+
raise Error, 'Missing layout identifier for asset tag'
|
24
|
+
end
|
25
|
+
|
26
|
+
def layout
|
27
|
+
@layout ||= context.site.layouts.find_by(identifier: @identifier)
|
28
|
+
end
|
29
|
+
|
30
|
+
def content
|
31
|
+
return '' unless layout
|
32
|
+
|
33
|
+
base = ComfortableMediaSurfer.config.public_cms_path || ''
|
34
|
+
unless base.ends_with?('/')
|
35
|
+
base += '/'
|
36
|
+
end
|
37
|
+
|
38
|
+
case @type
|
39
|
+
when 'css'
|
40
|
+
out = "#{base}cms-css/#{context.site.id}/#{@identifier}/#{layout.cache_buster}.css"
|
41
|
+
if @as == 'tag'
|
42
|
+
out = "<link href='#{out}' media='screen' rel='stylesheet' type='text/css' />"
|
43
|
+
end
|
44
|
+
out
|
45
|
+
when 'js'
|
46
|
+
out = "#{base}cms-js/#{context.site.id}/#{@identifier}/#{layout.cache_buster}.js"
|
47
|
+
if @as == 'tag'
|
48
|
+
out = "<script src='#{out}' type='text/javascript'></script>"
|
49
|
+
end
|
50
|
+
out
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ComfortableMediaSurfer::Content::Renderer.register_tag(
|
56
|
+
:asset, ComfortableMediaSurfer::Content::Tags::Asset
|
57
|
+
)
|