ghost 5.2.2 → 5.3.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.
- package/content/themes/casper/assets/built/screen.css +1 -1
- package/content/themes/casper/assets/built/screen.css.map +1 -1
- package/content/themes/casper/assets/css/screen.css +31 -1
- package/content/themes/casper/default.hbs +1 -0
- package/content/themes/casper/package.json +1 -1
- package/content/themes/casper/partials/icons/search.hbs +1 -0
- package/core/boot.js +3 -1
- package/core/bridge.js +7 -0
- package/core/built/assets/codemirror/{codemirror-d25c379b87ec8b33d54ac7149bc0b6ae.js → codemirror-30201ab2cff61db847193fc9f5ed922d.js} +1 -1
- package/core/built/assets/ghost-dark-9e5d1f0dfae41232e5e34e4d0df53ae0.css +1 -0
- package/core/built/assets/ghost.min-e7cfbd1800f8e99b9158f74f1e39cd76.css +1 -0
- package/core/built/assets/{ghost.min-971a0ff706bbf9e24f0b0a5770c8fc41.js → ghost.min-f4bba3a2a5ef256b82641345505d4f0f.js} +69 -66
- package/core/built/assets/icons/activity-placeholder.svg +3 -0
- package/core/built/assets/simplemde/{simplemde-3ffc0ec9e9fecf29b9a499db678c9e65.js → simplemde-fb4527da6e489b34dc24b28ea870b286.js} +1 -1
- package/core/built/assets/{vendor.min-ea369e6487643585f35409d474b06789.js → vendor.min-4076498ccd6c8412365f43b156084ed8.js} +119 -117
- package/core/built/assets/{vendor.min-ba66b98f7c24fa40e061c7ffc94f4e23.css → vendor.min-4a6661c574707ceca220aa2e76558995.css} +2 -1
- package/core/frontend/helpers/comment_count.js +25 -0
- package/core/frontend/helpers/comments.js +67 -0
- package/core/frontend/helpers/date.js +3 -1
- package/core/frontend/helpers/ghost_head.js +13 -0
- package/core/frontend/services/admin-auth-assets/index.js +4 -0
- package/core/frontend/services/admin-auth-assets/service.js +93 -0
- package/core/frontend/services/comment-counts-assets/index.js +4 -0
- package/core/frontend/services/comment-counts-assets/service.js +59 -0
- package/core/frontend/services/theme-engine/middleware/update-global-template-options.js +5 -1
- package/core/frontend/src/admin-auth/index.html +5 -0
- package/core/frontend/src/admin-auth/message-handler.js +75 -0
- package/core/frontend/src/comment-counts/js/comment-counts.js +71 -0
- package/core/frontend/web/site.js +3 -0
- package/core/server/api/{canary → endpoints}/actions.js +0 -0
- package/core/server/api/{canary → endpoints}/authentication.js +0 -0
- package/core/server/api/{canary → endpoints}/authors-public.js +0 -0
- package/core/server/api/endpoints/comments-comments.js +247 -0
- package/core/server/api/endpoints/comments.js +25 -0
- package/core/server/api/{canary → endpoints}/config.js +0 -0
- package/core/server/api/{canary → endpoints}/custom-theme-settings.js +0 -0
- package/core/server/api/{canary → endpoints}/db.js +0 -0
- package/core/server/api/{canary → endpoints}/email-post.js +0 -0
- package/core/server/api/{canary → endpoints}/email-previews.js +0 -0
- package/core/server/api/{canary → endpoints}/emails.js +0 -0
- package/core/server/api/endpoints/explore.js +12 -0
- package/core/server/api/{canary → endpoints}/files.js +0 -0
- package/core/server/api/{canary → endpoints}/identities.js +0 -0
- package/core/server/api/{canary → endpoints}/images.js +0 -0
- package/core/server/api/{canary → endpoints}/index.js +16 -0
- package/core/server/api/{canary → endpoints}/integrations.js +0 -0
- package/core/server/api/{canary → endpoints}/invites.js +0 -0
- package/core/server/api/{canary → endpoints}/labels.js +0 -0
- package/core/server/api/{canary → endpoints}/mail.js +0 -0
- package/core/server/api/{canary → endpoints}/media.js +0 -0
- package/core/server/api/{canary → endpoints}/member-signin-urls.js +0 -0
- package/core/server/api/{canary → endpoints}/members-stripe-connect.js +0 -0
- package/core/server/api/{canary → endpoints}/members.js +0 -0
- package/core/server/api/{canary → endpoints}/newsletters-public.js +0 -0
- package/core/server/api/{canary → endpoints}/newsletters.js +0 -0
- package/core/server/api/{canary → endpoints}/notifications.js +0 -0
- package/core/server/api/{canary → endpoints}/oembed.js +0 -0
- package/core/server/api/{canary → endpoints}/offers-public.js +0 -0
- package/core/server/api/{canary → endpoints}/offers.js +0 -0
- package/core/server/api/{canary → endpoints}/pages-public.js +0 -0
- package/core/server/api/{canary → endpoints}/pages.js +0 -0
- package/core/server/api/{canary → endpoints}/posts-public.js +0 -0
- package/core/server/api/{canary → endpoints}/posts.js +0 -0
- package/core/server/api/{canary → endpoints}/previews.js +0 -0
- package/core/server/api/{canary → endpoints}/redirects.js +0 -0
- package/core/server/api/{canary → endpoints}/roles.js +0 -0
- package/core/server/api/{canary → endpoints}/schedules.js +0 -0
- package/core/server/api/{canary → endpoints}/session.js +0 -0
- package/core/server/api/{canary → endpoints}/settings-public.js +0 -0
- package/core/server/api/{canary → endpoints}/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/site.js +0 -0
- package/core/server/api/{canary → endpoints}/slack.js +0 -0
- package/core/server/api/{canary → endpoints}/slugs.js +0 -0
- package/core/server/api/{canary → endpoints}/snippets.js +0 -0
- package/core/server/api/{canary → endpoints}/stats.js +0 -0
- package/core/server/api/{canary → endpoints}/tags-public.js +0 -0
- package/core/server/api/{canary → endpoints}/tags.js +0 -0
- package/core/server/api/{canary → endpoints}/themes.js +0 -0
- package/core/server/api/{canary → endpoints}/tiers-public.js +0 -0
- package/core/server/api/{canary → endpoints}/tiers.js +0 -0
- package/core/server/api/{canary → endpoints}/users.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/permissions.js +3 -3
- package/core/server/api/{canary → endpoints}/utils/serializers/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/authors.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/db.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/integrations.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/media.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/members.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/pages.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/posts.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/settings.js +2 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/tags.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/tiers.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/users.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/input/utils/slug-filter-order.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/utils/url.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/input/webhooks.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/all.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/authentication.js +1 -1
- package/core/server/api/endpoints/utils/serializers/output/comments.js +5 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/config.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/custom-theme-settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/db.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/default.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/email-posts.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/explore.js +11 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/files.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/images.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/index.js +8 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mail.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/actions.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/authors.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/mappers/comments.js +50 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/emails.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/images.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/index.js +1 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/integrations.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/newsletters.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/pages.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/posts.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/snippets.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/tags.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/mappers/users.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/media.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/members-stripe-connect.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/members.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/notifications.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/oembed.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/offers.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/pages.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/posts.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/previews.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/redirects.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/roles.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/schedules.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/session.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/site.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/slack.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/slugs.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/themes.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/tiers.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/users.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/clean.js +2 -1
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/date.js +0 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +67 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/post-gating.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/serializers/output/utils/url.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/files.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/images.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/invitations.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/invites.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/labels.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/media.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/members.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/oembed.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/pages.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/password_reset.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/posts.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/settings.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/setup.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/snippets.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/tags.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/tiers.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/input/users.js +1 -1
- package/core/server/api/{canary → endpoints}/utils/validators/input/webhooks.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/output/index.js +0 -0
- package/core/server/api/{canary → endpoints}/utils/validators/utils/json-schema.js +0 -0
- package/core/server/api/{canary → endpoints}/webhooks.js +0 -0
- package/core/server/api/index.js +1 -1
- package/core/server/data/exporter/table-lists.js +4 -2
- package/core/server/data/migrations/versions/5.3/2022-07-04-13-49-add-comments-table.js +13 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-09-36-add-comments-likes-table.js +9 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-09-47-add-comments-reports-table.js +10 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-10-00-add-comment-related-fields-to-members.js +21 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-12-55-add-comments-crud-permissions.js +68 -0
- package/core/server/data/migrations/versions/5.3/2022-07-05-15-35-add-comment-notifications-field-to-users-table.js +7 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-07-26-add-comments-enabled-setting.js +8 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-07-58-add-ghost-explore-integration-role.js +31 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-13-add-ghost-explore-integration-role-permissions.js +11 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-17-add-ghost-explore-integration.js +38 -0
- package/core/server/data/migrations/versions/5.3/2022-07-06-09-26-add-ghost-explore-integration-api-key.js +73 -0
- package/core/server/data/schema/default-settings/default-settings.json +14 -0
- package/core/server/data/schema/fixtures/fixtures.json +65 -2
- package/core/server/data/schema/schema.js +31 -1
- package/core/server/models/base/plugins/crud.js +15 -0
- package/core/server/models/comment-like.js +34 -0
- package/core/server/models/comment.js +163 -0
- package/core/server/models/member.js +2 -1
- package/core/server/models/user.js +2 -1
- package/core/server/services/auth/session/express-session.js +1 -1
- package/core/server/services/comments/email-templates/new-comment-reply.hbs +199 -0
- package/core/server/services/comments/email-templates/new-comment-reply.txt.js +14 -0
- package/core/server/services/comments/email-templates/new-comment.hbs +199 -0
- package/core/server/services/comments/email-templates/new-comment.txt.js +14 -0
- package/core/server/services/comments/emails.js +164 -0
- package/core/server/services/comments/index.js +26 -0
- package/core/server/services/comments/service.js +24 -0
- package/core/server/services/explore/index.js +18 -0
- package/core/server/services/explore/service.js +55 -0
- package/core/server/services/members/middleware.js +4 -4
- package/core/server/services/members/utils.js +2 -1
- package/core/server/services/permissions/can-this.js +18 -5
- package/core/server/services/permissions/parse-context.js +5 -0
- package/core/server/services/permissions/providers.js +17 -1
- package/core/server/services/posts/posts-service.js +14 -0
- package/core/server/services/users.js +84 -1
- package/core/server/web/admin/app.js +4 -0
- package/core/server/web/admin/views/default-prod.html +5 -5
- package/core/server/web/admin/views/default.html +5 -5
- package/core/server/web/api/app.js +2 -2
- package/core/server/web/api/{canary → endpoints}/admin/app.js +4 -4
- package/core/server/web/api/{canary → endpoints}/admin/middleware.js +1 -0
- package/core/server/web/api/{canary → endpoints}/admin/routes.js +6 -1
- package/core/server/web/api/{canary → endpoints}/content/app.js +4 -4
- package/core/server/web/api/{canary → endpoints}/content/middleware.js +0 -0
- package/core/server/web/api/{canary → endpoints}/content/routes.js +1 -1
- package/core/server/web/api/testmode/routes.js +1 -1
- package/core/server/web/comments/index.js +1 -0
- package/core/server/web/comments/routes.js +28 -0
- package/core/server/web/members/app.js +5 -0
- package/core/server/web/parent/frontend.js +1 -0
- package/core/shared/config/defaults.json +16 -6
- package/core/shared/config/env/config.testing.json +4 -0
- package/core/shared/config/overrides.json +1 -0
- package/core/shared/labs.js +2 -1
- package/core/shared/settings-cache/public.js +2 -1
- package/package.json +20 -20
- package/yarn.lock +425 -275
- package/Gruntfile.js +0 -384
- package/core/built/assets/ghost-dark-923c90399aa560625a983a6ae9abb38c.css +0 -1
- package/core/built/assets/ghost.min-c74f50609022cebf13ad28810def68b6.css +0 -1
- package/core/built/assets/img/contributors/AileenCGN-bf8b9ffbb34c0fd93beb8136af07771b.jpeg +0 -0
- package/core/built/assets/img/contributors/ErisDS-c958ccb9e3597320dee745a42f478569.jpeg +0 -0
- package/core/built/assets/img/contributors/GeorginaLusby-6cea5defddee3c4ea7320e580521e832.jpeg +0 -0
- package/core/built/assets/img/contributors/JohnONolan-47041b80c35c6341b9b929b03139aecc.jpeg +0 -0
- package/core/built/assets/img/contributors/acburdine-d9777fe2601dc215afb6723315829c89.jpeg +0 -0
- package/core/built/assets/img/contributors/bnookala-5896fcdd2f477495323e420efe890657.jpeg +0 -0
- package/core/built/assets/img/contributors/cobbspur-07ded67009757d12517621fc856eba62.jpeg +0 -0
- package/core/built/assets/img/contributors/dbalders-452347a406c2ca23657daea9100878f3.jpeg +0 -0
- package/core/built/assets/img/contributors/disordinary-b9997e5debb59b7aadc79ba90955b662.jpeg +0 -0
- package/core/built/assets/img/contributors/felixrieseberg-ecf29e8eadc58fab999c507049f898cf.jpeg +0 -0
- package/core/built/assets/img/contributors/frantzypants-637b03f85dff89700a661fde79daea5c.jpeg +0 -0
- package/core/built/assets/img/contributors/halfdan-00d6783e5fba2900ee1380939297d8ee.jpeg +0 -0
- package/core/built/assets/img/contributors/jaswilli-8cc9a8d2539ca03239d113dfb25ff5c2.jpeg +0 -0
- package/core/built/assets/img/contributors/kevinansfield-925606c55bc2f3f2f05c0fa58b953ad1.jpeg +0 -0
- package/core/built/assets/img/contributors/kevinkucharczyk-3c7dfe2a103a83737b9d5ee8e19d67f8.jpeg +0 -0
- package/core/built/assets/img/contributors/kirrg001-79823418f2ca21e81719653f0286f95b.jpeg +0 -0
- package/core/built/assets/img/contributors/mixonic-1ff87736dd02cfa080ae109b45131aa6.png +0 -0
- package/core/built/assets/img/contributors/rwjblue-5c7cc009cda45baca2d45f0d1ed19e48.jpeg +0 -0
- package/core/built/assets/img/contributors/sebgie-0fb02df00ee7834dbcc8beba84aec81e.png +0 -0
- package/core/built/assets/img/contributors/tgriesser-d871cbf74a871c0fb6d855e76a893f7e.png +0 -0
- package/core/server/api/canary/utils/serializers/output/utils/extra-attrs.js +0 -33
- package/urls.json +0 -597
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const {SafeString} = require('../services/handlebars');
|
|
2
|
+
const {labs} = require('../services/proxy');
|
|
3
|
+
|
|
4
|
+
function commentCount(options) {
|
|
5
|
+
return new SafeString(`
|
|
6
|
+
<span data-ghost-comment-count="${this.id}" style="display:none">
|
|
7
|
+
${options.fn(this)}
|
|
8
|
+
</span>`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = async function commentsLabsWrapper() {
|
|
13
|
+
const self = this;
|
|
14
|
+
const args = arguments;
|
|
15
|
+
|
|
16
|
+
return labs.enabledHelper({
|
|
17
|
+
flagKey: 'comments',
|
|
18
|
+
flagName: 'Comments',
|
|
19
|
+
helperName: 'comments'
|
|
20
|
+
}, () => {
|
|
21
|
+
return commentCount.apply(self, args);
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
module.exports.async = true;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const {SafeString} = require('../services/handlebars');
|
|
2
|
+
const {config, urlUtils, getFrontendKey, labs} = require('../services/proxy');
|
|
3
|
+
|
|
4
|
+
async function comments(options) {
|
|
5
|
+
// todo: For now check on the comment id to exclude normal pages (we probably have a better way to do this)
|
|
6
|
+
|
|
7
|
+
const commentId = this.comment_id;
|
|
8
|
+
|
|
9
|
+
if (!commentId) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let colorScheme = 'auto';
|
|
14
|
+
if (options.hash.color_scheme === 'dark' || options.hash.color_scheme === 'light') {
|
|
15
|
+
colorScheme = options.hash.color_scheme;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let avatarSaturation = parseInt(options.hash.avatar_saturation);
|
|
19
|
+
if (isNaN(avatarSaturation)) {
|
|
20
|
+
avatarSaturation = 50;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let accentColor = '';
|
|
24
|
+
if (options.data.site.accent_color) {
|
|
25
|
+
accentColor = options.data.site.accent_color;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const frontendKey = await getFrontendKey();
|
|
29
|
+
|
|
30
|
+
const data = {
|
|
31
|
+
'ghost-comments': urlUtils.getSiteUrl(),
|
|
32
|
+
api: urlUtils.urlFor('api', {type: 'content'}, true),
|
|
33
|
+
admin: urlUtils.urlFor('admin', true),
|
|
34
|
+
key: frontendKey,
|
|
35
|
+
'post-id': this.id,
|
|
36
|
+
'sentry-dsn': '', /* todo: insert sentry dsn key here */
|
|
37
|
+
'color-scheme': colorScheme,
|
|
38
|
+
'avatar-saturation': avatarSaturation,
|
|
39
|
+
'accent-color': accentColor,
|
|
40
|
+
'app-version': config.get('comments:version')
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
let dataAttributes = '';
|
|
44
|
+
|
|
45
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
46
|
+
dataAttributes += `data-${key}="${value}" `;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return new SafeString(`
|
|
50
|
+
<script defer src="${config.get('comments:url')}" ${dataAttributes} crossorigin="anonymous"></script>
|
|
51
|
+
`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = async function commentsLabsWrapper() {
|
|
55
|
+
const self = this;
|
|
56
|
+
const args = arguments;
|
|
57
|
+
|
|
58
|
+
return labs.enabledHelper({
|
|
59
|
+
flagKey: 'comments',
|
|
60
|
+
flagName: 'Comments',
|
|
61
|
+
helperName: 'comments'
|
|
62
|
+
}, () => {
|
|
63
|
+
return comments.apply(self, args);
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
module.exports.async = true;
|
|
@@ -45,7 +45,9 @@ module.exports = function (...attrs) {
|
|
|
45
45
|
// i18n: Making dates, including month names, translatable to any language.
|
|
46
46
|
// Documentation: http://momentjs.com/docs/#/i18n/
|
|
47
47
|
// Locales: https://github.com/moment/moment/tree/develop/locale
|
|
48
|
-
|
|
48
|
+
if (locale && locale.match('^[^/\\\\]*$') !== null) {
|
|
49
|
+
dateMoment.locale(locale);
|
|
50
|
+
}
|
|
49
51
|
|
|
50
52
|
if (timeago) {
|
|
51
53
|
date = dateMoment.tz(timezone).from(timeNow);
|
|
@@ -57,6 +57,14 @@ function getMembersHelper(data, frontendKey) {
|
|
|
57
57
|
return membersHelper;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
function getSearchHelper(frontendKey) {
|
|
61
|
+
const adminUrl = urlUtils.getAdminUrl() || urlUtils.getSiteUrl();
|
|
62
|
+
|
|
63
|
+
let helper = `<script defer src="${config.get('sodoSearch:url')}" data-sodo-search="${adminUrl}" data-version="${config.get('sodoSearch:version')}" data-key="${frontendKey}" crossorigin="anonymous"></script>`;
|
|
64
|
+
|
|
65
|
+
return helper;
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
/**
|
|
61
69
|
* **NOTE**
|
|
62
70
|
* Express adds `_locals`, see https://github.com/expressjs/express/blob/4.15.4/lib/response.js#L962.
|
|
@@ -193,6 +201,7 @@ module.exports = async function ghost_head(options) { // eslint-disable-line cam
|
|
|
193
201
|
// no code injection for amp context!!!
|
|
194
202
|
if (!_.includes(context, 'amp')) {
|
|
195
203
|
head.push(getMembersHelper(options.data, frontendKey));
|
|
204
|
+
head.push(getSearchHelper(frontendKey));
|
|
196
205
|
|
|
197
206
|
// @TODO do this in a more "frameworky" way
|
|
198
207
|
if (cardAssetService.hasFile('js')) {
|
|
@@ -202,6 +211,10 @@ module.exports = async function ghost_head(options) { // eslint-disable-line cam
|
|
|
202
211
|
head.push(`<link rel="stylesheet" type="text/css" href="${getAssetUrl('public/cards.min.css')}">`);
|
|
203
212
|
}
|
|
204
213
|
|
|
214
|
+
if (labs.isSet('comments') && settingsCache.get('enable_comments') !== 'off') {
|
|
215
|
+
head.push(`<script defer src="${getAssetUrl('public/comment-counts.min.js')}" data-ghost-comments-counts-api="${urlUtils.getSiteUrl(true)}members/api/comments/counts/"></script>`);
|
|
216
|
+
}
|
|
217
|
+
|
|
205
218
|
if (!_.isEmpty(globalCodeinjection)) {
|
|
206
219
|
head.push(globalCodeinjection);
|
|
207
220
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// const debug = require('@tryghost/debug')('comments-counts-assets');
|
|
2
|
+
const Minifier = require('@tryghost/minifier');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs').promises;
|
|
5
|
+
const logging = require('@tryghost/logging');
|
|
6
|
+
const config = require('../../../shared/config');
|
|
7
|
+
|
|
8
|
+
class AdminAuthAssetsService {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
/** @private */
|
|
11
|
+
this.src = options.src || path.join(config.get('paths').assetSrc, 'admin-auth');
|
|
12
|
+
/** @private */
|
|
13
|
+
this.dest = options.dest || path.join(config.getContentPath('public'), 'admin-auth');
|
|
14
|
+
/** @private */
|
|
15
|
+
this.minifier = new Minifier({src: this.src, dest: this.dest});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @private
|
|
20
|
+
*/
|
|
21
|
+
generateGlobs() {
|
|
22
|
+
return {
|
|
23
|
+
'admin-auth.min.js': '*.js'
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @private
|
|
29
|
+
* @returns {Promise<void>}
|
|
30
|
+
*/
|
|
31
|
+
async minify(globs) {
|
|
32
|
+
try {
|
|
33
|
+
await this.minifier.minify(globs);
|
|
34
|
+
} catch (error) {
|
|
35
|
+
if (error.code === 'EACCES') {
|
|
36
|
+
logging.error('Ghost was not able to write admin-auth asset files due to permissions.');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @private
|
|
46
|
+
* @returns {Promise<void>}
|
|
47
|
+
*/
|
|
48
|
+
async copyStatic() {
|
|
49
|
+
try {
|
|
50
|
+
await fs.copyFile(path.join(this.src, 'index.html'), path.join(this.dest, 'index.html'));
|
|
51
|
+
} catch (error) {
|
|
52
|
+
if (error.code === 'EACCES') {
|
|
53
|
+
logging.error('Ghost was not able to write admin-auth asset files due to permissions.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @private
|
|
63
|
+
* @returns {Promise<void>}
|
|
64
|
+
*/
|
|
65
|
+
async clearFiles() {
|
|
66
|
+
const rmFile = async (name) => {
|
|
67
|
+
await fs.unlink(path.join(this.dest, name));
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
let promises = [
|
|
71
|
+
// @deprecated switch this to use fs.rm when we drop support for Node v12
|
|
72
|
+
rmFile('admin-auth.min.js'),
|
|
73
|
+
rmFile('index.html')
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
// We don't care if removing these files fails as it's valid for them to not exist
|
|
77
|
+
await Promise.allSettled(promises);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Minify, move into the destination directory, and clear existing asset files.
|
|
82
|
+
*
|
|
83
|
+
* @returns {Promise<void>}
|
|
84
|
+
*/
|
|
85
|
+
async load() {
|
|
86
|
+
const globs = this.generateGlobs();
|
|
87
|
+
await this.clearFiles();
|
|
88
|
+
await this.minify(globs);
|
|
89
|
+
await this.copyStatic();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = AdminAuthAssetsService;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// const debug = require('@tryghost/debug')('comments-counts-assets');
|
|
2
|
+
const Minifier = require('@tryghost/minifier');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const fs = require('fs').promises;
|
|
5
|
+
const logging = require('@tryghost/logging');
|
|
6
|
+
const config = require('../../../shared/config');
|
|
7
|
+
|
|
8
|
+
class CommentCountsAssetsService {
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.src = options.src || path.join(config.get('paths').assetSrc, 'comment-counts');
|
|
11
|
+
this.dest = options.dest || config.getContentPath('public');
|
|
12
|
+
this.minifier = new Minifier({src: this.src, dest: this.dest});
|
|
13
|
+
|
|
14
|
+
this.files = [];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
generateGlobs() {
|
|
18
|
+
return {
|
|
19
|
+
'comment-counts.min.js': 'js/*.js'
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async minify(globs) {
|
|
24
|
+
try {
|
|
25
|
+
return await this.minifier.minify(globs);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (error.code === 'EACCES') {
|
|
28
|
+
logging.error('Ghost was not able to write comment-count asset files due to permissions.');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async clearFiles() {
|
|
37
|
+
this.files = [];
|
|
38
|
+
|
|
39
|
+
const rmFile = async (name) => {
|
|
40
|
+
await fs.unlink(path.join(this.dest, name));
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
let promises = [
|
|
44
|
+
// @deprecated switch this to use fs.rm when we drop support for Node v12
|
|
45
|
+
rmFile('comment-counts.min.js')
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
// We don't care if removing these files fails as it's valid for them to not exist
|
|
49
|
+
return Promise.allSettled(promises);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async load() {
|
|
53
|
+
await this.clearFiles();
|
|
54
|
+
const globs = this.generateGlobs();
|
|
55
|
+
this.files = await this.minify(globs);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = CommentCountsAssetsService;
|
|
@@ -36,7 +36,11 @@ async function updateGlobalTemplateOptions(req, res, next) {
|
|
|
36
36
|
{
|
|
37
37
|
hbs.updateTemplateOptions({
|
|
38
38
|
data: {
|
|
39
|
-
site:
|
|
39
|
+
site: {
|
|
40
|
+
...siteData,
|
|
41
|
+
comments_enabled: siteData.comments_enabled !== 'off',
|
|
42
|
+
comments_access: siteData.comments_enabled
|
|
43
|
+
},
|
|
40
44
|
labs: labsData,
|
|
41
45
|
config: themeData,
|
|
42
46
|
custom: themeSettingsData
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const adminUrl = window.location.href.replace('auth-frame/', '');
|
|
2
|
+
|
|
3
|
+
window.addEventListener('message', async function (event) {
|
|
4
|
+
if (event.origin !== '*') {
|
|
5
|
+
// return;
|
|
6
|
+
}
|
|
7
|
+
let data = null;
|
|
8
|
+
try {
|
|
9
|
+
data = JSON.parse(event.data);
|
|
10
|
+
} catch (err) {
|
|
11
|
+
console.error(err);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function respond(error, result) {
|
|
15
|
+
event.source.postMessage(JSON.stringify({
|
|
16
|
+
uid: data.uid,
|
|
17
|
+
error: error,
|
|
18
|
+
result: result
|
|
19
|
+
}), '*');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (data.action === 'getUser') {
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetch(
|
|
25
|
+
adminUrl + 'api/canary/admin/users/me/'
|
|
26
|
+
);
|
|
27
|
+
const json = await res.json();
|
|
28
|
+
respond(null, json);
|
|
29
|
+
} catch (err) {
|
|
30
|
+
respond(err, null);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (data.action === 'hideComment') {
|
|
35
|
+
try {
|
|
36
|
+
const res = await fetch(adminUrl + 'api/canary/admin/comments/' + data.id + '/', {
|
|
37
|
+
method: 'PUT',
|
|
38
|
+
body: JSON.stringify({
|
|
39
|
+
comments: [{
|
|
40
|
+
id: data.id,
|
|
41
|
+
status: 'hidden'
|
|
42
|
+
}]
|
|
43
|
+
}),
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/json'
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const json = await res.json();
|
|
49
|
+
respond(null, json);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
respond(err, null);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (data.action === 'showComment') {
|
|
56
|
+
try {
|
|
57
|
+
const res = await fetch(adminUrl + 'api/canary/admin/comments/' + data.id + '/', {
|
|
58
|
+
method: 'PUT',
|
|
59
|
+
body: JSON.stringify({
|
|
60
|
+
comments: [{
|
|
61
|
+
id: data.id,
|
|
62
|
+
status: 'published'
|
|
63
|
+
}]
|
|
64
|
+
}),
|
|
65
|
+
headers: {
|
|
66
|
+
'Content-Type': 'application/json'
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const json = await res.json();
|
|
70
|
+
respond(null, json);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
respond(err, null);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
(async function () {
|
|
2
|
+
const countsMap = {};
|
|
3
|
+
const fetchingIds = new Set();
|
|
4
|
+
|
|
5
|
+
const api = document.querySelector('[data-ghost-comments-counts-api]')
|
|
6
|
+
.dataset.ghostCommentsCountsApi;
|
|
7
|
+
|
|
8
|
+
const debounce = function (func, timeout = 100) {
|
|
9
|
+
let timer;
|
|
10
|
+
return (...args) => {
|
|
11
|
+
clearTimeout(timer);
|
|
12
|
+
timer = setTimeout(() => func.apply(this, args), timeout);
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const addIdsFromElement = function (node) {
|
|
17
|
+
const countElems = node.querySelectorAll?.('[data-ghost-comment-count]') || [];
|
|
18
|
+
|
|
19
|
+
countElems.forEach((countElem) => {
|
|
20
|
+
if (!countsMap[countElem.dataset.ghostCommentCount]) {
|
|
21
|
+
fetchingIds.add(countElem.dataset.ghostCommentCount);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const renderCounts = function () {
|
|
27
|
+
for (const [id, count] of Object.entries(countsMap)) {
|
|
28
|
+
const countElems = document.querySelectorAll(`[data-ghost-comment-count="${id}"]`);
|
|
29
|
+
countElems.forEach((e) => {
|
|
30
|
+
e.innerHTML = e.innerHTML.replace('#', count);
|
|
31
|
+
e.style.display = '';
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const fetchCounts = async function () {
|
|
37
|
+
const ids = Array.from(fetchingIds);
|
|
38
|
+
fetchingIds.clear();
|
|
39
|
+
|
|
40
|
+
const rawRes = await fetch(api, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: {
|
|
43
|
+
Accept: 'application/json',
|
|
44
|
+
'Content-Type': 'application/json'
|
|
45
|
+
},
|
|
46
|
+
body: JSON.stringify({ids})
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const res = await rawRes.json();
|
|
50
|
+
|
|
51
|
+
for (const [id, count] of Object.entries(res)) {
|
|
52
|
+
countsMap[id] = count;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
renderCounts();
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const countElemObserver = new MutationObserver((mutationsList) => {
|
|
59
|
+
mutationsList.forEach((mutation) => {
|
|
60
|
+
mutation.addedNodes.forEach((addedNode) => {
|
|
61
|
+
addIdsFromElement(addedNode);
|
|
62
|
+
debounce(fetchCounts);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
countElemObserver.observe(document.body, {subtree: true, childList: true});
|
|
68
|
+
|
|
69
|
+
addIdsFromElement(document.body);
|
|
70
|
+
fetchCounts();
|
|
71
|
+
})();
|
|
@@ -72,6 +72,9 @@ module.exports = function setupSiteApp(routerConfig) {
|
|
|
72
72
|
siteApp.use(mw.servePublicFile('built', 'public/cards.min.css', 'text/css', constants.ONE_YEAR_S));
|
|
73
73
|
siteApp.use(mw.servePublicFile('built', 'public/cards.min.js', 'application/javascript', constants.ONE_YEAR_S));
|
|
74
74
|
|
|
75
|
+
// Comment counts
|
|
76
|
+
siteApp.use(mw.servePublicFile('built', 'public/comment-counts.min.js', 'application/javascript', constants.ONE_YEAR_S));
|
|
77
|
+
|
|
75
78
|
// Serve blog images using the storage adapter
|
|
76
79
|
siteApp.use(STATIC_IMAGE_URL_PREFIX, mw.handleImageSizes, storage.getStorage('images').serve());
|
|
77
80
|
// Serve blog media using the storage adapter
|
|
File without changes
|
|
File without changes
|
|
File without changes
|