occams 1.0.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 +2 -0
- data/.github/issue_template.md +22 -0
- data/.github/pull_request_template.md +6 -0
- data/.gitignore +21 -0
- data/.rubocop.yml +87 -0
- data/.travis.yml +44 -0
- data/CHANGELOG.md +7 -0
- data/CONTRIBUTING.md +35 -0
- data/Gemfile +30 -0
- data/LICENSE +20 -0
- data/LICENSE.comfy +20 -0
- data/README.md +121 -0
- data/Rakefile +5 -0
- data/app/assets/config/manifest.js +0 -0
- data/app/assets/fonts/occams/admin/cms/lib/redactor-font.eot +0 -0
- data/app/assets/javascripts/occams/admin/cms/application.js +39 -0
- data/app/assets/javascripts/occams/admin/cms/base.js +46 -0
- data/app/assets/javascripts/occams/admin/cms/categories.js +17 -0
- data/app/assets/javascripts/occams/admin/cms/codemirror.js +31 -0
- data/app/assets/javascripts/occams/admin/cms/custom.js +1 -0
- data/app/assets/javascripts/occams/admin/cms/diff.js +10 -0
- data/app/assets/javascripts/occams/admin/cms/file_link.js +67 -0
- data/app/assets/javascripts/occams/admin/cms/file_upload.js +194 -0
- data/app/assets/javascripts/occams/admin/cms/files_modal.js +40 -0
- data/app/assets/javascripts/occams/admin/cms/page_fragments.js +22 -0
- data/app/assets/javascripts/occams/admin/cms/slugify.js +34 -0
- data/app/assets/javascripts/occams/admin/cms/sortable_list.js +40 -0
- data/app/assets/javascripts/occams/admin/cms/timepicker.js +30 -0
- data/app/assets/javascripts/occams/admin/cms/wysiwyg.js +72 -0
- data/app/assets/javascripts/occams/vendor/Moxie.swf +0 -0
- data/app/assets/javascripts/occams/vendor/Moxie.xap +0 -0
- data/app/assets/javascripts/occams/vendor/bootstrap.bundle.min.js +7 -0
- data/app/assets/javascripts/occams/vendor/bootstrap.bundle.min.js.map +1 -0
- data/app/assets/javascripts/occams/vendor/codemirror/addon/edit/closetag.js +169 -0
- data/app/assets/javascripts/occams/vendor/codemirror/mode/css/css.js +832 -0
- data/app/assets/javascripts/occams/vendor/codemirror/mode/htmlmixed/htmlmixed.js +152 -0
- data/app/assets/javascripts/occams/vendor/codemirror/mode/javascript/javascript.js +875 -0
- data/app/assets/javascripts/occams/vendor/codemirror/mode/markdown/markdown.js +861 -0
- data/app/assets/javascripts/occams/vendor/codemirror/mode/xml/xml.js +394 -0
- data/app/assets/javascripts/occams/vendor/codemirror.js +9653 -0
- data/app/assets/javascripts/occams/vendor/diff/diff_match_patch.min.js +49 -0
- data/app/assets/javascripts/occams/vendor/diff/pretty_text_diff.js +76 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ar.js +52 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/bg.js +65 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/bn.js +65 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ca.js +83 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/cs.js +70 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/cy.js +92 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/da.js +71 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/de.js +70 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/default.js +80 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/eo.js +73 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/es.js +69 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/et.js +73 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/fa.js +68 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/fi.js +69 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/fr.js +75 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/gr.js +74 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/he.js +57 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/hi.js +65 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/hr.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/hu.js +72 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/id.js +61 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/it.js +70 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ja.js +57 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ko.js +60 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/lt.js +72 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/lv.js +67 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/mk.js +69 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/mn.js +67 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ms.js +68 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/my.js +69 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/nl.js +75 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/no.js +73 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/pa.js +65 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/pl.js +68 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/pt-BR.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/pt.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ro.js +69 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/ru.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/si.js +65 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/sk.js +70 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/sl.js +70 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/sq.js +65 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/sr.js +69 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/sv.js +70 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/th.js +72 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/tr.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/uk.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/vn.js +66 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/zh-CN.js +61 -0
- data/app/assets/javascripts/occams/vendor/flatpickr/i18n/zh-TW.js +61 -0
- data/app/assets/javascripts/occams/vendor/flatpickr.min.js +2 -0
- data/app/assets/javascripts/occams/vendor/fontawesome.js +5 -0
- data/app/assets/javascripts/occams/vendor/moxie.min.js +16 -0
- data/app/assets/javascripts/occams/vendor/plupload.dev.js +2497 -0
- data/app/assets/javascripts/occams/vendor/redactor/definedlinks.js +53 -0
- data/app/assets/javascripts/occams/vendor/redactor/filemanager.js +64 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ar.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/az.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ba.js +79 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/bg.js +77 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/by.js +77 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ca.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/cs.js +87 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/da.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/de.js +80 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/el.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/en.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/eo.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/es.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/es_AR.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/fa.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/fi.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/fr.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ge.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/gr.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/he.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/hr.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/hu.js +77 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/id.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/it.js +78 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ja.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/kn.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ko.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/lt.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/lv.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/mk.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/nb.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/nl.js +80 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/pl.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/pt-BR.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/pt.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ro.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ru.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/sk.js +76 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/sl.js +79 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/sq.js +79 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/sr-CIR.js +79 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/sr-LAT.js +79 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/sv.js +74 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/th.js +74 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/tr.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/ua.js +77 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/uk.js +77 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/vi.js +74 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/zh-CN.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/i18n/zh-TW.js +75 -0
- data/app/assets/javascripts/occams/vendor/redactor/imagemanager.js +57 -0
- data/app/assets/javascripts/occams/vendor/redactor/table.js +337 -0
- data/app/assets/javascripts/occams/vendor/redactor/video.js +77 -0
- data/app/assets/javascripts/occams/vendor/redactor.js +9561 -0
- data/app/assets/javascripts/occams/vendor/sortable.min.js +5 -0
- data/app/assets/stylesheets/occams/admin/cms/application.sass +11 -0
- data/app/assets/stylesheets/occams/admin/cms/base.sass +256 -0
- data/app/assets/stylesheets/occams/admin/cms/codemirror_overrides.sass +19 -0
- data/app/assets/stylesheets/occams/admin/cms/custom.sass +1 -0
- data/app/assets/stylesheets/occams/admin/cms/redactor_overrides.sass +22 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_alert.scss +51 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_badge.scss +54 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_breadcrumb.scss +41 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_button-group.scss +163 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_buttons.scss +137 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_card.scss +289 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_carousel.scss +197 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_close.scss +41 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_code.scss +48 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_custom-forms.scss +507 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_dropdown.scss +191 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_forms.scss +330 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_functions.scss +86 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_grid.scss +52 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_images.scss +42 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_input-group.scss +193 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_jumbotron.scss +17 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_list-group.scss +149 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_media.scss +8 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_mixins.scss +47 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_modal.scss +229 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_nav.scss +120 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_navbar.scss +294 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_pagination.scss +73 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_popover.scss +171 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_print.scss +141 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_progress.scss +43 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_reboot.scss +483 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_root.scss +19 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_spinners.scss +55 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_tables.scss +185 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_toasts.scss +44 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_tooltip.scss +115 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_transitions.scss +20 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_type.scss +125 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_utilities.scss +17 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/_variables.scss +1123 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/bootstrap-grid.scss +29 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/bootstrap-reboot.scss +12 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/bootstrap.scss +44 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_alert.scss +13 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_background-variant.scss +21 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_badge.scss +17 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_border-radius.scss +63 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_box-shadow.scss +20 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_breakpoints.scss +123 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_buttons.scss +107 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_caret.scss +62 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_clearfix.scss +7 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_deprecate.scss +10 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_float.scss +14 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_forms.scss +192 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_gradients.scss +45 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_grid-framework.scss +66 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_grid.scss +51 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_hover.scss +37 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_image.scss +36 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_list-group.scss +21 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_lists.scss +7 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_nav-divider.scss +10 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_pagination.scss +22 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_reset-text.scss +17 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_resize.scss +6 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_screen-reader.scss +33 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_size.scss +7 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_table-row.scss +39 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_text-emphasis.scss +16 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_text-hide.scss +11 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_text-truncate.scss +8 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_transition.scss +16 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/mixins/_visibility.scss +8 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_align.scss +8 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_background.scss +19 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_borders.scss +75 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_clearfix.scss +3 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_display.scss +26 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_embed.scss +39 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_flex.scss +51 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_float.scss +11 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_overflow.scss +5 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_position.scss +32 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_screenreaders.scss +11 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_shadows.scss +6 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_sizing.scss +20 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_spacing.scss +73 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_stretched-link.scss +19 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_text.scss +72 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/utilities/_visibility.scss +13 -0
- data/app/assets/stylesheets/occams/vendor/bootstrap/vendor/_rfs.scss +204 -0
- data/app/assets/stylesheets/occams/vendor/codemirror.css +346 -0
- data/app/assets/stylesheets/occams/vendor/flatpickr.min.css +13 -0
- data/app/assets/stylesheets/occams/vendor/fontawesome.css +343 -0
- data/app/assets/stylesheets/occams/vendor/redactor.css +948 -0
- data/app/controllers/application_controller.rb +7 -0
- data/app/controllers/concerns/occams/paginate.rb +16 -0
- data/app/controllers/concerns/occams/reorder_action.rb +19 -0
- data/app/controllers/occams/admin/base_controller.rb +22 -0
- data/app/controllers/occams/admin/cms/base_controller.rb +55 -0
- data/app/controllers/occams/admin/cms/categories_controller.rb +40 -0
- data/app/controllers/occams/admin/cms/files_controller.rb +142 -0
- data/app/controllers/occams/admin/cms/layouts_controller.rb +69 -0
- data/app/controllers/occams/admin/cms/pages_controller.rb +156 -0
- data/app/controllers/occams/admin/cms/revisions/base_controller.rb +50 -0
- data/app/controllers/occams/admin/cms/revisions/layout_controller.rb +18 -0
- data/app/controllers/occams/admin/cms/revisions/page_controller.rb +30 -0
- data/app/controllers/occams/admin/cms/revisions/snippet_controller.rb +18 -0
- data/app/controllers/occams/admin/cms/revisions/translation_controller.rb +31 -0
- data/app/controllers/occams/admin/cms/sites_controller.rb +69 -0
- data/app/controllers/occams/admin/cms/snippets_controller.rb +66 -0
- data/app/controllers/occams/admin/cms/translations_controller.rb +107 -0
- data/app/controllers/occams/cms/assets_controller.rb +40 -0
- data/app/controllers/occams/cms/base_controller.rb +33 -0
- data/app/controllers/occams/cms/content_controller.rb +87 -0
- data/app/helpers/occams/admin/cms_helper.rb +49 -0
- data/app/helpers/occams/cms_helper.rb +73 -0
- data/app/models/concerns/occams/cms/with_categories.rb +53 -0
- data/app/models/concerns/occams/cms/with_fragments.rb +125 -0
- data/app/models/occams/cms/categorization.rb +16 -0
- data/app/models/occams/cms/category.rb +24 -0
- data/app/models/occams/cms/file.rb +70 -0
- data/app/models/occams/cms/fragment.rb +63 -0
- data/app/models/occams/cms/layout.rb +113 -0
- data/app/models/occams/cms/page.rb +170 -0
- data/app/models/occams/cms/revision.rb +12 -0
- data/app/models/occams/cms/site.rb +94 -0
- data/app/models/occams/cms/snippet.rb +45 -0
- data/app/models/occams/cms/translation.rb +43 -0
- data/app/views/kaminari/occams/_first_page.html.haml +3 -0
- data/app/views/kaminari/occams/_gap.html.haml +2 -0
- data/app/views/kaminari/occams/_last_page.html.haml +3 -0
- data/app/views/kaminari/occams/_next_page.html.haml +2 -0
- data/app/views/kaminari/occams/_page.html.haml +2 -0
- data/app/views/kaminari/occams/_paginator.html.haml +11 -0
- data/app/views/kaminari/occams/_prev_page.html.haml +2 -0
- data/app/views/layouts/occams/admin/cms/_body.html.haml +14 -0
- data/app/views/layouts/occams/admin/cms/_flash.html.haml +4 -0
- data/app/views/layouts/occams/admin/cms/_footer_js.html.haml +6 -0
- data/app/views/layouts/occams/admin/cms/_head.html.haml +19 -0
- data/app/views/layouts/occams/admin/cms/_left.html.haml +39 -0
- data/app/views/layouts/occams/admin/cms/_right.html.haml +5 -0
- data/app/views/layouts/occams/admin/cms.html.haml +4 -0
- data/app/views/occams/admin/cms/categories/_categories.html.haml +4 -0
- data/app/views/occams/admin/cms/categories/_edit.html.haml +7 -0
- data/app/views/occams/admin/cms/categories/_form.html.haml +5 -0
- data/app/views/occams/admin/cms/categories/_index.html.haml +28 -0
- data/app/views/occams/admin/cms/categories/_show.html.haml +15 -0
- data/app/views/occams/admin/cms/categories/create.js.erb +7 -0
- data/app/views/occams/admin/cms/categories/destroy.js.erb +8 -0
- data/app/views/occams/admin/cms/categories/edit.js.erb +3 -0
- data/app/views/occams/admin/cms/categories/update.js.erb +6 -0
- data/app/views/occams/admin/cms/files/_file.html.haml +31 -0
- data/app/views/occams/admin/cms/files/_form.html.haml +26 -0
- data/app/views/occams/admin/cms/files/_modal.html.haml +3 -0
- data/app/views/occams/admin/cms/files/destroy.js.erb +4 -0
- data/app/views/occams/admin/cms/files/edit.html.haml +5 -0
- data/app/views/occams/admin/cms/files/index.html.haml +31 -0
- data/app/views/occams/admin/cms/files/new.html.haml +5 -0
- data/app/views/occams/admin/cms/fragments/_form_fragment_attachments.html.haml +23 -0
- data/app/views/occams/admin/cms/fragments/_form_fragments.html.haml +38 -0
- data/app/views/occams/admin/cms/layouts/_form.html.haml +20 -0
- data/app/views/occams/admin/cms/layouts/_index_branch.html.haml +26 -0
- data/app/views/occams/admin/cms/layouts/edit.html.haml +9 -0
- data/app/views/occams/admin/cms/layouts/index.html.haml +10 -0
- data/app/views/occams/admin/cms/layouts/new.html.haml +5 -0
- data/app/views/occams/admin/cms/pages/_form.html.haml +31 -0
- data/app/views/occams/admin/cms/pages/_index_branch.html.haml +44 -0
- data/app/views/occams/admin/cms/pages/edit.html.haml +10 -0
- data/app/views/occams/admin/cms/pages/index.html.haml +13 -0
- data/app/views/occams/admin/cms/pages/new.html.haml +5 -0
- data/app/views/occams/admin/cms/pages/toggle_branch.js.erb +13 -0
- data/app/views/occams/admin/cms/revisions/_sidebar.html.haml +2 -0
- data/app/views/occams/admin/cms/revisions/show.html.haml +36 -0
- data/app/views/occams/admin/cms/sites/_form.html.haml +15 -0
- data/app/views/occams/admin/cms/sites/edit.html.haml +5 -0
- data/app/views/occams/admin/cms/sites/index.html.haml +28 -0
- data/app/views/occams/admin/cms/sites/new.html.haml +5 -0
- data/app/views/occams/admin/cms/snippets/_form.html.haml +18 -0
- data/app/views/occams/admin/cms/snippets/edit.html.haml +9 -0
- data/app/views/occams/admin/cms/snippets/index.html.haml +33 -0
- data/app/views/occams/admin/cms/snippets/new.html.haml +5 -0
- data/app/views/occams/admin/cms/translations/_form.html.haml +20 -0
- data/app/views/occams/admin/cms/translations/_sidebar.html.haml +19 -0
- data/app/views/occams/admin/cms/translations/edit.html.haml +10 -0
- data/app/views/occams/admin/cms/translations/new.html.haml +5 -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/config/application.rb +39 -0
- data/config/boot.rb +7 -0
- data/config/cms_routes.rb +8 -0
- data/config/database.yml +11 -0
- data/config/environment.rb +7 -0
- data/config/environments/development.rb +59 -0
- data/config/environments/test.rb +50 -0
- data/config/initializers/occams.rb +122 -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.rb +34 -0
- data/db/migrate/01_create_cms.rb +143 -0
- data/lib/generators/occams/cms/README +17 -0
- data/lib/generators/occams/cms/assets_generator.rb +18 -0
- data/lib/generators/occams/cms/cms_generator.rb +69 -0
- data/lib/generators/occams/cms/controllers_generator.rb +17 -0
- data/lib/generators/occams/cms/models_generator.rb +17 -0
- data/lib/generators/occams/cms/views_generator.rb +17 -0
- data/lib/generators/occams/scaffold/scaffold_generator.rb +80 -0
- data/lib/generators/occams/scaffold/templates/controller.rb.tt +62 -0
- data/lib/generators/occams/scaffold/templates/migration.rb.tt +11 -0
- data/lib/generators/occams/scaffold/templates/model.rb.tt +21 -0
- data/lib/generators/occams/scaffold/templates/tests/controller.rb.tt +115 -0
- data/lib/generators/occams/scaffold/templates/tests/fixture.yml.tt +4 -0
- data/lib/generators/occams/scaffold/templates/tests/model.rb.tt +26 -0
- data/lib/generators/occams/scaffold/templates/views/_form.haml.tt +7 -0
- data/lib/generators/occams/scaffold/templates/views/edit.haml.tt +5 -0
- data/lib/generators/occams/scaffold/templates/views/index.haml.tt +21 -0
- data/lib/generators/occams/scaffold/templates/views/new.haml.tt +5 -0
- data/lib/generators/occams/scaffold/templates/views/show.haml.tt +4 -0
- data/lib/occams/access_control/admin_authentication.rb +24 -0
- data/lib/occams/access_control/admin_authorization.rb +12 -0
- data/lib/occams/access_control/public_authentication.rb +12 -0
- data/lib/occams/access_control/public_authorization.rb +12 -0
- data/lib/occams/configuration.rb +140 -0
- data/lib/occams/content/block.rb +14 -0
- data/lib/occams/content/params_parser.rb +151 -0
- data/lib/occams/content/renderer.rb +149 -0
- data/lib/occams/content/tag.rb +50 -0
- data/lib/occams/content/tags/asset.rb +59 -0
- data/lib/occams/content/tags/checkbox.rb +29 -0
- data/lib/occams/content/tags/date.rb +21 -0
- data/lib/occams/content/tags/datetime.rb +44 -0
- data/lib/occams/content/tags/file.rb +72 -0
- data/lib/occams/content/tags/file_link.rb +63 -0
- data/lib/occams/content/tags/files.rb +43 -0
- data/lib/occams/content/tags/fragment.rb +66 -0
- data/lib/occams/content/tags/helper.rb +55 -0
- data/lib/occams/content/tags/markdown.rb +24 -0
- data/lib/occams/content/tags/mixins/file_content.rb +43 -0
- data/lib/occams/content/tags/number.rb +20 -0
- data/lib/occams/content/tags/page_file_link.rb +84 -0
- data/lib/occams/content/tags/partial.rb +49 -0
- data/lib/occams/content/tags/snippet.rb +38 -0
- data/lib/occams/content/tags/template.rb +44 -0
- data/lib/occams/content/tags/text.rb +20 -0
- data/lib/occams/content/tags/textarea.rb +20 -0
- data/lib/occams/content/tags/wysiwyg.rb +21 -0
- data/lib/occams/content.rb +31 -0
- data/lib/occams/engine.rb +31 -0
- data/lib/occams/error.rb +32 -0
- data/lib/occams/extensions/acts_as_tree.rb +120 -0
- data/lib/occams/extensions/has_revisions.rb +72 -0
- data/lib/occams/form_builder.rb +47 -0
- data/lib/occams/render_methods.rb +112 -0
- data/lib/occams/routes/cms.rb +18 -0
- data/lib/occams/routes/cms_admin.rb +58 -0
- data/lib/occams/routing.rb +12 -0
- data/lib/occams/seeds/file/exporter.rb +43 -0
- data/lib/occams/seeds/file/importer.rb +63 -0
- data/lib/occams/seeds/layout/exporter.rb +40 -0
- data/lib/occams/seeds/layout/importer.rb +62 -0
- data/lib/occams/seeds/page/exporter.rb +92 -0
- data/lib/occams/seeds/page/importer.rb +219 -0
- data/lib/occams/seeds/snippet/exporter.rb +34 -0
- data/lib/occams/seeds/snippet/importer.rb +51 -0
- data/lib/occams/seeds.rb +118 -0
- data/lib/occams/version.rb +7 -0
- data/lib/occams/view_hooks.rb +35 -0
- data/lib/occams.rb +60 -0
- data/lib/tasks/cms_seeds.rake +40 -0
- data/occams.gemspec +33 -0
- data/public/favicon.ico +0 -0
- metadata +666 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.page-header
|
|
2
|
+
= link_to 'New <%= class_name.titleize %>', new_admin_<%= file_name %>_path, class: 'btn btn-secondary float-right'
|
|
3
|
+
%h2= '<%= class_name.pluralize.titleize %>'
|
|
4
|
+
|
|
5
|
+
= paginate @<%= file_name.pluralize %>, theme: 'occams'
|
|
6
|
+
|
|
7
|
+
%ul.list
|
|
8
|
+
- @<%= file_name.pluralize %>.each do |<%= file_name %>|
|
|
9
|
+
%li
|
|
10
|
+
.row
|
|
11
|
+
.col-md-8.item
|
|
12
|
+
.item-content
|
|
13
|
+
.item-title
|
|
14
|
+
= <%= file_name%>.<%= model_attrs.first.name %>
|
|
15
|
+
|
|
16
|
+
.col-md-4.d-flex.align-items-center.justify-content-md-end
|
|
17
|
+
.btn-group.btn-group-sm
|
|
18
|
+
= link_to 'Edit', edit_admin_<%= file_name %>_path(<%= file_name %>), class: 'btn btn-outline-secondary'
|
|
19
|
+
= link_to 'Delete', admin_<%= file_name %>_path(<%= file_name %>), method: :delete, data: {confirm: 'Are you sure?'}, class: 'btn btn-danger'
|
|
20
|
+
|
|
21
|
+
= paginate @<%= file_name.pluralize %>, theme: 'occams'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Occams::AccessControl
|
|
4
|
+
module AdminAuthentication
|
|
5
|
+
|
|
6
|
+
# Set username and password in config/initializers/occams.rb
|
|
7
|
+
# Like this:
|
|
8
|
+
# Occams::AccessControl::AdminAuthentication.username = 'myname'
|
|
9
|
+
# Occams::AccessControl::AdminAuthentication.password = 'mypassword'
|
|
10
|
+
|
|
11
|
+
mattr_accessor :username,
|
|
12
|
+
:password
|
|
13
|
+
|
|
14
|
+
# Simple http_auth. When implementing some other form of authentication
|
|
15
|
+
# this method should return +true+ if everything is great, or redirect user
|
|
16
|
+
# to some other page, thus denying access to cms admin section.
|
|
17
|
+
def authenticate
|
|
18
|
+
authenticate_or_request_with_http_basic do |username, password|
|
|
19
|
+
self.username == username && self.password == password
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Occams::Configuration
|
|
4
|
+
|
|
5
|
+
# Don't like Occams? Set it to whatever you like. :(
|
|
6
|
+
attr_accessor :cms_title
|
|
7
|
+
|
|
8
|
+
# Controller that is inherited from CmsAdmin::BaseController
|
|
9
|
+
# 'ApplicationController' is the default
|
|
10
|
+
attr_accessor :admin_base_controller
|
|
11
|
+
|
|
12
|
+
# Controller that Occams::Cms::BaseController will inherit from
|
|
13
|
+
# 'ApplicationController' is the default
|
|
14
|
+
attr_accessor :public_base_controller
|
|
15
|
+
|
|
16
|
+
# Module that will handle authentication to access cms-admin area
|
|
17
|
+
attr_accessor :admin_auth
|
|
18
|
+
|
|
19
|
+
# Module that will handle authorization against admin cms resources
|
|
20
|
+
attr_accessor :admin_authorization
|
|
21
|
+
|
|
22
|
+
# Module that will handle authentication for public pages
|
|
23
|
+
attr_accessor :public_auth
|
|
24
|
+
|
|
25
|
+
# Module that will handle authorization against public resources
|
|
26
|
+
attr_accessor :public_authorization
|
|
27
|
+
|
|
28
|
+
# When arriving at /cms-admin you may chose to redirect to arbirtary path,
|
|
29
|
+
# for example '/cms-admin/users'
|
|
30
|
+
attr_accessor :admin_route_redirect
|
|
31
|
+
|
|
32
|
+
# With each page load, files will be synched with the database. Database entries are
|
|
33
|
+
# destroyed if there's no corresponding file. Seeds are disabled by default.
|
|
34
|
+
attr_accessor :enable_seeds
|
|
35
|
+
|
|
36
|
+
# Path where seeds can be located.
|
|
37
|
+
attr_accessor :seeds_path
|
|
38
|
+
|
|
39
|
+
# Number of revisions kept. Default is 25. If you wish to disable: set this to 0.
|
|
40
|
+
attr_accessor :revisions_limit
|
|
41
|
+
|
|
42
|
+
# Locale definitions. If you want to define your own locale merge
|
|
43
|
+
# {:locale => 'Locale Title'} with this.
|
|
44
|
+
attr_accessor :locales
|
|
45
|
+
|
|
46
|
+
# Admin interface will respect the locale of the site being managed. However you can
|
|
47
|
+
# force it to English by setting this to `:en`
|
|
48
|
+
attr_accessor :admin_locale
|
|
49
|
+
|
|
50
|
+
# A class that is included as a sweeper to admin base controller if it's set
|
|
51
|
+
attr_accessor :admin_cache_sweeper
|
|
52
|
+
|
|
53
|
+
# Not allowing erb code to be run inside page content. False by default.
|
|
54
|
+
# @return [Boolean]
|
|
55
|
+
attr_accessor :allow_erb
|
|
56
|
+
|
|
57
|
+
# Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default
|
|
58
|
+
# all helpers are allowed except `eval`, `send`, `call` and few others. Empty array
|
|
59
|
+
# will prevent rendering of all helpers.
|
|
60
|
+
attr_accessor :allowed_helpers
|
|
61
|
+
|
|
62
|
+
# Whitelist of partials paths that can be used via {{cms:partial}} tag. All partials
|
|
63
|
+
# are accessible by default. Empty array will prevent rendering of all partials.
|
|
64
|
+
attr_accessor :allowed_partials
|
|
65
|
+
|
|
66
|
+
# Whitelist of template paths that can be used via {{cms:template}} tag. All templates
|
|
67
|
+
# are accessible by default. Empty array will prevent rendering of all templates.
|
|
68
|
+
attr_accessor :allowed_templates
|
|
69
|
+
|
|
70
|
+
# Site aliases, if you want to have aliases for your site. Good for harmonizing
|
|
71
|
+
# production env with dev/testing envs.
|
|
72
|
+
# e.g. config.site_aliases = {'host.com' => 'host.inv', 'host_a.com' => ['host.lvh.me', 'host.dev']}
|
|
73
|
+
# Default is nil (not used)
|
|
74
|
+
attr_accessor :hostname_aliases
|
|
75
|
+
|
|
76
|
+
# Reveal partials that can be overwritten in the admin area.
|
|
77
|
+
# Default is false.
|
|
78
|
+
attr_accessor :reveal_cms_partials
|
|
79
|
+
|
|
80
|
+
# Auto-setting parameter derived from the routes
|
|
81
|
+
attr_accessor :public_cms_path
|
|
82
|
+
|
|
83
|
+
# Customize returned content from `page.to_json`
|
|
84
|
+
# Default is set to `methods: [:content], except: [:content_cache]`
|
|
85
|
+
# For example: include fragments into json data with `config.page_to_json_options = { include: [:fragments] }`
|
|
86
|
+
attr_accessor :page_to_json_options
|
|
87
|
+
|
|
88
|
+
# Configuration defaults
|
|
89
|
+
def initialize
|
|
90
|
+
@cms_title = "Occams CMS Engine"
|
|
91
|
+
@admin_base_controller = "ApplicationController"
|
|
92
|
+
@public_base_controller = "ApplicationController"
|
|
93
|
+
@admin_auth = "Occams::AccessControl::AdminAuthentication"
|
|
94
|
+
@admin_authorization = "Occams::AccessControl::AdminAuthorization"
|
|
95
|
+
@public_auth = "Occams::AccessControl::PublicAuthentication"
|
|
96
|
+
@public_authorization = "Occams::AccessControl::PublicAuthorization"
|
|
97
|
+
@seed_data_path = nil
|
|
98
|
+
@admin_route_redirect = ""
|
|
99
|
+
@enable_sitemap = true
|
|
100
|
+
@enable_seeds = false
|
|
101
|
+
@seeds_path = File.expand_path("db/cms_seeds", Rails.root)
|
|
102
|
+
@revisions_limit = 25
|
|
103
|
+
@locales = {
|
|
104
|
+
"ar" => "عربي",
|
|
105
|
+
"ca" => "Català",
|
|
106
|
+
"cs" => "Česky",
|
|
107
|
+
"da" => "Dansk",
|
|
108
|
+
"de" => "Deutsch",
|
|
109
|
+
"en" => "English",
|
|
110
|
+
"es" => "Español",
|
|
111
|
+
"fi" => "Suomi",
|
|
112
|
+
"fr" => "Français",
|
|
113
|
+
"gr" => "Ελληνικά",
|
|
114
|
+
"hr" => "Hrvatski",
|
|
115
|
+
"it" => "Italiano",
|
|
116
|
+
"ja" => "日本語",
|
|
117
|
+
"nb" => "Norsk",
|
|
118
|
+
"nl" => "Nederlands",
|
|
119
|
+
"pl" => "Polski",
|
|
120
|
+
"pt-BR" => "Português Brasileiro",
|
|
121
|
+
"ru" => "Русский",
|
|
122
|
+
"sk" => "Slovensky",
|
|
123
|
+
"sv" => "Svenska",
|
|
124
|
+
"tr" => "Türkçe",
|
|
125
|
+
"uk" => "Українська",
|
|
126
|
+
"zh-CN" => "简体中文",
|
|
127
|
+
"zh-TW" => "正體中文"
|
|
128
|
+
}
|
|
129
|
+
@admin_locale = nil
|
|
130
|
+
@admin_cache_sweeper = nil
|
|
131
|
+
@allow_erb = false
|
|
132
|
+
@allowed_helpers = nil
|
|
133
|
+
@allowed_partials = nil
|
|
134
|
+
@hostname_aliases = nil
|
|
135
|
+
@reveal_cms_partials = false
|
|
136
|
+
@public_cms_path = nil
|
|
137
|
+
@page_to_json_options = { methods: [:content], except: [:content_cache] }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
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 Occams::Content::Block < Occams::Content::Tag
|
|
7
|
+
|
|
8
|
+
attr_writer :nodes
|
|
9
|
+
|
|
10
|
+
def nodes
|
|
11
|
+
@nodes ||= []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
end
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "strscan"
|
|
4
|
+
|
|
5
|
+
class Occams::Content::ParamsParser
|
|
6
|
+
|
|
7
|
+
class Error < StandardError; end
|
|
8
|
+
|
|
9
|
+
STRING_LITERAL = %r{'[^']*'|"[^"]*"}
|
|
10
|
+
IDENTIFIER = %r{[a-z0-9][\w\-/.]*}i
|
|
11
|
+
HASH_KEY = %r{#{IDENTIFIER}:}
|
|
12
|
+
COMMA = %r{,}
|
|
13
|
+
HASH_OPEN = %r{\{}
|
|
14
|
+
HASH_CLOSE = %r{\}}
|
|
15
|
+
ARRAY_OPEN = %r{\[}
|
|
16
|
+
ARRAY_CLOSE = %r{\]}
|
|
17
|
+
INTEGER = %r{\b[0-9]+\b}i
|
|
18
|
+
|
|
19
|
+
# @param <String> string
|
|
20
|
+
def initialize(string = "")
|
|
21
|
+
@string = string
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Takes CMS content tag parameters and converts them into array of strings,
|
|
25
|
+
# hashes and arrays.
|
|
26
|
+
#
|
|
27
|
+
# @return [Array<String, {String => String}>]
|
|
28
|
+
# @raise [Error] if the given `text` is malformed.
|
|
29
|
+
#
|
|
30
|
+
# @example
|
|
31
|
+
# new("a, b, c").parse
|
|
32
|
+
# #=> ["a", "b", "c"]
|
|
33
|
+
#
|
|
34
|
+
# new("a, b: c, d: e").parse
|
|
35
|
+
# #=> ["a", {"b" => "c", "d" => "e"}]
|
|
36
|
+
#
|
|
37
|
+
# new("a, b: {c: [d, e]}").parse
|
|
38
|
+
# #=> ["a", {"b" => {"c" => ["d", "e"]}}]
|
|
39
|
+
#
|
|
40
|
+
def params
|
|
41
|
+
@tokens = tokenize(@string)
|
|
42
|
+
parse_params
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Contructs root-level list of arguments sent via content tag
|
|
48
|
+
def parse_params
|
|
49
|
+
params = []
|
|
50
|
+
while (token = @tokens.shift)
|
|
51
|
+
params << parse_value(token)
|
|
52
|
+
end
|
|
53
|
+
params
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Gets token value. Will trigger parsing of hash and array structures
|
|
57
|
+
def parse_value(token)
|
|
58
|
+
case token&.first
|
|
59
|
+
when :string
|
|
60
|
+
token[1]
|
|
61
|
+
when :hash_key
|
|
62
|
+
@tokens.unshift(token)
|
|
63
|
+
parse_hash
|
|
64
|
+
when :hash_open
|
|
65
|
+
parse_hash
|
|
66
|
+
when :array_open
|
|
67
|
+
parse_array
|
|
68
|
+
else
|
|
69
|
+
raise Error, "Invalid params: #{@string}"
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Hash constructor method. Will handle nested hashes as well
|
|
74
|
+
def parse_hash
|
|
75
|
+
opens = 1
|
|
76
|
+
hash = {}
|
|
77
|
+
|
|
78
|
+
while (token = @tokens.shift)
|
|
79
|
+
case token&.first
|
|
80
|
+
when :hash_key
|
|
81
|
+
hash[token[1]] = parse_value(@tokens.shift)
|
|
82
|
+
when :hash_close
|
|
83
|
+
opens -= 1
|
|
84
|
+
when :hash_open
|
|
85
|
+
opens += 1
|
|
86
|
+
else
|
|
87
|
+
raise Error, "Invalid params: #{@string}"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
return hash if opens.zero?
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# We're can't really detect unclosed hashes as we can construct them without
|
|
94
|
+
# opening brakets. For example, `a: b, c: d` is same as `{a: b, c: d}` and
|
|
95
|
+
# `{a: b, c: d` is also ends up to be a valid hash. It will error out if
|
|
96
|
+
# unclosed hash is followed by some other unexpected token. Like: `{a: b, c`
|
|
97
|
+
hash
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Array construction method. Will handle nested arrays
|
|
101
|
+
def parse_array
|
|
102
|
+
opens = 1
|
|
103
|
+
array = []
|
|
104
|
+
while (token = @tokens.shift)
|
|
105
|
+
case token&.first
|
|
106
|
+
when :array_close
|
|
107
|
+
opens -= 1
|
|
108
|
+
else
|
|
109
|
+
array << parse_value(token)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
return array if opens.zero?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
raise Error, "Unclosed array param: #{@string}"
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
# Tokenizing input string into a list of touples
|
|
119
|
+
# Also args_string is stripped of "smart" quotes coming from wysiwyg
|
|
120
|
+
#
|
|
121
|
+
# @param [String] args_string
|
|
122
|
+
# @return [Array<String>] tokens
|
|
123
|
+
def tokenize(args_string)
|
|
124
|
+
args_string = args_string.tr("“”‘’", %q(""''))
|
|
125
|
+
ss = StringScanner.new(args_string)
|
|
126
|
+
tokens = []
|
|
127
|
+
loop do
|
|
128
|
+
ss.skip(%r{\s*})
|
|
129
|
+
break if ss.eos?
|
|
130
|
+
|
|
131
|
+
# commas are just separators like spaces
|
|
132
|
+
next if ss.scan(COMMA)
|
|
133
|
+
|
|
134
|
+
tokens <<
|
|
135
|
+
if (t = ss.scan(STRING_LITERAL)) then [:string, t[1...-1]]
|
|
136
|
+
elsif (t = ss.scan(HASH_KEY)) then [:hash_key, t[0...-1]]
|
|
137
|
+
elsif (t = ss.scan(INTEGER)) then [:string, t.to_i]
|
|
138
|
+
elsif (t = ss.scan(IDENTIFIER)) then [:string, t]
|
|
139
|
+
elsif (t = ss.scan(HASH_OPEN)) then [:hash_open, t]
|
|
140
|
+
elsif (t = ss.scan(HASH_CLOSE)) then [:hash_close, t]
|
|
141
|
+
elsif (t = ss.scan(ARRAY_OPEN)) then [:array_open, t]
|
|
142
|
+
elsif (t = ss.scan(ARRAY_CLOSE)) then [:array_close, t]
|
|
143
|
+
else
|
|
144
|
+
raise Error, "Unexpected char: #{ss.getch}"
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
tokens
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
end
|
|
@@ -0,0 +1,149 @@
|
|
|
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 Occams::Content::Renderer
|
|
18
|
+
|
|
19
|
+
class SyntaxError < StandardError; end
|
|
20
|
+
class Error < StandardError; end
|
|
21
|
+
|
|
22
|
+
MAX_DEPTH = 100
|
|
23
|
+
|
|
24
|
+
# tags are in this format: {{ cms:tag_class params }}
|
|
25
|
+
TAG_REGEX = %r{\{\{\s*?cms:(?<class>\w+)(?<params>.*?)\}\}}
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
|
|
29
|
+
# @return [Hash<String, Class<Occams::Content::Tag>>]
|
|
30
|
+
def tags
|
|
31
|
+
@tags ||= {}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# @param [String] name
|
|
35
|
+
# @param [Class<Occams::Content::Tag>] klass
|
|
36
|
+
def register_tag(name, klass)
|
|
37
|
+
tags[name.to_s] = klass
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param [Occams::Cms::WithFragments, nil] context
|
|
43
|
+
def initialize(context)
|
|
44
|
+
@context = context
|
|
45
|
+
@depth = 0
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# This is how we render content out. Takes context (cms page) and content
|
|
49
|
+
# nodes
|
|
50
|
+
# @param [Array<String, Occams::Content::Tag>]
|
|
51
|
+
# @param [Boolean] allow_erb
|
|
52
|
+
def render(nodes, allow_erb = Occams.config.allow_erb)
|
|
53
|
+
if (@depth += 1) > MAX_DEPTH
|
|
54
|
+
raise Error, "Deep tag nesting or recursive nesting detected"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
nodes.map do |node|
|
|
58
|
+
case node
|
|
59
|
+
when String
|
|
60
|
+
sanitize_erb(node, allow_erb)
|
|
61
|
+
else
|
|
62
|
+
tokens = tokenize(node.render)
|
|
63
|
+
nodes = nodes(tokens)
|
|
64
|
+
render(nodes, allow_erb || node.allow_erb?)
|
|
65
|
+
end
|
|
66
|
+
end.flatten.join
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def sanitize_erb(string, allow_erb)
|
|
70
|
+
if allow_erb
|
|
71
|
+
string.to_s
|
|
72
|
+
else
|
|
73
|
+
string.to_s.gsub("<%", "<%").gsub("%>", "%>")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Splitting text with tags into tokens we can process down the line
|
|
78
|
+
# @return [Array<String, {Symbol => String}>]
|
|
79
|
+
def tokenize(string)
|
|
80
|
+
tokens = []
|
|
81
|
+
ss = StringScanner.new(string.to_s)
|
|
82
|
+
while (string = ss.scan_until(TAG_REGEX))
|
|
83
|
+
text = string.sub(ss[0], "")
|
|
84
|
+
tokens << text unless text.empty?
|
|
85
|
+
tokens << {
|
|
86
|
+
tag_class: ss[:class],
|
|
87
|
+
tag_params: ss[:params].strip,
|
|
88
|
+
source: ss[0]
|
|
89
|
+
}
|
|
90
|
+
end
|
|
91
|
+
text = ss.rest
|
|
92
|
+
tokens << text if text.present?
|
|
93
|
+
tokens
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Constructing node tree for content. It's a list of strings and tags with
|
|
97
|
+
# their own `nodes` method that has array of strings and tags with their own
|
|
98
|
+
# `nodes` method that... you get the idea.
|
|
99
|
+
# @param [Array<String, {Symbol => String}>] tokens
|
|
100
|
+
# @return [Array<String, Occams::Content::Tag>]
|
|
101
|
+
def nodes(tokens)
|
|
102
|
+
nodes = [[]]
|
|
103
|
+
tokens.each do |token|
|
|
104
|
+
case token
|
|
105
|
+
|
|
106
|
+
# tag signature
|
|
107
|
+
when Hash
|
|
108
|
+
case tag_class = token[:tag_class]
|
|
109
|
+
|
|
110
|
+
# This handles {{cms:end}} tag. Stopping collecting block nodes.
|
|
111
|
+
when "end"
|
|
112
|
+
if nodes.count == 1
|
|
113
|
+
raise SyntaxError, "closing unopened block"
|
|
114
|
+
end
|
|
115
|
+
nodes.pop
|
|
116
|
+
|
|
117
|
+
else
|
|
118
|
+
# @type [Class<Occams::Content::Tag>]
|
|
119
|
+
klass = self.class.tags[tag_class] ||
|
|
120
|
+
raise(SyntaxError, "Unrecognized tag: #{token[:source]}")
|
|
121
|
+
|
|
122
|
+
# @type [Occams::Content::Tag]
|
|
123
|
+
tag = klass.new(
|
|
124
|
+
context: @context,
|
|
125
|
+
params: Occams::Content::ParamsParser.new(token[:tag_params]).params,
|
|
126
|
+
source: token[:source]
|
|
127
|
+
)
|
|
128
|
+
nodes.last << tag
|
|
129
|
+
|
|
130
|
+
# If it's a block tag we start collecting nodes into it
|
|
131
|
+
if tag.is_a?(Occams::Content::Block)
|
|
132
|
+
nodes << tag.nodes
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# text
|
|
137
|
+
else
|
|
138
|
+
nodes.last << token
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
if nodes.count > 1
|
|
143
|
+
raise SyntaxError, "unclosed block detected"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
nodes.flatten
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Occams::Content::Tag
|
|
4
|
+
|
|
5
|
+
class Error < StandardError; end
|
|
6
|
+
|
|
7
|
+
# @type [Occams::Cms::WithFragments]
|
|
8
|
+
attr_reader :context
|
|
9
|
+
|
|
10
|
+
# @type [Array<String, {String => String}>] params
|
|
11
|
+
attr_reader :params
|
|
12
|
+
|
|
13
|
+
# @type [String, nil] source
|
|
14
|
+
attr_reader :source
|
|
15
|
+
|
|
16
|
+
# @param [Occams::Cms::WithFragments] context
|
|
17
|
+
# @param [Array<String, {String => String}>] params
|
|
18
|
+
# @param [String, nil] source
|
|
19
|
+
def initialize(context:, params: [], source: nil)
|
|
20
|
+
@context = context
|
|
21
|
+
@params = params
|
|
22
|
+
@source = source
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Making sure we don't leak erb from tags by accident.
|
|
26
|
+
# Tag classes can override this, like partials/helpers tags.
|
|
27
|
+
def allow_erb?
|
|
28
|
+
Occams.config.allow_erb
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Normally it's a {(String)}. However, if tag content has tags,
|
|
32
|
+
# we need to expand them and that produces potentially more stuff.
|
|
33
|
+
# @return [Array<String, Occams::Content::Tag>]
|
|
34
|
+
def nodes
|
|
35
|
+
template = Occams::Content::Renderer.new(@context)
|
|
36
|
+
tokens = template.tokenize(content)
|
|
37
|
+
template.nodes(tokens)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @return [String]
|
|
41
|
+
def content
|
|
42
|
+
raise Error, "This is a base class. It holds no content"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @return [String]
|
|
46
|
+
def render
|
|
47
|
+
content
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
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 Occams::Content::Tag::Asset < Occams::Content::Tag
|
|
11
|
+
|
|
12
|
+
attr_reader :identifier, :type, :as
|
|
13
|
+
|
|
14
|
+
def initialize(context:, params: [], source: nil)
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
options = params.extract_options!
|
|
18
|
+
@identifier = params[0]
|
|
19
|
+
@type = options["type"]
|
|
20
|
+
@as = options["as"] || "url"
|
|
21
|
+
|
|
22
|
+
unless @identifier.present?
|
|
23
|
+
raise Error, "Missing layout identifier for asset tag"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def layout
|
|
28
|
+
@layout ||= context.site.layouts.find_by(identifier: @identifier)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def content
|
|
32
|
+
return "" unless layout
|
|
33
|
+
|
|
34
|
+
base = Occams.config.public_cms_path || ""
|
|
35
|
+
unless base.ends_with?("/")
|
|
36
|
+
base += "/"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
case @type
|
|
40
|
+
when "css"
|
|
41
|
+
out = "#{base}cms-css/#{context.site.id}/#{@identifier}/#{layout.cache_buster}.css"
|
|
42
|
+
if @as == "tag"
|
|
43
|
+
out = "<link href='#{out}' media='screen' rel='stylesheet' type='text/css' />"
|
|
44
|
+
end
|
|
45
|
+
out
|
|
46
|
+
when "js"
|
|
47
|
+
out = "#{base}cms-js/#{context.site.id}/#{@identifier}/#{layout.cache_buster}.js"
|
|
48
|
+
if @as == "tag"
|
|
49
|
+
out = "<script src='#{out}' type='text/javascript'></script>"
|
|
50
|
+
end
|
|
51
|
+
out
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
Occams::Content::Renderer.register_tag(
|
|
58
|
+
:asset, Occams::Content::Tag::Asset
|
|
59
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Tag for boolean content that is going to be rendered using checkbox
|
|
4
|
+
# {{ cms:checkbox identifier }}
|
|
5
|
+
#
|
|
6
|
+
class Occams::Content::Tag::Checkbox < Occams::Content::Tag::Fragment
|
|
7
|
+
|
|
8
|
+
def content
|
|
9
|
+
fragment.boolean
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def form_field(object_name, view, index)
|
|
13
|
+
name = "#{object_name}[fragments_attributes][#{index}][boolean]"
|
|
14
|
+
|
|
15
|
+
input = view.content_tag(:div, class: "form-check mt-2") do
|
|
16
|
+
view.concat view.hidden_field_tag(name, "0", id: nil)
|
|
17
|
+
|
|
18
|
+
options = { id: form_field_id, class: "form-check-input position-static" }
|
|
19
|
+
view.concat view.check_box_tag(name, "1", content.present?, options)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
yield input
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Occams::Content::Renderer.register_tag(
|
|
28
|
+
:checkbox, Occams::Content::Tag::Checkbox
|
|
29
|
+
)
|