pages_core 3.6.0 → 3.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -3
- data/Rakefile +3 -1
- data/app/assets/builds/pages_core/admin-dist.js +55 -0
- data/app/assets/stylesheets/pages/admin/components/forms.scss +20 -0
- data/app/assets/stylesheets/pages/admin/components/image_editor.scss +1 -0
- data/app/assets/stylesheets/pages/admin/components/image_grid.scss +33 -5
- data/app/assets/stylesheets/pages/admin/components/layout.scss +2 -1
- data/app/assets/stylesheets/pages/admin/components/login.scss +6 -0
- data/app/assets/stylesheets/pages/admin/components/tabs.scss +5 -0
- data/app/assets/stylesheets/pages/admin/components/tag_editor.scss +13 -7
- data/app/assets/stylesheets/pages/admin/controllers/pages.scss +13 -5
- data/app/assets/stylesheets/pages/admin.scss +0 -1
- data/app/assets/stylesheets/pages/errors.css +2 -0
- data/app/controller_dummies/admin/admin_controller.rb +3 -1
- data/app/controller_dummies/application_controller.rb +3 -1
- data/app/controller_dummies/attachments_controller.rb +3 -1
- data/app/controller_dummies/frontend_controller.rb +3 -1
- data/app/controller_dummies/images_controller.rb +3 -1
- data/app/controller_dummies/page_files_controller.rb +3 -1
- data/app/controller_dummies/pages_controller.rb +3 -1
- data/app/controller_dummies/sitemaps_controller.rb +3 -1
- data/app/controllers/admin/attachments_controller.rb +5 -3
- data/app/controllers/admin/categories_controller.rb +2 -0
- data/app/controllers/admin/images_controller.rb +16 -8
- data/app/controllers/admin/invites_controller.rb +4 -1
- data/app/controllers/admin/pages_controller.rb +9 -26
- data/app/controllers/admin/password_resets_controller.rb +9 -5
- data/app/controllers/admin/users_controller.rb +10 -4
- data/app/controllers/concerns/pages_core/admin/news_page_controller.rb +13 -11
- data/app/controllers/concerns/pages_core/admin/persistent_params.rb +75 -0
- data/app/controllers/concerns/pages_core/authentication.rb +13 -5
- data/app/controllers/concerns/pages_core/error_renderer.rb +3 -0
- data/app/controllers/concerns/pages_core/error_reporting.rb +36 -0
- data/app/controllers/concerns/pages_core/policies_helper.rb +4 -1
- data/app/controllers/concerns/pages_core/preview_pages_controller.rb +8 -0
- data/app/controllers/concerns/pages_core/process_titler.rb +2 -0
- data/app/controllers/concerns/pages_core/rss_controller.rb +2 -0
- data/app/controllers/concerns/pages_core/static_cache_controller.rb +48 -0
- data/app/controllers/errors_controller.rb +5 -53
- data/app/controllers/pages_core/admin_controller.rb +7 -67
- data/app/controllers/pages_core/attachments_controller.rb +10 -6
- data/app/controllers/pages_core/base_controller.rb +11 -17
- data/app/controllers/pages_core/frontend/page_files_controller.rb +6 -2
- data/app/controllers/pages_core/frontend/pages_controller.rb +14 -18
- data/app/controllers/pages_core/frontend_controller.rb +3 -0
- data/app/controllers/pages_core/images_controller.rb +3 -1
- data/app/controllers/pages_core/sitemaps_controller.rb +11 -5
- data/app/controllers/sessions_controller.rb +3 -1
- data/app/formatters/pages_core/html_formatter.rb +13 -63
- data/app/formatters/pages_core/image_embedder.rb +79 -0
- data/app/formatters/pages_core/link_renderer.rb +4 -2
- data/app/helpers/admin/admin_helper.rb +2 -0
- data/app/helpers/admin/menu_helper.rb +6 -4
- data/app/helpers/admin/pages_helper.rb +4 -57
- data/app/helpers/application_helper.rb +3 -1
- data/app/helpers/frontend_helper.rb +3 -1
- data/app/helpers/pages_core/admin/admin_helper.rb +22 -106
- data/app/helpers/pages_core/admin/content_tabs_helper.rb +31 -0
- data/app/helpers/pages_core/admin/date_range_helper.rb +55 -0
- data/app/helpers/pages_core/admin/form_builder.rb +8 -0
- data/app/helpers/pages_core/admin/image_uploads_helper.rb +47 -0
- data/app/helpers/pages_core/admin/labelled_field_helper.rb +12 -9
- data/app/helpers/pages_core/admin/page_blocks_helper.rb +66 -0
- data/app/helpers/pages_core/admin/page_json_helper.rb +23 -0
- data/app/helpers/pages_core/admin/tag_editor_helper.rb +11 -39
- data/app/helpers/pages_core/application_helper.rb +3 -0
- data/app/helpers/pages_core/attachments_helper.rb +31 -27
- data/app/helpers/pages_core/form_builder.rb +17 -13
- data/app/helpers/pages_core/frontend_helper.rb +3 -3
- data/app/helpers/pages_core/head_tags_helper.rb +18 -22
- data/app/helpers/pages_core/images_helper.rb +3 -0
- data/app/helpers/pages_core/meta_tags_helper.rb +3 -1
- data/app/helpers/pages_core/open_graph_tags_helper.rb +8 -6
- data/app/helpers/pages_core/page_path_helper.rb +24 -3
- data/app/javascript/admin-dist.js +2 -0
- data/app/javascript/components/Attachments/Attachment.jsx +121 -0
- data/app/javascript/components/Attachments/AttachmentEditor.jsx +116 -0
- data/app/javascript/components/Attachments/Placeholder.jsx +10 -0
- data/app/javascript/components/Attachments.jsx +165 -0
- data/app/{assets/javascripts/pages/admin/components/date_range_select.jsx → javascript/components/DateRangeSelect.jsx} +16 -5
- data/app/javascript/components/EditableImage.jsx +61 -0
- data/app/{assets/javascripts/pages/admin/components/file_upload_button.jsx → javascript/components/FileUploadButton.jsx} +11 -1
- data/app/{assets/javascripts/pages/admin/components/focal_point.jsx → javascript/components/ImageCropper/FocalPoint.jsx} +12 -1
- data/app/javascript/components/ImageCropper/Image.jsx +65 -0
- data/app/javascript/components/ImageCropper/Toolbar.jsx +73 -0
- data/app/javascript/components/ImageCropper/useCrop.js +199 -0
- data/app/javascript/components/ImageCropper.jsx +90 -0
- data/app/javascript/components/ImageEditor/Form.jsx +98 -0
- data/app/javascript/components/ImageEditor.jsx +62 -0
- data/app/javascript/components/ImageGrid/DragElement.jsx +30 -0
- data/app/javascript/components/ImageGrid/FilePlaceholder.jsx +9 -0
- data/app/javascript/components/ImageGrid/GridImage.jsx +103 -0
- data/app/javascript/components/ImageGrid/Placeholder.jsx +23 -0
- data/app/javascript/components/ImageGrid.jsx +257 -0
- data/app/javascript/components/ImageUploader.jsx +171 -0
- data/app/{assets/javascripts/pages/admin/components/modal.jsx → javascript/components/Modal.jsx} +13 -2
- data/app/javascript/components/ModalStore.jsx +12 -0
- data/app/{assets/javascripts/pages/admin/components/page_dates.jsx → javascript/components/PageDates.jsx} +11 -1
- data/app/{assets/javascripts/pages/admin/components/page_files.jsx → javascript/components/PageFiles.jsx} +11 -2
- data/app/{assets/javascripts/pages/admin/components/page_images.jsx → javascript/components/PageImages.jsx} +11 -2
- data/app/{assets/javascripts/pages/admin/components/page_tree_store.jsx → javascript/components/PageTree.jsx} +127 -137
- data/app/{assets/javascripts/pages/admin/components/page_tree.jsx → javascript/components/PageTreeDraggable.jsx} +44 -38
- data/app/{assets/javascripts/pages/admin/components/page_tree_node.jsx → javascript/components/PageTreeNode.jsx} +46 -31
- data/app/javascript/components/RichTextArea.jsx +213 -0
- data/app/javascript/components/RichTextToolbarButton.jsx +20 -0
- data/app/javascript/components/TagEditor/AddTagForm.jsx +42 -0
- data/app/javascript/components/TagEditor/Tag.jsx +32 -0
- data/app/javascript/components/TagEditor.jsx +61 -0
- data/app/javascript/components/Toast.jsx +72 -0
- data/app/javascript/components/ToastStore.jsx +14 -0
- data/app/javascript/components/drag/draggedOrder.js +51 -0
- data/app/javascript/components/drag/useDragCollection.js +84 -0
- data/app/javascript/components/drag/useDragUploader.js +112 -0
- data/app/javascript/components/drag/useDraggable.js +17 -0
- data/app/javascript/components/drag.js +6 -0
- data/app/javascript/components.js +14 -0
- data/app/javascript/controllers/EditPageController.js +20 -0
- data/app/javascript/controllers/LoginController.js +29 -0
- data/app/javascript/controllers/MainController.js +65 -0
- data/app/javascript/controllers/PageOptionsController.js +62 -0
- data/app/javascript/features/RichText.jsx +34 -0
- data/app/javascript/hooks.js +2 -0
- data/app/javascript/index.js +33 -0
- data/app/{assets/javascripts/pages/admin/lib/tree.jsx → javascript/lib/Tree.js} +64 -63
- data/app/javascript/lib/copyToClipboard.js +13 -0
- data/app/javascript/lib/readyHandler.js +22 -0
- data/app/javascript/lib/request.js +36 -0
- data/app/jobs/pages_core/autopublish_job.rb +3 -1
- data/app/jobs/pages_core/sweep_cache_job.rb +4 -2
- data/app/mailers/admin_mailer.rb +4 -14
- data/app/models/attachment.rb +10 -8
- data/app/models/autopublisher.rb +3 -0
- data/app/models/category.rb +3 -1
- data/app/models/concerns/pages_core/has_roles.rb +2 -0
- data/app/models/concerns/pages_core/humanizable_param.rb +9 -6
- data/app/models/concerns/pages_core/page_model/attachments.rb +2 -0
- data/app/models/concerns/pages_core/page_model/autopublishable.rb +2 -0
- data/app/models/concerns/pages_core/page_model/dated_page.rb +11 -11
- data/app/models/concerns/pages_core/page_model/images.rb +8 -2
- data/app/models/concerns/pages_core/page_model/localizable.rb +2 -0
- data/app/models/concerns/pages_core/page_model/pathable.rb +26 -25
- data/app/models/concerns/pages_core/page_model/redirectable.rb +3 -1
- data/app/models/concerns/pages_core/page_model/searchable.rb +19 -0
- data/app/models/concerns/pages_core/page_model/sortable.rb +6 -5
- data/app/models/concerns/pages_core/page_model/status.rb +2 -0
- data/app/models/concerns/pages_core/page_model/templateable.rb +7 -2
- data/app/models/concerns/pages_core/page_model/tree.rb +27 -20
- data/app/models/concerns/pages_core/searchable_document.rb +71 -0
- data/app/models/concerns/pages_core/sweepable.rb +4 -2
- data/app/models/concerns/pages_core/taggable.rb +33 -12
- data/app/models/image.rb +14 -1
- data/app/models/invite.rb +3 -1
- data/app/models/invite_role.rb +5 -3
- data/app/models/page.rb +6 -3
- data/app/models/page_builder.rb +2 -0
- data/app/models/page_category.rb +3 -1
- data/app/models/page_exporter.rb +23 -10
- data/app/models/page_file.rb +3 -1
- data/app/models/page_image.rb +3 -3
- data/app/models/page_path.rb +13 -5
- data/app/models/password_reset_token.rb +3 -1
- data/app/models/role.rb +9 -6
- data/app/models/search_document.rb +72 -0
- data/app/models/tag.rb +9 -6
- data/app/models/tagging.rb +4 -2
- data/app/models/user.rb +8 -5
- data/app/policies/invite_policy.rb +2 -0
- data/app/policies/page_file_policy.rb +2 -0
- data/app/policies/page_image_policy.rb +2 -0
- data/app/policies/page_policy.rb +2 -0
- data/app/policies/policy.rb +2 -0
- data/app/policies/user_policy.rb +2 -0
- data/app/{serializers/admin/attachment_serializer.rb → resources/admin/attachment_resource.rb} +10 -7
- data/app/{serializers/admin/image_serializer.rb → resources/admin/image_resource.rb} +13 -11
- data/app/resources/admin/page_file_resource.rb +10 -0
- data/app/resources/admin/page_image_resource.rb +10 -0
- data/app/resources/export/attachment_resource.rb +10 -0
- data/app/resources/export/page_image_resource.rb +45 -0
- data/app/resources/export/page_resource.rb +42 -0
- data/app/{serializers/page_image_serializer.rb → resources/page_image_resource.rb} +10 -16
- data/app/resources/page_resource.rb +33 -0
- data/app/services/pages_core/create_user_service.rb +5 -2
- data/app/services/pages_core/destroy_invite_service.rb +25 -0
- data/app/services/pages_core/invite_service.rb +4 -2
- data/app/views/admin/images/show.json.jbuilder +2 -0
- data/app/views/admin/pages/_edit_content.html.erb +1 -1
- data/app/views/admin/pages/_edit_files.html.erb +1 -5
- data/app/views/admin/pages/_edit_images.html.erb +1 -5
- data/app/views/admin/pages/_edit_metadata.html.erb +1 -12
- data/app/views/admin/pages/_edit_options.html.erb +74 -55
- data/app/views/admin/pages/_form.html.erb +19 -0
- data/app/views/admin/pages/edit.html.erb +35 -61
- data/app/views/admin/pages/index.html.erb +0 -1
- data/app/views/admin/pages/new.html.erb +32 -32
- data/app/views/admin/pages/news.html.erb +1 -1
- data/app/views/admin/users/_access_control.html.erb +5 -1
- data/app/views/admin/users/login.html.erb +12 -4
- data/app/views/errors/500.html.erb +2 -20
- data/app/views/errors/_generic_help.html.erb +1 -1
- data/app/views/feeds/pages.rss.builder +3 -2
- data/app/views/layouts/admin/_header.html.erb +1 -1
- data/app/views/layouts/admin/_page_header.html.erb +33 -0
- data/app/views/layouts/admin.html.erb +23 -42
- data/app/views/pages_core/_google_analytics.html.erb +8 -0
- data/app/views/sitemaps/show.xml.builder +2 -0
- data/config/routes.rb +5 -6
- data/db/migrate/20111219033112_create_pages_tables.rb +192 -271
- data/db/migrate/20180625154059_enable_search_extensions.rb +10 -0
- data/db/migrate/20210209151400_create_search_configurations.rb +35 -0
- data/db/migrate/20210210235200_create_search_documents.rb +74 -0
- data/lib/pages_core/admin_menu_item.rb +3 -0
- data/lib/pages_core/archive_finder.rb +12 -16
- data/lib/pages_core/attachment_embedder.rb +4 -6
- data/lib/pages_core/cache_sweeper.rb +10 -108
- data/lib/pages_core/configuration/base.rb +5 -0
- data/lib/pages_core/configuration/pages.rb +4 -2
- data/lib/pages_core/configuration.rb +2 -0
- data/lib/pages_core/digest_verifier.rb +5 -5
- data/lib/pages_core/engine.rb +53 -5
- data/lib/pages_core/extensions/string_extensions.rb +3 -1
- data/lib/pages_core/extensions.rb +2 -0
- data/lib/pages_core/page_path_constraint.rb +2 -0
- data/lib/pages_core/pages_plugin.rb +3 -1
- data/lib/pages_core/plugin.rb +4 -52
- data/lib/pages_core/pub_sub.rb +2 -0
- data/lib/pages_core/static_cache/null_handler.rb +17 -0
- data/lib/pages_core/static_cache/page_cache_handler.rb +56 -0
- data/lib/pages_core/static_cache/varnish_handler.rb +55 -0
- data/lib/pages_core/static_cache.rb +26 -0
- data/lib/pages_core/templates/block_configuration.rb +4 -1
- data/lib/pages_core/templates/configuration.rb +5 -1
- data/lib/pages_core/templates/configuration_handler.rb +5 -3
- data/lib/pages_core/templates/configuration_proxy.rb +2 -0
- data/lib/pages_core/templates/controller_actions.rb +2 -0
- data/lib/pages_core/templates/template_configuration.rb +20 -14
- data/lib/pages_core/templates.rb +5 -3
- data/lib/pages_core/version.rb +3 -1
- data/lib/pages_core.rb +13 -5
- data/lib/rails/generators/pages_core/frontend/frontend_generator.rb +2 -7
- data/lib/rails/generators/pages_core/install/install_generator.rb +3 -7
- data/lib/rails/generators/pages_core/install/templates/active_job_initializer.rb +2 -0
- data/lib/rails/generators/pages_core/install/templates/application_controller.rb +2 -0
- data/lib/rails/generators/pages_core/install/templates/application_helper.rb +2 -0
- data/lib/rails/generators/pages_core/install/templates/delayed_job +1 -0
- data/lib/rails/generators/pages_core/install/templates/delayed_job_initializer.rb +17 -0
- data/lib/rails/generators/pages_core/install/templates/frontend_controller.rb +2 -0
- data/lib/rails/generators/pages_core/install/templates/frontend_helper.rb +2 -0
- data/lib/rails/generators/pages_core/install/templates/gitignore.erb +12 -1
- data/lib/rails/generators/pages_core/install/templates/page_templates_initializer.rb +4 -2
- data/lib/rails/generators/pages_core/install/templates/pages_controller.rb +2 -0
- data/lib/rails/generators/pages_core/install/templates/pages_initializer.rb +2 -6
- data/lib/rails/generators/pages_core/rspec/rspec_generator.rb +18 -14
- data/lib/rails/generators/pages_core/rspec/templates/factories.rb +3 -8
- data/lib/rails/generators/pages_core/rspec/templates/mailer_macros.rb +2 -0
- data/lib/rails/generators/pages_core/rspec/templates/page_templates_spec.rb +26 -0
- data/lib/rails/generators/pages_core/rspec/templates/rails_helper.rb +91 -0
- data/lib/rails/generators/pages_core/rspec/templates/spec_helper.rb +89 -36
- data/lib/tasks/pages/cache.rake +8 -5
- data/lib/tasks/pages/export.rake +3 -1
- data/lib/tasks/pages/page_paths.rake +2 -0
- data/lib/tasks/pages.rake +3 -2
- data/template.rb +2 -0
- metadata +193 -156
- data/app/assets/javascripts/pages/admin/components/attachment.jsx +0 -130
- data/app/assets/javascripts/pages/admin/components/attachment_editor.jsx +0 -131
- data/app/assets/javascripts/pages/admin/components/attachments.jsx +0 -211
- data/app/assets/javascripts/pages/admin/components/drag_uploader.jsx +0 -174
- data/app/assets/javascripts/pages/admin/components/editable_image.jsx +0 -57
- data/app/assets/javascripts/pages/admin/components/grid_image.jsx +0 -124
- data/app/assets/javascripts/pages/admin/components/image_editor.jsx +0 -496
- data/app/assets/javascripts/pages/admin/components/image_grid.jsx +0 -301
- data/app/assets/javascripts/pages/admin/components/image_uploader.jsx +0 -171
- data/app/assets/javascripts/pages/admin/components/modal_store.jsx +0 -20
- data/app/assets/javascripts/pages/admin/components/rich_text_area.jsx +0 -63
- data/app/assets/javascripts/pages/admin/components/rich_text_toolbar.jsx +0 -58
- data/app/assets/javascripts/pages/admin/components/toast.jsx +0 -37
- data/app/assets/javascripts/pages/admin/components/toast_store.jsx +0 -52
- data/app/assets/javascripts/pages/admin/components.jsx +0 -2
- data/app/assets/javascripts/pages/admin/features/content_tabs.jsx +0 -72
- data/app/assets/javascripts/pages/admin/features/edit_page.jsx +0 -97
- data/app/assets/javascripts/pages/admin/features/rich_text.jsx +0 -14
- data/app/assets/javascripts/pages/admin/features/tag_editor.jsx +0 -160
- data/app/assets/javascripts/pages/admin.jsx +0 -17
- data/app/assets/javascripts/pages/login_form.jsx +0 -21
- data/app/controllers/concerns/pages_core/domain_based_cache.rb +0 -26
- data/app/serializers/admin/page_file_serializer.rb +0 -6
- data/app/serializers/admin/page_image_serializer.rb +0 -6
- data/app/serializers/page_export_serializer.rb +0 -30
- data/app/serializers/page_file_export_serializer.rb +0 -4
- data/app/serializers/page_image_export_serializer.rb +0 -40
- data/app/serializers/page_serializer.rb +0 -21
- data/app/views/admin_mailer/error_report.html.erb +0 -70
- data/app/views/errors/500_critical.html.erb +0 -7
- data/app/views/errors/report.html.erb +0 -4
- data/app/views/layouts/admin/_analytics.html.erb +0 -16
- data/config/removed_migrations.yml +0 -60
- data/db/migrate/20120627033112_rename_textbits.rb +0 -17
- data/db/migrate/20121010055412_drop_removed_tables.rb +0 -81
- data/db/migrate/20130130053932_add_queue_to_delayed_jobs.rb +0 -9
- data/db/migrate/20130303053932_remove_filter_from_localizations.rb +0 -9
- data/db/migrate/20130303160632_remove_imagesets.rb +0 -22
- data/db/migrate/20130303161732_remove_sms_subscribers.rb +0 -14
- data/db/migrate/20130823133208_update_page_redirect_to.rb +0 -10
- data/db/migrate/20140203183900_create_roles.rb +0 -66
- data/db/migrate/20140414150500_change_locale_names.rb +0 -11
- data/db/migrate/20140604142100_remove_openid_url.rb +0 -9
- data/db/migrate/20140920231700_convert_images_to_dis.rb +0 -81
- data/db/migrate/20140922124600_convert_page_files_to_dis.rb +0 -50
- data/db/migrate/20141004003100_create_password_reset_tokens.rb +0 -10
- data/db/migrate/20141006181300_remove_user_cruft.rb +0 -11
- data/db/migrate/20141007173000_create_invites.rb +0 -16
- data/db/migrate/20150204130800_update_delayed_job_table.rb +0 -9
- data/db/migrate/20150401131300_localize_images.rb +0 -38
- data/db/migrate/20150520174300_add_meta_image_to_page.rb +0 -5
- data/db/migrate/20150904164200_add_pinned_to_tags.rb +0 -5
- data/db/migrate/20151002174800_create_page_paths.rb +0 -10
- data/db/migrate/20151021103400_drop_binaries_table.rb +0 -7
- data/db/migrate/20151204151000_remove_page_content_order.rb +0 -5
- data/db/migrate/20160330220900_rename_pages_categories.rb +0 -6
- data/db/migrate/20160405202700_change_localization_limit.rb +0 -9
- data/db/migrate/20170716040500_remove_page_comments.rb +0 -23
- data/db/migrate/20170716213400_remove_sessions.rb +0 -15
- data/db/migrate/20180207134000_add_dates_to_pages.rb +0 -11
- data/db/migrate/20190211154800_create_attachments.rb +0 -73
- data/lib/rails/generators/pages_core/frontend/templates/application.js.erb +0 -15
- data/lib/rails/generators/pages_core/install/templates/cache_sweeper_initializer.rb +0 -6
- data/lib/tasks/pages/update.rake +0 -17
- data/vendor/assets/javascripts/ReactCrop.min.js +0 -1
- data/vendor/assets/javascripts/reflux.min.js +0 -1
@@ -1,55 +1,56 @@
|
|
1
1
|
/*
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
2
|
+
Based on
|
3
|
+
|
4
|
+
js-tree by Wang Zuo
|
5
|
+
https://github.com/wangzuo/js-tree
|
6
|
+
|
7
|
+
react-ui-tree
|
8
|
+
https://github.com/pqx/react-ui-tree
|
9
|
+
|
10
|
+
The MIT License (MIT)
|
11
|
+
|
12
|
+
Copyright (c) 2015 Wang Zuo
|
13
|
+
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
16
|
+
in the Software without restriction, including without limitation the rights
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
19
|
+
furnished to do so, subject to the following conditions:
|
20
|
+
|
21
|
+
The above copyright notice and this permission notice shall be included in
|
22
|
+
all copies or substantial portions of the Software.
|
23
|
+
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
30
|
+
SOFTWARE.
|
31
|
+
|
32
|
+
Copyright (c) 2015 pqx Limited
|
33
|
+
|
34
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
35
|
+
of this software and associated documentation files (the "Software"), to deal
|
36
|
+
in the Software without restriction, including without limitation the rights
|
37
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
38
|
+
copies of the Software, and to permit persons to whom the Software is
|
39
|
+
furnished to do so, subject to the following conditions:
|
40
|
+
|
41
|
+
The above copyright notice and this permission notice shall be included in
|
42
|
+
all copies or substantial portions of the Software.
|
43
|
+
|
44
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
45
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
46
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
47
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
48
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
49
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
50
|
+
SOFTWARE.
|
51
|
+
*/
|
52
|
+
|
53
|
+
export default class Tree {
|
53
54
|
constructor(obj) {
|
54
55
|
this.cnt = 1;
|
55
56
|
this.obj = obj || { children: [] };
|
@@ -63,7 +64,7 @@ class Tree {
|
|
63
64
|
var self = this;
|
64
65
|
|
65
66
|
var index = { id: startId, node: obj };
|
66
|
-
indexes[this.cnt +
|
67
|
+
indexes[this.cnt + ""] = index;
|
67
68
|
this.cnt++;
|
68
69
|
|
69
70
|
if (obj.children && obj.children.length) {
|
@@ -72,7 +73,7 @@ class Tree {
|
|
72
73
|
|
73
74
|
function walk(objs, parent) {
|
74
75
|
var children = [];
|
75
|
-
objs.forEach(function(obj
|
76
|
+
objs.forEach(function(obj) {
|
76
77
|
var index = {};
|
77
78
|
index.id = self.cnt;
|
78
79
|
index.node = obj;
|
@@ -81,7 +82,7 @@ class Tree {
|
|
81
82
|
index.parent = parent.id;
|
82
83
|
}
|
83
84
|
|
84
|
-
indexes[self.cnt +
|
85
|
+
indexes[self.cnt + ""] = index;
|
85
86
|
children.push(self.cnt);
|
86
87
|
self.cnt++;
|
87
88
|
|
@@ -92,7 +93,7 @@ class Tree {
|
|
92
93
|
parent.children = children;
|
93
94
|
|
94
95
|
children.forEach(function(id, i) {
|
95
|
-
var index = indexes[id +
|
96
|
+
var index = indexes[id + ""];
|
96
97
|
if (i > 0) {
|
97
98
|
index.prev = children[i - 1];
|
98
99
|
}
|
@@ -106,7 +107,7 @@ class Tree {
|
|
106
107
|
}
|
107
108
|
|
108
109
|
getIndex(id) {
|
109
|
-
var index = this.indexes[id +
|
110
|
+
var index = this.indexes[id + ""];
|
110
111
|
if (index) {
|
111
112
|
return index;
|
112
113
|
}
|
@@ -117,7 +118,7 @@ class Tree {
|
|
117
118
|
del(index);
|
118
119
|
|
119
120
|
function del(index) {
|
120
|
-
delete self.indexes[index.id +
|
121
|
+
delete self.indexes[index.id + ""];
|
121
122
|
if (index.children && index.children.length) {
|
122
123
|
index.children.forEach(function(child) {
|
123
124
|
del(self.getIndex(child));
|
@@ -259,13 +260,13 @@ class Tree {
|
|
259
260
|
var obj = this.remove(fromId);
|
260
261
|
var index = null;
|
261
262
|
|
262
|
-
if (placement ===
|
263
|
+
if (placement === "before") {
|
263
264
|
index = this.insertBefore(obj, toId);
|
264
|
-
} else if (placement ===
|
265
|
+
} else if (placement === "after") {
|
265
266
|
index = this.insertAfter(obj, toId);
|
266
|
-
} else if(placement ===
|
267
|
+
} else if(placement === "prepend") {
|
267
268
|
index = this.prepend(obj, toId);
|
268
|
-
} else if(placement ===
|
269
|
+
} else if(placement === "append") {
|
269
270
|
index = this.append(obj, toId);
|
270
271
|
}
|
271
272
|
|
@@ -276,7 +277,7 @@ class Tree {
|
|
276
277
|
|
277
278
|
getParent(id) {
|
278
279
|
var indexes = this.indexes;
|
279
|
-
if (
|
280
|
+
if (Object.prototype.hasOwnProperty.call(indexes, id)) {
|
280
281
|
return this.getIndex(indexes[id].parent);
|
281
282
|
}
|
282
283
|
}
|
@@ -284,7 +285,7 @@ class Tree {
|
|
284
285
|
getNodeByTop(top) {
|
285
286
|
var indexes = this.indexes;
|
286
287
|
for(var id in indexes) {
|
287
|
-
if (
|
288
|
+
if (Object.prototype.hasOwnProperty.call(indexes, id)) {
|
288
289
|
if(indexes[id].top === top) {
|
289
290
|
return indexes[id];
|
290
291
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
export function copySupported () {
|
2
|
+
return document.queryCommandSupported &&
|
3
|
+
document.queryCommandSupported("copy");
|
4
|
+
}
|
5
|
+
|
6
|
+
export default function copyToClipboard (str) {
|
7
|
+
const el = document.createElement("textarea");
|
8
|
+
el.value = str;
|
9
|
+
document.body.appendChild(el);
|
10
|
+
el.select();
|
11
|
+
document.execCommand("copy");
|
12
|
+
document.body.removeChild(el);
|
13
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
let readyHandlers = [];
|
2
|
+
|
3
|
+
const handleState = () => {
|
4
|
+
if (["interactive", "complete"].indexOf(document.readyState) > -1) {
|
5
|
+
while(readyHandlers.length > 0) {
|
6
|
+
(readyHandlers.shift())();
|
7
|
+
}
|
8
|
+
}
|
9
|
+
};
|
10
|
+
|
11
|
+
class ReadyHandler {
|
12
|
+
constructor () {
|
13
|
+
document.onreadystatechange = handleState;
|
14
|
+
}
|
15
|
+
|
16
|
+
ready (handler) {
|
17
|
+
readyHandlers.push(handler);
|
18
|
+
handleState();
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
export default new ReadyHandler();
|
@@ -0,0 +1,36 @@
|
|
1
|
+
export function csrfToken() {
|
2
|
+
return document.querySelector("[name=csrf-token]").content;
|
3
|
+
}
|
4
|
+
|
5
|
+
function jsonFetchOptions() {
|
6
|
+
return({ method: "POST",
|
7
|
+
headers: { "Content-Type": "application/json; charset=utf-8",
|
8
|
+
"X-CSRF-Token": csrfToken() } });
|
9
|
+
}
|
10
|
+
|
11
|
+
export async function postJson(url, data) {
|
12
|
+
const options = { ...jsonFetchOptions(), method: "POST" };
|
13
|
+
if (data) {
|
14
|
+
options.body = JSON.stringify(data);
|
15
|
+
}
|
16
|
+
const response = await fetch(url, options);
|
17
|
+
return response.json();
|
18
|
+
}
|
19
|
+
|
20
|
+
export async function putJson(url, data) {
|
21
|
+
const options = { ...jsonFetchOptions(), method: "PUT" };
|
22
|
+
if (data) {
|
23
|
+
options.body = JSON.stringify(data);
|
24
|
+
}
|
25
|
+
const response = await fetch(url, options);
|
26
|
+
return response.json();
|
27
|
+
}
|
28
|
+
|
29
|
+
export async function post(url, data) {
|
30
|
+
const response = await fetch(url, {
|
31
|
+
method: "POST",
|
32
|
+
body: data,
|
33
|
+
headers: { "X-CSRF-Token": csrfToken() }
|
34
|
+
});
|
35
|
+
return response.json();
|
36
|
+
}
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PagesCore
|
2
|
-
class SweepCacheJob <
|
4
|
+
class SweepCacheJob < ApplicationJob
|
3
5
|
queue_as :pages_core
|
4
6
|
|
5
7
|
def perform
|
6
|
-
PagesCore::
|
8
|
+
PagesCore::StaticCache.handler.sweep_now!
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
data/app/mailers/admin_mailer.rb
CHANGED
@@ -1,17 +1,7 @@
|
|
1
|
-
|
2
|
-
default from: proc { "\"Pages\" <support@anyone.no>" }
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
@from = from
|
7
|
-
@description = description
|
8
|
-
short_message = @error_report[:message].gsub(/[\s\n]+/, " ")[0..80]
|
9
|
-
mail(
|
10
|
-
to: "system+error@anyone.no",
|
11
|
-
from: "\"Error reports\" <system+error@anyone.no>",
|
12
|
-
subject: "[#{PagesCore.config(:site_name)}] Error: #{short_message}"
|
13
|
-
)
|
14
|
-
end
|
3
|
+
class AdminMailer < ApplicationMailer
|
4
|
+
default from: proc { "\"Pages\" <support@anyone.no>" }
|
15
5
|
|
16
6
|
def password_reset(user, url)
|
17
7
|
@user = user
|
@@ -26,7 +16,7 @@ class AdminMailer < ActionMailer::Base
|
|
26
16
|
@invite = invite
|
27
17
|
@url = url
|
28
18
|
mail(
|
29
|
-
to:
|
19
|
+
to: @invite.email,
|
30
20
|
subject: "#{PagesCore.config(:site_name)} has invited you to Pages"
|
31
21
|
)
|
32
22
|
end
|
data/app/models/attachment.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Attachment < ApplicationRecord
|
2
4
|
include Dis::Model
|
3
5
|
include PagesCore::Sweepable
|
4
6
|
|
@@ -25,12 +27,12 @@ class Attachment < ActiveRecord::Base
|
|
25
27
|
|
26
28
|
def formats
|
27
29
|
{
|
28
|
-
"audio/mpeg"
|
29
|
-
"image/gif"
|
30
|
-
"image/jpeg"
|
31
|
-
"image/jpg"
|
32
|
-
"image/pjpeg"
|
33
|
-
"image/png"
|
30
|
+
"audio/mpeg" => :mp3,
|
31
|
+
"image/gif" => :gif,
|
32
|
+
"image/jpeg" => :jpg,
|
33
|
+
"image/jpg" => :jpg,
|
34
|
+
"image/pjpeg" => :jpg,
|
35
|
+
"image/png" => :png,
|
34
36
|
"application/pdf" => :pdf
|
35
37
|
}
|
36
38
|
end
|
@@ -52,7 +54,7 @@ class Attachment < ActiveRecord::Base
|
|
52
54
|
|
53
55
|
def filename_extension
|
54
56
|
if filename_extension?
|
55
|
-
filename.match(/\.([
|
57
|
+
filename.match(/\.([^.]+)$/)[1]
|
56
58
|
else
|
57
59
|
""
|
58
60
|
end
|
data/app/models/autopublisher.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Autopublisher
|
2
4
|
class << self
|
3
5
|
def run!(_options = {})
|
@@ -13,6 +15,7 @@ class Autopublisher
|
|
13
15
|
|
14
16
|
def queue!
|
15
17
|
return unless queued_pages.any?
|
18
|
+
|
16
19
|
PagesCore::AutopublishJob
|
17
20
|
.set(wait_until: queued_pages.first.published_at)
|
18
21
|
.perform_later
|
data/app/models/category.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PagesCore
|
2
4
|
module HumanizableParam
|
3
5
|
include ActiveSupport::Inflector
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
6
8
|
def humanized_param(slug)
|
7
|
-
return id.to_s unless slug
|
9
|
+
return id.to_s unless slug&.present?
|
10
|
+
|
8
11
|
"#{id}-" + transliterate(slug)
|
9
12
|
.downcase
|
10
|
-
.gsub(/[\[
|
11
|
-
.gsub(/
|
12
|
-
.gsub(/[^[[:alnum:]]()
|
13
|
-
.gsub(
|
14
|
-
.gsub(/(
|
13
|
+
.gsub(/[\[{]/, "(")
|
14
|
+
.gsub(/}\]/, ")")
|
15
|
+
.gsub(/[^[[:alnum:]]()-]+/, "-")
|
16
|
+
.gsub(/-{2,}/, "-")
|
17
|
+
.gsub(/(^-|-$)/, "")
|
15
18
|
end
|
16
19
|
end
|
17
20
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PagesCore
|
2
4
|
module PageModel
|
3
5
|
module DatedPage
|
@@ -14,25 +16,21 @@ module PagesCore
|
|
14
16
|
module ClassMethods
|
15
17
|
end
|
16
18
|
|
17
|
-
# Finds the page's next sibling by date. Returns nil if there
|
19
|
+
# Finds the page's next sibling by date. Returns nil if there
|
20
|
+
# isn't one.
|
18
21
|
def next_sibling_by_date
|
19
|
-
|
20
|
-
return unless siblings.any?
|
21
|
-
|
22
|
-
siblings[(siblings.to_a.index(self) + 1)...siblings.length]
|
23
|
-
.try(&:first)
|
22
|
+
siblings_by_date.where("starts_at >= ?", starts_at)&.first
|
24
23
|
end
|
25
24
|
|
26
|
-
# Finds the page's previous sibling by date. Returns nil if
|
25
|
+
# Finds the page's previous sibling by date. Returns nil if
|
26
|
+
# there isn't one.
|
27
27
|
def previous_sibling_by_date
|
28
|
-
|
29
|
-
return unless siblings.any?
|
30
|
-
|
31
|
-
siblings[0...siblings.to_a.index(self)].try(&:last)
|
28
|
+
siblings_by_date.where("starts_at < ?", starts_at)&.last
|
32
29
|
end
|
33
30
|
|
34
31
|
def upcoming?
|
35
32
|
return false unless ends_at?
|
33
|
+
|
36
34
|
ends_at > Time.zone.now
|
37
35
|
end
|
38
36
|
|
@@ -53,6 +51,8 @@ module PagesCore
|
|
53
51
|
|
54
52
|
def siblings_by_date
|
55
53
|
siblings.reorder("starts_at ASC, pages.id DESC")
|
54
|
+
.where
|
55
|
+
.not(id: id)
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PagesCore
|
2
4
|
module PageModel
|
3
5
|
module Images
|
@@ -6,7 +8,9 @@ module PagesCore
|
|
6
8
|
included do
|
7
9
|
belongs_to_image :image, optional: true
|
8
10
|
belongs_to_image :meta_image, class_name: "Image", optional: true
|
9
|
-
has_many :page_images, -> { order("position") },
|
11
|
+
has_many :page_images, -> { order("position") },
|
12
|
+
inverse_of: :page,
|
13
|
+
dependent: :destroy
|
10
14
|
has_many(
|
11
15
|
:images,
|
12
16
|
-> { where(page_images: { primary: false }).order("position") },
|
@@ -16,7 +20,9 @@ module PagesCore
|
|
16
20
|
after_save :update_primary_image
|
17
21
|
|
18
22
|
accepts_nested_attributes_for :page_images,
|
19
|
-
reject_if: proc { |a|
|
23
|
+
reject_if: proc { |a|
|
24
|
+
a["image_id"].blank?
|
25
|
+
},
|
20
26
|
allow_destroy: true
|
21
27
|
end
|
22
28
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PagesCore
|
2
4
|
module PageModel
|
3
5
|
module Pathable
|
@@ -6,43 +8,32 @@ module PagesCore
|
|
6
8
|
included do
|
7
9
|
has_many :page_paths, dependent: :destroy
|
8
10
|
|
9
|
-
validates :path_segment, format: { with: /\A[[[:alnum:]]
|
11
|
+
validates :path_segment, format: { with: /\A[[[:alnum:]]-_]*\z/ }
|
10
12
|
validate :path_segment_cannot_be_routable
|
11
13
|
before_validation :ensure_no_path_segment_on_deletion
|
12
14
|
after_save :ensure_path_segment
|
13
15
|
after_save :associate_page_path
|
14
16
|
end
|
15
17
|
|
16
|
-
def full_path
|
17
|
-
|
18
|
-
return nil unless full_path?(last_segment)
|
19
|
-
if parent
|
20
|
-
[parent.full_path, last_segment].join("/")
|
21
|
-
else
|
22
|
-
last_segment
|
23
|
-
end
|
18
|
+
def full_path
|
19
|
+
generate_full_path
|
24
20
|
end
|
25
21
|
|
26
|
-
def full_path?
|
27
|
-
|
28
|
-
if parent
|
29
|
-
parent.full_path? && last_segment.present?
|
30
|
-
else
|
31
|
-
last_segment.present?
|
32
|
-
end
|
22
|
+
def full_path?
|
23
|
+
path_segment.present? && pathable?
|
33
24
|
end
|
34
25
|
|
35
26
|
def ensure_path_segment
|
36
27
|
return if deleted? || path_segment? || !name?
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
end
|
28
|
+
|
29
|
+
segment = generated_path_segment
|
30
|
+
segment = "#{segment}-#{id}" if path_collision?(segment)
|
31
|
+
update(path_segment: segment)
|
42
32
|
end
|
43
33
|
|
44
34
|
def pathable?
|
45
35
|
return true unless parent
|
36
|
+
|
46
37
|
parent.full_path?
|
47
38
|
end
|
48
39
|
|
@@ -50,18 +41,27 @@ module PagesCore
|
|
50
41
|
|
51
42
|
def associate_page_path
|
52
43
|
return if deleted? || !full_path?
|
44
|
+
|
53
45
|
PagePath.build(self)
|
54
46
|
end
|
55
47
|
|
56
48
|
def ensure_no_path_segment_on_deletion
|
57
49
|
return unless deleted?
|
50
|
+
|
58
51
|
self.path_segment = nil
|
59
52
|
end
|
60
53
|
|
54
|
+
def generate_full_path(last_segment = nil)
|
55
|
+
last_segment ||= path_segment
|
56
|
+
return nil unless last_segment.present? && pathable?
|
57
|
+
|
58
|
+
[parent&.full_path, last_segment].compact.join("/")
|
59
|
+
end
|
60
|
+
|
61
61
|
def generated_path_segment
|
62
|
-
transliterated_name.gsub(/[^[[:alnum:]]
|
63
|
-
.gsub(
|
64
|
-
.gsub(/(
|
62
|
+
transliterated_name.gsub(/[^[[:alnum:]]-_]+/, "-")
|
63
|
+
.gsub(/-{2,}/, "-")
|
64
|
+
.gsub(/(^-|-$)/, "")
|
65
65
|
.mb_chars
|
66
66
|
.downcase
|
67
67
|
end
|
@@ -81,12 +81,13 @@ module PagesCore
|
|
81
81
|
|
82
82
|
def path_collision?(path_segment)
|
83
83
|
sibling_path_segments.include?(path_segment) ||
|
84
|
-
page_path_matches_routes?(
|
84
|
+
page_path_matches_routes?(generate_full_path(path_segment))
|
85
85
|
end
|
86
86
|
|
87
87
|
def path_segment_cannot_be_routable
|
88
88
|
return unless full_path?
|
89
89
|
return unless page_path_matches_routes?(full_path)
|
90
|
+
|
90
91
|
errors.add(:path_segment, "can't match an existing URL")
|
91
92
|
end
|
92
93
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module PagesCore
|
2
4
|
module PageModel
|
3
5
|
class InvalidRedirectUrl < StandardError; end
|
@@ -8,7 +10,6 @@ module PagesCore
|
|
8
10
|
included do
|
9
11
|
validates(:redirect_to,
|
10
12
|
format: { with: %r{\A(/|https?://).+\z},
|
11
|
-
allow_nil: true,
|
12
13
|
allow_blank: true })
|
13
14
|
end
|
14
15
|
|
@@ -24,6 +25,7 @@ module PagesCore
|
|
24
25
|
unless value.is_a?(String) || value.is_a?(Symbol)
|
25
26
|
raise InvalidRedirectUrl, "must be a string or a symbol"
|
26
27
|
end
|
28
|
+
|
27
29
|
path.gsub!("/:#{key}", "/#{value}")
|
28
30
|
end
|
29
31
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PagesCore
|
4
|
+
module PageModel
|
5
|
+
module Searchable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def search_document_attributes
|
9
|
+
super.merge(
|
10
|
+
published: published?,
|
11
|
+
name: name,
|
12
|
+
description: try(&:meta_description?) ? meta_description : excerpt,
|
13
|
+
# content: "",
|
14
|
+
tags: tag_names.join(" ")
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|