ghost 5.35.0 → 5.36.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/components/tryghost-adapter-cache-memory-ttl-5.36.0.tgz +0 -0
- package/components/tryghost-adapter-cache-redis-5.36.0.tgz +0 -0
- package/components/{tryghost-adapter-manager-5.35.0.tgz → tryghost-adapter-manager-5.36.0.tgz} +0 -0
- package/components/tryghost-api-framework-5.36.0.tgz +0 -0
- package/components/tryghost-api-version-compatibility-service-5.36.0.tgz +0 -0
- package/components/{tryghost-audience-feedback-5.35.0.tgz → tryghost-audience-feedback-5.36.0.tgz} +0 -0
- package/components/tryghost-bootstrap-socket-5.36.0.tgz +0 -0
- package/components/{tryghost-constants-5.35.0.tgz → tryghost-constants-5.36.0.tgz} +0 -0
- package/components/tryghost-custom-theme-settings-service-5.36.0.tgz +0 -0
- package/components/tryghost-data-generator-5.36.0.tgz +0 -0
- package/components/{tryghost-domain-events-5.35.0.tgz → tryghost-domain-events-5.36.0.tgz} +0 -0
- package/components/tryghost-dynamic-routing-events-5.36.0.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.36.0.tgz +0 -0
- package/components/tryghost-email-analytics-service-5.36.0.tgz +0 -0
- package/components/{tryghost-email-content-generator-5.35.0.tgz → tryghost-email-content-generator-5.36.0.tgz} +0 -0
- package/components/{tryghost-email-events-5.35.0.tgz → tryghost-email-events-5.36.0.tgz} +0 -0
- package/components/tryghost-email-service-5.36.0.tgz +0 -0
- package/components/{tryghost-email-suppression-list-5.35.0.tgz → tryghost-email-suppression-list-5.36.0.tgz} +0 -0
- package/components/tryghost-event-aware-cache-wrapper-5.36.0.tgz +0 -0
- package/components/{tryghost-express-dynamic-redirects-5.35.0.tgz → tryghost-express-dynamic-redirects-5.36.0.tgz} +0 -0
- package/components/tryghost-extract-api-key-5.36.0.tgz +0 -0
- package/components/{tryghost-html-to-plaintext-5.35.0.tgz → tryghost-html-to-plaintext-5.36.0.tgz} +0 -0
- package/components/tryghost-i18n-5.36.0.tgz +0 -0
- package/components/tryghost-importer-revue-5.36.0.tgz +0 -0
- package/components/tryghost-job-manager-5.36.0.tgz +0 -0
- package/components/{tryghost-link-redirects-5.35.0.tgz → tryghost-link-redirects-5.36.0.tgz} +0 -0
- package/components/{tryghost-link-replacer-5.35.0.tgz → tryghost-link-replacer-5.36.0.tgz} +0 -0
- package/components/tryghost-link-tracking-5.36.0.tgz +0 -0
- package/components/{tryghost-magic-link-5.35.0.tgz → tryghost-magic-link-5.36.0.tgz} +0 -0
- package/components/tryghost-mailgun-client-5.36.0.tgz +0 -0
- package/components/{tryghost-member-attribution-5.35.0.tgz → tryghost-member-attribution-5.36.0.tgz} +0 -0
- package/components/{tryghost-member-events-5.35.0.tgz → tryghost-member-events-5.36.0.tgz} +0 -0
- package/components/tryghost-members-api-5.36.0.tgz +0 -0
- package/components/{tryghost-members-csv-5.35.0.tgz → tryghost-members-csv-5.36.0.tgz} +0 -0
- package/components/{tryghost-members-events-service-5.35.0.tgz → tryghost-members-events-service-5.36.0.tgz} +0 -0
- package/components/tryghost-members-importer-5.36.0.tgz +0 -0
- package/components/{tryghost-members-offers-5.35.0.tgz → tryghost-members-offers-5.36.0.tgz} +0 -0
- package/components/{tryghost-members-payments-5.35.0.tgz → tryghost-members-payments-5.36.0.tgz} +0 -0
- package/components/{tryghost-members-ssr-5.35.0.tgz → tryghost-members-ssr-5.36.0.tgz} +0 -0
- package/components/tryghost-members-stripe-service-5.36.0.tgz +0 -0
- package/components/tryghost-milestones-5.36.0.tgz +0 -0
- package/components/tryghost-minifier-5.36.0.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.36.0.tgz +0 -0
- package/components/{tryghost-mw-cache-control-5.35.0.tgz → tryghost-mw-cache-control-5.36.0.tgz} +0 -0
- package/components/tryghost-mw-error-handler-5.36.0.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.36.0.tgz +0 -0
- package/components/{tryghost-mw-update-user-last-seen-5.35.0.tgz → tryghost-mw-update-user-last-seen-5.36.0.tgz} +0 -0
- package/components/tryghost-mw-vhost-5.36.0.tgz +0 -0
- package/components/tryghost-oembed-service-5.36.0.tgz +0 -0
- package/components/tryghost-package-json-5.36.0.tgz +0 -0
- package/components/tryghost-referrers-5.36.0.tgz +0 -0
- package/components/tryghost-security-5.36.0.tgz +0 -0
- package/components/tryghost-session-service-5.36.0.tgz +0 -0
- package/components/tryghost-settings-path-manager-5.36.0.tgz +0 -0
- package/components/tryghost-slack-notifications-5.36.0.tgz +0 -0
- package/components/tryghost-staff-service-5.36.0.tgz +0 -0
- package/components/tryghost-stats-service-5.36.0.tgz +0 -0
- package/components/tryghost-tiers-5.36.0.tgz +0 -0
- package/components/tryghost-update-check-service-5.36.0.tgz +0 -0
- package/components/tryghost-verification-trigger-5.36.0.tgz +0 -0
- package/components/{tryghost-version-notifications-data-service-5.35.0.tgz → tryghost-version-notifications-data-service-5.36.0.tgz} +0 -0
- package/components/tryghost-webmentions-5.36.0.tgz +0 -0
- package/core/built/admin/assets/{chunk.143.d49ad252968f2ef3966d.js → chunk.143.d5eaed4616c55cdbdabb.js} +6 -6
- package/core/built/admin/assets/{chunk.178.3d45fff87e08a5be5eb8.js → chunk.178.8cafcc33fe672738cc5b.js} +4 -4
- package/core/built/admin/assets/{chunk.502.c4afca88c98edad8b268.js → chunk.502.800e1515996bcc900013.js} +3 -3
- package/core/built/admin/assets/{chunk.79.ec143a398298020c87e6.js → chunk.79.53e8aa9671b2d5dae8ba.js} +1 -1
- package/core/built/admin/assets/codemirror/{codemirror-6c43f4894cbd8db73d7f35cde836c58e.js → codemirror-3f3b9966a7237652dd31484694e38ad5.js} +1 -1
- package/core/built/admin/assets/ghost-7ecf5c7934d90798485ee5ac2956f7fe.css +1 -0
- package/core/built/admin/assets/{ghost-4a6ed62455c9e367434183980b3ca3e9.js → ghost-b828e9e3c161aae92909c2e163656bb1.js} +295 -267
- package/core/built/admin/assets/ghost-dark-e50717df8e57d3e7fee67a0bcea895ad.css +1 -0
- package/core/built/admin/assets/img/mentions-background-fa39b7597e875c165b12190eda606993.png +0 -0
- package/core/built/admin/assets/simplemde/{simplemde-28049a9bd7f432b0648747eb26958a33.js → simplemde-9cd5549b68db674742d6ec2ecd72ac30.js} +1 -1
- package/core/built/admin/assets/vendor-c4684647d4f5213e5dbb6763de430e7e.js +22 -21
- package/core/built/admin/index.html +5 -5
- package/core/server/adapters/cache/MemoryTTL.js +3 -0
- package/core/server/api/endpoints/emails.js +35 -0
- package/core/server/api/endpoints/pages-public.js +1 -2
- package/core/server/api/endpoints/posts-public.js +2 -1
- package/core/server/api/endpoints/tags-public.js +2 -1
- package/core/server/api/endpoints/utils/serializers/input/index.js +4 -0
- package/core/server/api/endpoints/utils/serializers/input/mentions.js +11 -0
- package/core/server/api/endpoints/utils/serializers/output/emails.js +4 -0
- package/core/server/api/endpoints/utils/serializers/output/mappers/posts.js +2 -5
- package/core/server/api/endpoints/utils/serializers/output/utils/clean.js +1 -0
- package/core/server/api/endpoints/utils/serializers/output/utils/extra-attrs.js +19 -11
- package/core/server/data/exporter/table-lists.js +2 -1
- package/core/server/data/migrations/versions/5.36/2023-02-20-12-22-add-milestones-table.js +10 -0
- package/core/server/data/migrations/versions/5.36/2023-02-21-12-29-add-milestone-notifications-column.js +7 -0
- package/core/server/data/migrations/versions/5.36/2023-02-23-10-40-set-outbound-link-tagging-based-on-source-tracking.js +31 -0
- package/core/server/data/schema/schema.js +9 -0
- package/core/server/lib/request-external.js +14 -13
- package/core/server/models/milestone.js +9 -0
- package/core/server/models/user.js +4 -1
- package/core/server/services/email-analytics/lib/queries.js +18 -3
- package/core/server/services/email-analytics/wrapper.js +34 -15
- package/core/server/services/email-suppression-list/MailgunEmailSuppressionList.js +2 -0
- package/core/server/services/mentions/BookshelfMentionRepository.js +2 -1
- package/core/server/services/mentions/ResourceService.js +6 -0
- package/core/server/services/mentions/RoutingService.js +2 -1
- package/core/server/services/mentions/service.js +1 -3
- package/core/server/services/milestones/BookshelfMilestoneRepository.js +136 -0
- package/core/server/services/milestones/MilestoneQueries.js +8 -3
- package/core/server/services/milestones/service.js +47 -9
- package/core/server/services/oembed/nft-oembed.js +1 -2
- package/core/server/services/posts-public/service.js +21 -9
- package/core/server/services/tags-public/service.js +21 -10
- package/core/server/services/websockets/service.js +2 -1
- package/core/server/web/api/endpoints/admin/routes.js +3 -0
- package/core/shared/config/defaults.json +5 -2
- package/core/shared/labs.js +5 -4
- package/package.json +125 -124
- package/yarn.lock +151 -199
- package/components/tryghost-adapter-cache-redis-5.35.0.tgz +0 -0
- package/components/tryghost-api-framework-5.35.0.tgz +0 -0
- package/components/tryghost-api-version-compatibility-service-5.35.0.tgz +0 -0
- package/components/tryghost-bootstrap-socket-5.35.0.tgz +0 -0
- package/components/tryghost-custom-theme-settings-service-5.35.0.tgz +0 -0
- package/components/tryghost-data-generator-5.35.0.tgz +0 -0
- package/components/tryghost-dynamic-routing-events-5.35.0.tgz +0 -0
- package/components/tryghost-email-analytics-provider-mailgun-5.35.0.tgz +0 -0
- package/components/tryghost-email-analytics-service-5.35.0.tgz +0 -0
- package/components/tryghost-email-service-5.35.0.tgz +0 -0
- package/components/tryghost-extract-api-key-5.35.0.tgz +0 -0
- package/components/tryghost-i18n-5.35.0.tgz +0 -0
- package/components/tryghost-importer-revue-5.35.0.tgz +0 -0
- package/components/tryghost-job-manager-5.35.0.tgz +0 -0
- package/components/tryghost-link-tracking-5.35.0.tgz +0 -0
- package/components/tryghost-mailgun-client-5.35.0.tgz +0 -0
- package/components/tryghost-members-api-5.35.0.tgz +0 -0
- package/components/tryghost-members-importer-5.35.0.tgz +0 -0
- package/components/tryghost-members-stripe-service-5.35.0.tgz +0 -0
- package/components/tryghost-milestones-5.35.0.tgz +0 -0
- package/components/tryghost-minifier-5.35.0.tgz +0 -0
- package/components/tryghost-mw-api-version-mismatch-5.35.0.tgz +0 -0
- package/components/tryghost-mw-error-handler-5.35.0.tgz +0 -0
- package/components/tryghost-mw-session-from-token-5.35.0.tgz +0 -0
- package/components/tryghost-mw-vhost-5.35.0.tgz +0 -0
- package/components/tryghost-oembed-service-5.35.0.tgz +0 -0
- package/components/tryghost-package-json-5.35.0.tgz +0 -0
- package/components/tryghost-public-resource-repository-5.35.0.tgz +0 -0
- package/components/tryghost-referrers-5.35.0.tgz +0 -0
- package/components/tryghost-security-5.35.0.tgz +0 -0
- package/components/tryghost-session-service-5.35.0.tgz +0 -0
- package/components/tryghost-settings-path-manager-5.35.0.tgz +0 -0
- package/components/tryghost-slack-notifications-5.35.0.tgz +0 -0
- package/components/tryghost-staff-service-5.35.0.tgz +0 -0
- package/components/tryghost-stats-service-5.35.0.tgz +0 -0
- package/components/tryghost-tiers-5.35.0.tgz +0 -0
- package/components/tryghost-update-check-service-5.35.0.tgz +0 -0
- package/components/tryghost-verification-trigger-5.35.0.tgz +0 -0
- package/components/tryghost-webmentions-5.35.0.tgz +0 -0
- package/core/built/admin/assets/ghost-558c1e319d6e025bfab2054bc0f7fe83.css +0 -1
- package/core/built/admin/assets/ghost-dark-a15754df1f9070dc2525482ce22e2251.css +0 -1
- /package/core/built/admin/assets/{chunk.502.c4afca88c98edad8b268.js.LICENSE.txt → chunk.502.800e1515996bcc900013.js.LICENSE.txt} +0 -0
|
Binary file
|
|
@@ -1871,4 +1871,4 @@ return/editor-preview-active/.test(e.className)},Y.prototype.isSideBySideActive=
|
|
|
1871
1871
|
return/editor-preview-active-side/.test(e.className)},Y.prototype.isFullscreenActive=function(){return this.codemirror.getOption("fullScreen")},Y.prototype.getState=function(){return m(this.codemirror)},Y.prototype.toTextArea=function(){var e=this.codemirror,t=e.getWrapperElement()
|
|
1872
1872
|
t.parentNode&&(this.gui.toolbar&&t.parentNode.removeChild(this.gui.toolbar),this.gui.statusbar&&t.parentNode.removeChild(this.gui.statusbar),this.gui.sideBySide&&t.parentNode.removeChild(this.gui.sideBySide)),e.toTextArea(),this.autosaveTimeoutId&&(clearTimeout(this.autosaveTimeoutId),this.autosaveTimeoutId=void 0,this.clearAutosavedValue())},t.exports=Y},{"./codemirror/tablist":17,codemirror:10,"codemirror-spell-checker":4,"codemirror/addon/display/fullscreen.js":5,"codemirror/addon/display/placeholder.js":6,"codemirror/addon/edit/continuelist.js":7,"codemirror/addon/mode/overlay.js":8,"codemirror/addon/selection/mark-selection.js":9,"codemirror/mode/gfm/gfm.js":11,"codemirror/mode/markdown/markdown.js":12,"codemirror/mode/xml/xml.js":14}]},{},[18])(18)}))
|
|
1873
1873
|
|
|
1874
|
-
//# sourceMappingURL=simplemde-
|
|
1874
|
+
//# sourceMappingURL=simplemde-9cd5549b68db674742d6ec2ecd72ac30.map
|
|
@@ -9137,7 +9137,8 @@ a?.finish(),a=n({name:`route:${i}`,op:"navigation",tags:{fromRoute:r,toRoute:i,"
|
|
|
9137
9137
|
t[e.object]=r}function c(e,t,i,o){const a=t[e.object]
|
|
9138
9138
|
if(!a)return
|
|
9139
9139
|
const s=(0,n.timestampWithMs)()
|
|
9140
|
-
if(1e3*(s-a.now)>=o){(0,r.getActiveTransaction)()
|
|
9140
|
+
if(1e3*(s-a.now)>=o){const t=(0,r.getActiveTransaction)()
|
|
9141
|
+
t?.startChild({op:i,description:e.containerKey||e.object,startTimestamp:a.now,endTimestamp:s})}}function d(e){const t="@sentry/ember:initial-load-start",i="@sentry/ember:initial-load-end"
|
|
9141
9142
|
let{HAS_PERFORMANCE:o,HAS_PERFORMANCE_TIMING:a}=function(){const e=window.performance,t=Boolean(e&&e.clearMarks&&e.clearMeasures),r=Boolean(e.measure&&e.getEntriesByName&&void 0!==n.browserPerformanceTimeOrigin)
|
|
9142
9143
|
return{HAS_PERFORMANCE:t,HAS_PERFORMANCE_TIMING:r}}()
|
|
9143
9144
|
if(!o)return
|
|
@@ -9147,8 +9148,8 @@ if(!a)return
|
|
|
9147
9148
|
const l="@sentry/ember:initial-load",u=s.getEntriesByName(t).length>0,c=s.getEntriesByName(i).length>0
|
|
9148
9149
|
if(!u||!c)return
|
|
9149
9150
|
s.measure(l,t,i)
|
|
9150
|
-
const d=s.getEntriesByName(l)[0],h=(d.startTime+n.browserPerformanceTimeOrigin)/1e3,p=h+d.duration/1e3,f=(0,r.getActiveTransaction)()?.startChild({op:"ui.ember.init",startTimestamp:h})
|
|
9151
|
-
|
|
9151
|
+
const d=s.getEntriesByName(l)[0],h=(d.startTime+n.browserPerformanceTimeOrigin)/1e3,p=h+d.duration/1e3,f=(0,r.getActiveTransaction)(),m=f?.startChild({op:"ui.ember.init",startTimestamp:h})
|
|
9152
|
+
m?.finish(p),s.clearMarks(t),s.clearMarks(i),s.clearMeasures(l)}async function h(e){const a=o(),h=a.sentry,p=a.browserTracingOptions||a.sentry.browserTracingOptions||{},f=await emberAutoImportDynamic("@sentry/tracing"),m=a.transitionTimeout||5e3,g=h.integrations||[]
|
|
9152
9153
|
h.integrations=[...g,new f.Integrations.BrowserTracing({routingInstrumentation:(t,r)=>{const n=e.lookup("router:main")
|
|
9153
9154
|
let i=e.lookup("service:router")
|
|
9154
9155
|
i.externalRouter&&(i=i.externalRouter),i._hasMountedSentryPerformanceRouting||i.recognize&&(i._hasMountedSentryPerformanceRouting=!0,l(i,n,a,t,r))},idleTimeout:m,...p})]
|
|
@@ -12263,10 +12264,10 @@ Object.entries({loop:!1}).forEach((e=>{let[t,r]=e
|
|
|
12263
12264
|
void 0===this.args.payload[t]&&this.updatePayloadAttr(t,r)}))}didInsert(e){this.element=e
|
|
12264
12265
|
const{triggerBrowse:t,src:r,files:n}=this.args.payload
|
|
12265
12266
|
delete this.args.payload.triggerBrowse,delete this.args.payload.files,!t||r||n||this.triggerAudioFileDialog(),n&&(this.files=n)}registerAudioFileInput(e){this._audioFileInput=e}registerAudioThumbnailFileInput(e){this._audioThumbnailFileInput=e}triggerAudioFileDialog(e){if(this._audioFileInput)return this._audioFileInput.click()
|
|
12266
|
-
const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12267
|
-
|
|
12268
|
-
const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12269
|
-
|
|
12267
|
+
const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12268
|
+
r&&r.click()}triggerThumbnailFileDialog(e){if(this._audioThumbnailFileInput)return this._audioThumbnailFileInput.click()
|
|
12269
|
+
const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12270
|
+
r&&r.click()}deleteThumbnail(){this.updatePayloadAttr("thumbnailSrc",null)}*extractAudioMetadataTask(e){return yield(0,r.default)(e)}async audioUploadStarted(e){const t=e[0]
|
|
12270
12271
|
if(t){const e=await this.extractAudioMetadataTask.perform(t)
|
|
12271
12272
|
this.previewPayload.duration=e?.duration,this.previewPayload.mimeType=e?.mimeType}}getFormattedDuration(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:200
|
|
12272
12273
|
const t=Math.floor(e/60),r=Math.floor(e-60*t)
|
|
@@ -12299,8 +12300,8 @@ window.addEventListener("resize",e),this.willDestroy=()=>{window.removeEventList
|
|
|
12299
12300
|
n.addEventListener("load",(()=>{let e=this.selectingFile
|
|
12300
12301
|
this.selectingFile=!1,t({id:e})})),n.src=r}))}uploadSuccess(e,t){let r=new Image
|
|
12301
12302
|
r.addEventListener("load",(()=>{let n={src:e.url,width:r.naturalWidth,height:r.naturalHeight},i=`${t.id}Image`
|
|
12302
|
-
this.args.payload[i]=n,this.updateImageDimensions()})),r.src=e.url}setLayoutWide(){this.args.payload.cardWidth="wide",Ember.run.scheduleOnce("afterRender",this,this.updateImageDimensions)}setLayoutFull(){this.args.payload.cardWidth="full",Ember.run.scheduleOnce("afterRender",this,this.updateImageDimensions)}setStartingPosition(e){this.args.payload.startingPosition=Math.min(100,Math.max(0,parseInt(e.target.value)))}selectBeforeImage(){this.selectingFile="before",this._triggerFileDialog()}selectAfterImage(){this.selectingFile="after",this._triggerFileDialog()}_triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12303
|
-
|
|
12303
|
+
this.args.payload[i]=n,this.updateImageDimensions()})),r.src=e.url}setLayoutWide(){this.args.payload.cardWidth="wide",Ember.run.scheduleOnce("afterRender",this,this.updateImageDimensions)}setLayoutFull(){this.args.payload.cardWidth="full",Ember.run.scheduleOnce("afterRender",this,this.updateImageDimensions)}setStartingPosition(e){this.args.payload.startingPosition=Math.min(100,Math.max(0,parseInt(e.target.value)))}selectBeforeImage(){this.selectingFile="before",this._triggerFileDialog()}selectAfterImage(){this.selectingFile="after",this._triggerFileDialog()}_triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12304
|
+
r?.click()}uploadFailed(){}handleErrors(){}setCaption(e){this.args.payload.caption=e}leaveEditMode(){this.isEmpty&&Ember.run.scheduleOnce("afterRender",this,this.args.deleteCard)}},_=E(y.prototype,"imageWidth",[n],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),E(y.prototype,"preventDefault",[i],Object.getOwnPropertyDescriptor(y.prototype,"preventDefault"),y.prototype),E(y.prototype,"stopPropagation",[o],Object.getOwnPropertyDescriptor(y.prototype,"stopPropagation"),y.prototype),E(y.prototype,"removeFocus",[a],Object.getOwnPropertyDescriptor(y.prototype,"removeFocus"),y.prototype),E(y.prototype,"registerElement",[s],Object.getOwnPropertyDescriptor(y.prototype,"registerElement"),y.prototype),E(y.prototype,"uploadStart",[l],Object.getOwnPropertyDescriptor(y.prototype,"uploadStart"),y.prototype),E(y.prototype,"uploadSuccess",[u],Object.getOwnPropertyDescriptor(y.prototype,"uploadSuccess"),y.prototype),E(y.prototype,"setLayoutWide",[c],Object.getOwnPropertyDescriptor(y.prototype,"setLayoutWide"),y.prototype),E(y.prototype,"setLayoutFull",[d],Object.getOwnPropertyDescriptor(y.prototype,"setLayoutFull"),y.prototype),E(y.prototype,"setStartingPosition",[h],Object.getOwnPropertyDescriptor(y.prototype,"setStartingPosition"),y.prototype),E(y.prototype,"selectBeforeImage",[p],Object.getOwnPropertyDescriptor(y.prototype,"selectBeforeImage"),y.prototype),E(y.prototype,"selectAfterImage",[f],Object.getOwnPropertyDescriptor(y.prototype,"selectAfterImage"),y.prototype),E(y.prototype,"uploadFailed",[m],Object.getOwnPropertyDescriptor(y.prototype,"uploadFailed"),y.prototype),E(y.prototype,"handleErrors",[g],Object.getOwnPropertyDescriptor(y.prototype,"handleErrors"),y.prototype),E(y.prototype,"setCaption",[v],Object.getOwnPropertyDescriptor(y.prototype,"setCaption"),y.prototype),E(y.prototype,"leaveEditMode",[b],Object.getOwnPropertyDescriptor(y.prototype,"leaveEditMode"),y.prototype),y)
|
|
12304
12305
|
e.default=x,Ember._setComponentTemplate(w,x)})),define("koenig-editor/components/koenig-card-bookmark",["exports","koenig-editor/components/koenig-editor","@tryghost/helpers","ember-concurrency"],(function(e,t,r,n){"use strict"
|
|
12305
12306
|
var i,o,a,s,l,u,c,d,h,p,f,m,g,v,b
|
|
12306
12307
|
function y(e,t,r,n){r&&Object.defineProperty(e,t,{enumerable:r.enumerable,configurable:r.configurable,writable:r.writable,value:r.initializer?r.initializer.call(n):void 0})}function _(e,t,r){return(t=function(e){var t=function(e,t){if("object"!=typeof e||null===e)return e
|
|
@@ -12480,8 +12481,8 @@ Object.entries({loop:!1}).forEach((e=>{let[t,r]=e
|
|
|
12480
12481
|
void 0===this.args.payload[t]&&this.updatePayloadAttr(t,r)}))}didInsert(e){this.element=e
|
|
12481
12482
|
const{triggerBrowse:t,src:r,files:n}=this.args.payload
|
|
12482
12483
|
delete this.args.payload.triggerBrowse,delete this.args.payload.files,!t||r||n||this.triggerFileDialog(),n&&(this.files=n)}triggerFileDialog(e){if(this._fileInput)return this._fileInput.click()
|
|
12483
|
-
const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12484
|
-
|
|
12484
|
+
const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12485
|
+
r?.click()}async fileUploadStarted(e){const t=e[0]
|
|
12485
12486
|
t&&(this.previewPayload.fileSize=t.size)}async fileUploadCompleted(e){let[t]=e
|
|
12486
12487
|
this.previewPayload.src=t.url,this.previewPayload.fileName=t.fileName,this.previewPayload.fileTitle=(0,r.default)(t.fileName),this.previewPayload.fileCaption="",this.args.editor.run((()=>{this.payloadFileAttrs.forEach((e=>{this.updatePayloadAttr(e,this.previewPayload[e])}))})),this.previewPayload=new n.TrackedObject({})}fileUploadFailed(){this.args.editor.run((()=>{this.payloadFileAttrs.forEach((e=>{this.updatePayloadAttr(e,null)}))}))}setFileTitle(e){this.updatePayloadAttr("fileTitle",e)}setFileCaption(e){this.updatePayloadAttr("fileCaption",e)}updatePayloadAttr(e,t){const{payload:r}=this.args
|
|
12487
12488
|
Ember.set(r,e,t),this.args.saveCard(r,!1)}dragOver(e){e.dataTransfer&&(e.stopPropagation(),e.preventDefault(),this.isDraggedOver=!0)}dragLeave(e){e.preventDefault(),this.isDraggedOver=!1}drop(e){e.preventDefault(),e.stopPropagation(),this.isDraggedOver=!1,e.dataTransfer.files&&(this.files=[e.dataTransfer.files[0]])}_bytesToSize(e){if(!e)return"0 Byte"
|
|
@@ -12506,8 +12507,8 @@ r(i)&&(o+=1),e[o]?(i+1)%3==0||r(i+1)||i+1===t?(a.push("pl2"),s.push("ml2")):(a.p
|
|
|
12506
12507
|
let l=Object.assign({},n),u=(n.width||1)/(n.height||1)
|
|
12507
12508
|
l.style=Ember.String.htmlSafe(`flex: ${u} 1 0%`),l.classes=Ember.String.htmlSafe(a.join(" ")),l.overlayClasses=Ember.String.htmlSafe(s.join(" ")),e[o].push(l)})),e}init(){super.init(...arguments),this.payload&&!Ember.isEmpty(this.payload.images)||this._updatePayloadAttr("images",[]),this._buildImages(),this.registerComponent(this)}willDestroyElement(){super.willDestroyElement(...arguments),this._dragDropContainer&&this._dragDropContainer.destroy()}addImage(e){let t=this.images.length+1,r=Math.ceil(t/3)-1,n=this._readDataFromImageFile(e)
|
|
12508
12509
|
n.row=r,this.images.pushObject(n)}setImageSrc(e){this.images.findBy("fileName",e.fileName).set("src",e.url),this._buildAndSaveImagesPayload()}setFiles(e){this._startUpload(e)}deleteImage(e){let t=this.images.findBy("fileName",e.fileName)
|
|
12509
|
-
this.images.removeObject(t),this._recalculateImageRows(),this._buildAndSaveImagesPayload()}updateCaption(e){this._updatePayloadAttr("caption",e)}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12510
|
-
|
|
12510
|
+
this.images.removeObject(t),this._recalculateImageRows(),this._buildAndSaveImagesPayload()}updateCaption(e){this._updatePayloadAttr("caption",e)}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12511
|
+
r?.click()}uploadFailed(e){let t=this.images.findBy("fileName",e.fileName)
|
|
12511
12512
|
this.images.removeObject(t),this._buildAndSaveImagesPayload()
|
|
12512
12513
|
let r=e.fileName.length>20?`${e.fileName.substr(0,20)}...`:e.fileName
|
|
12513
12514
|
this.set("errorMessage",`${r} failed to upload`)}handleErrors(e){let t=e[0]&&e[0].message||"Some images failed to upload"
|
|
@@ -12554,8 +12555,8 @@ Object.keys(t).forEach((r=>{e.registerKeyCommand({str:r,run:()=>t[r](e,r)})})),t
|
|
|
12554
12555
|
Ember.set(r,e,t),this.args.saveCard?.(r,!1)}_afterRender(){this._placeCursorAtEnd(),this._focusInput()}_placeCursorAtEnd(){if(!this._textReplacementEditor)return
|
|
12555
12556
|
let e=this._textReplacementEditor.post.tailPosition().toRange()
|
|
12556
12557
|
this._textReplacementEditor.selectRange(e)}_focusInput(){let e=this.element.querySelector(".kg-header-card-header .koenig-basic-html-input__editor")
|
|
12557
|
-
e&&e.focus()}toggleButton(){this._updatePayloadAttr("buttonEnabled",!this.args.payload.buttonEnabled)}setSize(e){["small","medium","large"].includes(e)&&this._updatePayloadAttr("size",e)}setStyle(e){["dark","light","accent","image"].includes(e)&&(this._updatePayloadAttr("style",e),"image"!==e||this.args.payload.backgroundImageSrc||this.triggerFileDialog())}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12558
|
-
|
|
12558
|
+
e&&e.focus()}toggleButton(){this._updatePayloadAttr("buttonEnabled",!this.args.payload.buttonEnabled)}setSize(e){["small","medium","large"].includes(e)&&this._updatePayloadAttr("size",e)}setStyle(e){["dark","light","accent","image"].includes(e)&&(this._updatePayloadAttr("style",e),"image"!==e||this.args.payload.backgroundImageSrc||this.triggerFileDialog())}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12559
|
+
r&&r.click()}backgroundImageUploadCompleted(e){let[t]=e
|
|
12559
12560
|
this.args.editor.run((()=>{this._updatePayloadAttr("backgroundImageSrc",t.url)}))}deleteBackgroundImage(){this._updatePayloadAttr("backgroundImageSrc",null)}},O=R(x.prototype,"feature",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),C=R(x.prototype,"store",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),S=R(x.prototype,"membersUtils",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),T=R(x.prototype,"ui",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),P=R(x.prototype,"config",[i.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),R(x.prototype,"registerElement",[u],Object.getOwnPropertyDescriptor(x.prototype,"registerElement"),x.prototype),R(x.prototype,"registerHeaderEditor",[c],Object.getOwnPropertyDescriptor(x.prototype,"registerHeaderEditor"),x.prototype),R(x.prototype,"registerSubheaderEditor",[d],Object.getOwnPropertyDescriptor(x.prototype,"registerSubheaderEditor"),x.prototype),R(x.prototype,"setHeader",[h],Object.getOwnPropertyDescriptor(x.prototype,"setHeader"),x.prototype),R(x.prototype,"setSubheader",[p],Object.getOwnPropertyDescriptor(x.prototype,"setSubheader"),x.prototype),R(x.prototype,"setButtonUrl",[f],Object.getOwnPropertyDescriptor(x.prototype,"setButtonUrl"),x.prototype),R(x.prototype,"setButtonText",[m],Object.getOwnPropertyDescriptor(x.prototype,"setButtonText"),x.prototype),R(x.prototype,"leaveEditMode",[g],Object.getOwnPropertyDescriptor(x.prototype,"leaveEditMode"),x.prototype),R(x.prototype,"focusElement",[v],Object.getOwnPropertyDescriptor(x.prototype,"focusElement"),x.prototype),R(x.prototype,"toggleButton",[b],Object.getOwnPropertyDescriptor(x.prototype,"toggleButton"),x.prototype),R(x.prototype,"setSize",[y],Object.getOwnPropertyDescriptor(x.prototype,"setSize"),x.prototype),R(x.prototype,"setStyle",[_],Object.getOwnPropertyDescriptor(x.prototype,"setStyle"),x.prototype),R(x.prototype,"triggerFileDialog",[k],Object.getOwnPropertyDescriptor(x.prototype,"triggerFileDialog"),x.prototype),R(x.prototype,"backgroundImageUploadCompleted",[E],Object.getOwnPropertyDescriptor(x.prototype,"backgroundImageUploadCompleted"),x.prototype),R(x.prototype,"deleteBackgroundImage",[w],Object.getOwnPropertyDescriptor(x.prototype,"deleteBackgroundImage"),x.prototype),x)
|
|
12560
12561
|
e.default=D,Ember._setComponentTemplate(j,D)})),define("koenig-editor/components/koenig-card-hr",["exports","@glimmer/component"],(function(e,t){"use strict"
|
|
12561
12562
|
Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0
|
|
@@ -12594,8 +12595,8 @@ let e=["summer","mountains","ufo-attack"]
|
|
|
12594
12595
|
this.set("placeholder",e[Math.floor(Math.random()*e.length)]),this.registerComponent(this)}didReceiveAttrs(){super.didReceiveAttrs(...arguments),Ember.isEmpty(this.payload.files)||Ember.run.schedule("afterRender",this,(function(){this.set("files",this.payload.files),delete this.payload.files})),this.isSelected||this.set("isEditingAlt",!1)}didInsertElement(){if(super.didInsertElement(...arguments),this.payload.triggerBrowse&&!this.payload.src&&!this.payload.files){this._updatePayloadAttr("triggerBrowse",void 0)
|
|
12595
12596
|
let e=this.element.querySelector('input[type="file"]')
|
|
12596
12597
|
e&&e.click()}this.imageSelector&&this.scrollToCard()}updateSrc(e){let[t]=e
|
|
12597
|
-
this.editor.run((()=>{this._updatePayloadAttr("src",t.url),this._imageWidth&&this._imageHeight&&(this._updatePayloadAttr("width",this._imageWidth),this._updatePayloadAttr("height",this._imageHeight)),this._imageWidth=null,this._imageHeight=null}))}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12598
|
-
|
|
12598
|
+
this.editor.run((()=>{this._updatePayloadAttr("src",t.url),this._imageWidth&&this._imageHeight&&(this._updatePayloadAttr("width",this._imageWidth),this._updatePayloadAttr("height",this._imageHeight)),this._imageWidth=null,this._imageHeight=null}))}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12599
|
+
r?.click()}setPreviewSrc(e){let t=e[0]
|
|
12599
12600
|
if(t){let e=URL.createObjectURL(t)
|
|
12600
12601
|
this.set("previewSrc",e)
|
|
12601
12602
|
let r=new Image
|
|
@@ -12689,8 +12690,8 @@ if(t){let e=URL.createObjectURL(t)
|
|
|
12689
12690
|
this.previewSrc=e
|
|
12690
12691
|
let r=new Image
|
|
12691
12692
|
r.onload=()=>{this._productImageWidth=r.naturalWidth,this._productImageHeight=r.naturalHeight},r.src=e}}resetSrcs(){this.previewSrc=null,this._productImageWidth=null,this._productImageHeight=null,this.args.editor.run((()=>{this._updatePayloadAttr("productImageSrc",null),this._updatePayloadAttr("productImageWidth",null),this._updatePayloadAttr("productImageHeight",null)}))}updateSrc(e){let[t]=e
|
|
12692
|
-
this.args.editor.run((()=>{this._updatePayloadAttr("productImageSrc",t.url),this._productImageWidth&&this._productImageHeight&&(this._updatePayloadAttr("productImageWidth",this._productImageWidth),this._updatePayloadAttr("productImageHeight",this._productImageHeight)),this._productImageWidth=null,this._productImageHeight=null})),this.files=null}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12693
|
-
|
|
12693
|
+
this.args.editor.run((()=>{this._updatePayloadAttr("productImageSrc",t.url),this._productImageWidth&&this._productImageHeight&&(this._updatePayloadAttr("productImageWidth",this._productImageWidth),this._updatePayloadAttr("productImageHeight",this._productImageHeight)),this._productImageWidth=null,this._productImageHeight=null})),this.files=null}triggerFileDialog(e){const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12694
|
+
r?.click()}changeStars(e){this._updatePayloadAttr("productStarRating",e.currentTarget.value)}toggleProductButton(){this._updatePayloadAttr("productButtonEnabled",!this.args.payload.productButtonEnabled)}toggleProductRating(){this._updatePayloadAttr("productRatingEnabled",!this.args.payload.productRatingEnabled)}hoverStarOn(e){const t=e.currentTarget.value,r=this.element.querySelectorAll(".kg-product-card-rating-star")
|
|
12694
12695
|
for(let n=0;n+1<=t&&n<r.length;n++)r[n].classList.add("kg-product-card-rating-star-hovered")}hoverStarOff(){const e=this.element.querySelectorAll(".kg-product-card-rating-star")
|
|
12695
12696
|
for(let t=0;t<e.length;t++)e[t].classList.remove("kg-product-card-rating-star-hovered")}dragOver(e){if(e.dataTransfer){if(navigator.userAgent.indexOf("Chrome")>-1){let t=e.dataTransfer.effectAllowed
|
|
12696
12697
|
e.dataTransfer.dropEffect="move"===t||"linkMove"===t?"move":"copy"}e.stopPropagation(),e.preventDefault(),this.isDraggedOver=!0}}dragLeave(e){e.preventDefault(),this.isDraggedOver=!1}drop(e){e.preventDefault(),this.isDraggedOver=!1,e.dataTransfer.files&&(this.files=[e.dataTransfer.files[0]])}},D=q(j.prototype,"feature",[o],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),I=q(j.prototype,"store",[a],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),N=q(j.prototype,"membersUtils",[s],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),L=q(j.prototype,"ui",[l],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),F=q(j.prototype,"config",[i.inject],{configurable:!0,enumerable:!0,writable:!0,initializer:null}),z=q(j.prototype,"files",[u],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return null}}),B=q(j.prototype,"previewSrc",[c],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return null}}),H=q(j.prototype,"isDraggedOver",[d],{configurable:!0,enumerable:!0,writable:!0,initializer:function(){return!1}}),q(j.prototype,"registerElement",[h],Object.getOwnPropertyDescriptor(j.prototype,"registerElement"),j.prototype),q(j.prototype,"registerTitleEditor",[p],Object.getOwnPropertyDescriptor(j.prototype,"registerTitleEditor"),j.prototype),q(j.prototype,"registerEditor",[f],Object.getOwnPropertyDescriptor(j.prototype,"registerEditor"),j.prototype),q(j.prototype,"setProductTitle",[m],Object.getOwnPropertyDescriptor(j.prototype,"setProductTitle"),j.prototype),q(j.prototype,"setProductDescription",[g],Object.getOwnPropertyDescriptor(j.prototype,"setProductDescription"),j.prototype),q(j.prototype,"setProductUrl",[v],Object.getOwnPropertyDescriptor(j.prototype,"setProductUrl"),j.prototype),q(j.prototype,"setProductButton",[b],Object.getOwnPropertyDescriptor(j.prototype,"setProductButton"),j.prototype),q(j.prototype,"leaveEditMode",[y],Object.getOwnPropertyDescriptor(j.prototype,"leaveEditMode"),j.prototype),q(j.prototype,"focusElement",[_],Object.getOwnPropertyDescriptor(j.prototype,"focusElement"),j.prototype),q(j.prototype,"setPreviewSrc",[k],Object.getOwnPropertyDescriptor(j.prototype,"setPreviewSrc"),j.prototype),q(j.prototype,"resetSrcs",[E],Object.getOwnPropertyDescriptor(j.prototype,"resetSrcs"),j.prototype),q(j.prototype,"updateSrc",[w],Object.getOwnPropertyDescriptor(j.prototype,"updateSrc"),j.prototype),q(j.prototype,"triggerFileDialog",[x],Object.getOwnPropertyDescriptor(j.prototype,"triggerFileDialog"),j.prototype),q(j.prototype,"changeStars",[O],Object.getOwnPropertyDescriptor(j.prototype,"changeStars"),j.prototype),q(j.prototype,"toggleProductButton",[C],Object.getOwnPropertyDescriptor(j.prototype,"toggleProductButton"),j.prototype),q(j.prototype,"toggleProductRating",[S],Object.getOwnPropertyDescriptor(j.prototype,"toggleProductRating"),j.prototype),q(j.prototype,"hoverStarOn",[T],Object.getOwnPropertyDescriptor(j.prototype,"hoverStarOn"),j.prototype),q(j.prototype,"hoverStarOff",[P],Object.getOwnPropertyDescriptor(j.prototype,"hoverStarOff"),j.prototype),q(j.prototype,"dragOver",[M],Object.getOwnPropertyDescriptor(j.prototype,"dragOver"),j.prototype),q(j.prototype,"dragLeave",[A],Object.getOwnPropertyDescriptor(j.prototype,"dragLeave"),j.prototype),q(j.prototype,"drop",[R],Object.getOwnPropertyDescriptor(j.prototype,"drop"),j.prototype),j)
|
|
@@ -12732,8 +12733,8 @@ Object.entries({loop:!1}).forEach((e=>{let[t,r]=e
|
|
|
12732
12733
|
void 0===this.args.payload[t]&&this.updatePayloadAttr(t,r)}))}didInsert(e){this.element=e
|
|
12733
12734
|
const{triggerBrowse:t,src:r,files:n}=this.args.payload
|
|
12734
12735
|
delete this.args.payload.triggerBrowse,delete this.args.payload.files,!t||r||n||this.triggerVideoFileDialog(),n&&(this.files=n)}registerVideoFileInput(e){this._videoFileInput=e}triggerVideoFileDialog(e){if(this._videoFileInput)return this._videoFileInput.click()
|
|
12735
|
-
const t=(e?.target||this.element).closest(".__mobiledoc-card")?.querySelector('input[type="file"]')
|
|
12736
|
-
|
|
12736
|
+
const t=(e?.target||this.element).closest(".__mobiledoc-card"),r=t?.querySelector('input[type="file"]')
|
|
12737
|
+
r&&r.click()}async videoUploadStarted(e){const t=e[0]
|
|
12737
12738
|
if(t){const e=await this.extractVideoMetadataTask.perform(t)
|
|
12738
12739
|
this.previewPayload.duration=e.duration,this.previewPayload.width=e.width,this.previewPayload.height=e.height,this.previewPayload.mimeType=e.mimeType,e.thumbnailBlob&&(this.previewPayload.thumbnailSrc||(this.previewThumbnailSrc=URL.createObjectURL(e.thumbnailBlob)),this._thumbnailBlob=e.thumbnailBlob)}}async videoUploadCompleted(e){let[t]=e
|
|
12739
12740
|
if(this.previewPayload.src=t.url,this.previewPayload.fileName=t.fileName,await this.extractVideoMetadataTask.last,this._thumbnailBlob)try{const e=await this.uploadThumbnailFromBlobTask.perform(t.url,this._thumbnailBlob)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<title>Ghost Admin</title>
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.
|
|
11
|
+
<meta name="ghost-admin/config/environment" content="%7B%22modulePrefix%22%3A%22ghost-admin%22%2C%22environment%22%3A%22production%22%2C%22rootURL%22%3A%22%22%2C%22locationType%22%3A%22trailing-hash%22%2C%22EmberENV%22%3A%7B%22FEATURES%22%3A%7B%7D%2C%22EXTEND_PROTOTYPES%22%3A%7B%22Date%22%3Afalse%2C%22Array%22%3Atrue%2C%22String%22%3Atrue%2C%22Function%22%3Afalse%7D%2C%22_APPLICATION_TEMPLATE_WRAPPER%22%3Afalse%2C%22_JQUERY_INTEGRATION%22%3Atrue%2C%22_TEMPLATE_ONLY_GLIMMER_COMPONENTS%22%3Atrue%7D%2C%22APP%22%3A%7B%22version%22%3A%225.36%22%2C%22name%22%3A%22ghost-admin%22%7D%2C%22ember-simple-auth%22%3A%7B%7D%2C%22ember-websockets%22%3A%7B%22socketIO%22%3Atrue%7D%2C%22%40sentry%2Fember%22%3A%7B%22disablePerformance%22%3Atrue%2C%22sentry%22%3A%7B%7D%7D%2C%22ember-cli-mirage%22%3A%7B%22usingProxy%22%3Afalse%2C%22useDefaultPassthroughs%22%3Atrue%7D%2C%22exportApplicationGlobal%22%3Afalse%2C%22ember-load%22%3A%7B%22loadingIndicatorClass%22%3A%22ember-load-indicator%22%7D%7D" />
|
|
12
12
|
|
|
13
13
|
<meta name="HandheldFriendly" content="True" />
|
|
14
14
|
<meta name="MobileOptimized" content="320" />
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
</style>
|
|
38
38
|
|
|
39
39
|
<link integrity="" rel="stylesheet" href="assets/vendor-3e6947aa681f0fb82b193090e520dc73.css">
|
|
40
|
-
<link integrity="" rel="stylesheet" href="assets/ghost-
|
|
40
|
+
<link integrity="" rel="stylesheet" href="assets/ghost-7ecf5c7934d90798485ee5ac2956f7fe.css" title="light">
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
</head>
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
<div id="ember-basic-dropdown-wormhole"></div>
|
|
58
58
|
|
|
59
59
|
<script src="assets/vendor-c4684647d4f5213e5dbb6763de430e7e.js"></script>
|
|
60
|
-
<script src="assets/chunk.502.
|
|
61
|
-
<script src="assets/chunk.143.
|
|
62
|
-
<script src="assets/ghost-
|
|
60
|
+
<script src="assets/chunk.502.800e1515996bcc900013.js"></script>
|
|
61
|
+
<script src="assets/chunk.143.d5eaed4616c55cdbdabb.js"></script>
|
|
62
|
+
<script src="assets/ghost-b828e9e3c161aae92909c2e163656bb1.js"></script>
|
|
63
63
|
</body>
|
|
64
64
|
</html>
|
|
@@ -4,6 +4,7 @@ const errors = require('@tryghost/errors');
|
|
|
4
4
|
const megaService = require('../../services/mega');
|
|
5
5
|
const emailService = require('../../services/email-service');
|
|
6
6
|
const labs = require('../../../shared/labs');
|
|
7
|
+
const emailAnalytics = require('../../services/email-analytics');
|
|
7
8
|
|
|
8
9
|
const messages = {
|
|
9
10
|
emailNotFound: 'Email not found.',
|
|
@@ -140,5 +141,39 @@ module.exports = {
|
|
|
140
141
|
const filter = `email_id:'${frame.data.id}'` + (frame.options.filter ? `+(${frame.options.filter})` : '');
|
|
141
142
|
return await models.EmailRecipientFailure.findPage({...frame.options, filter});
|
|
142
143
|
}
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
analyticsStatus: {
|
|
147
|
+
permissions: {
|
|
148
|
+
method: 'browse'
|
|
149
|
+
},
|
|
150
|
+
async query() {
|
|
151
|
+
return emailAnalytics.service.getStatus();
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
scheduleAnalytics: {
|
|
156
|
+
permissions: {
|
|
157
|
+
method: 'browse'
|
|
158
|
+
},
|
|
159
|
+
data: [
|
|
160
|
+
'id'
|
|
161
|
+
],
|
|
162
|
+
async query(frame) {
|
|
163
|
+
const model = await models.Email.findOne(frame.data, frame.options);
|
|
164
|
+
return emailAnalytics.service.schedule({
|
|
165
|
+
begin: model.get('created_at'),
|
|
166
|
+
end: new Date(Math.min(Date.now() - 60 * 60 * 1000, model.get('created_at').getTime() + 24 * 60 * 60 * 1000 * 7))
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
cancelScheduledAnalytics: {
|
|
172
|
+
permissions: {
|
|
173
|
+
method: 'browse'
|
|
174
|
+
},
|
|
175
|
+
async query() {
|
|
176
|
+
return emailAnalytics.service.cancelScheduled();
|
|
177
|
+
}
|
|
143
178
|
}
|
|
144
179
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const tpl = require('@tryghost/tpl');
|
|
2
2
|
const errors = require('@tryghost/errors');
|
|
3
3
|
const models = require('../../models');
|
|
4
|
-
const postsPublicService = require('../../services/posts-public');
|
|
5
4
|
|
|
6
5
|
const ALLOWED_INCLUDES = ['tags', 'authors', 'tiers'];
|
|
7
6
|
|
|
@@ -36,7 +35,7 @@ module.exports = {
|
|
|
36
35
|
},
|
|
37
36
|
permissions: true,
|
|
38
37
|
query(frame) {
|
|
39
|
-
return
|
|
38
|
+
return models.Post.findPage(frame.options);
|
|
40
39
|
}
|
|
41
40
|
},
|
|
42
41
|
|
|
@@ -13,6 +13,7 @@ module.exports = {
|
|
|
13
13
|
docName: 'posts',
|
|
14
14
|
|
|
15
15
|
browse: {
|
|
16
|
+
cache: postsPublicService.api?.cache,
|
|
16
17
|
options: [
|
|
17
18
|
'include',
|
|
18
19
|
'filter',
|
|
@@ -36,7 +37,7 @@ module.exports = {
|
|
|
36
37
|
},
|
|
37
38
|
permissions: true,
|
|
38
39
|
query(frame) {
|
|
39
|
-
return
|
|
40
|
+
return models.Post.findPage(frame.options);
|
|
40
41
|
}
|
|
41
42
|
},
|
|
42
43
|
|
|
@@ -14,6 +14,7 @@ module.exports = {
|
|
|
14
14
|
docName: 'tags',
|
|
15
15
|
|
|
16
16
|
browse: {
|
|
17
|
+
cache: tagsPublicService.api?.cache,
|
|
17
18
|
options: [
|
|
18
19
|
'include',
|
|
19
20
|
'filter',
|
|
@@ -32,7 +33,7 @@ module.exports = {
|
|
|
32
33
|
},
|
|
33
34
|
permissions: true,
|
|
34
35
|
query(frame) {
|
|
35
|
-
return
|
|
36
|
+
return models.TagPublic.findPage(frame.options);
|
|
36
37
|
}
|
|
37
38
|
},
|
|
38
39
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
browse(_apiConfig, frame) {
|
|
3
|
+
// Force source:-~^'https://brid.gy/' to be added to the filter
|
|
4
|
+
const filterBridgy = `source:-~^'https://brid.gy/'`;
|
|
5
|
+
if (frame.options.filter) {
|
|
6
|
+
frame.options.filter = `${frame.options.filter}+${filterBridgy}`;
|
|
7
|
+
} else {
|
|
8
|
+
frame.options.filter = filterBridgy;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
@@ -23,11 +23,8 @@ const labs = require('../../../../../../../shared/labs');
|
|
|
23
23
|
|
|
24
24
|
module.exports = async (model, frame, options = {}) => {
|
|
25
25
|
const {tiers: tiersData} = options || {};
|
|
26
|
-
const extendedOptions = Object.assign(_.cloneDeep(frame.options), {
|
|
27
|
-
extraProperties: ['canonical_url']
|
|
28
|
-
});
|
|
29
26
|
|
|
30
|
-
const jsonModel = model.toJSON(
|
|
27
|
+
const jsonModel = model.toJSON(frame.options);
|
|
31
28
|
|
|
32
29
|
// Map email_recipient_filter to email_segment
|
|
33
30
|
jsonModel.email_segment = jsonModel.email_recipient_filter;
|
|
@@ -35,7 +32,7 @@ module.exports = async (model, frame, options = {}) => {
|
|
|
35
32
|
|
|
36
33
|
url.forPost(model.id, jsonModel, frame);
|
|
37
34
|
|
|
38
|
-
extraAttrs.forPost(frame, model, jsonModel);
|
|
35
|
+
extraAttrs.forPost(frame.options, model, jsonModel);
|
|
39
36
|
|
|
40
37
|
// Attach tiers to custom nql visibility filter
|
|
41
38
|
if (jsonModel.visibility) {
|
|
@@ -36,6 +36,7 @@ const author = (attrs, frame) => {
|
|
|
36
36
|
delete attrs.paid_subscription_started_notification;
|
|
37
37
|
delete attrs.paid_subscription_canceled_notification;
|
|
38
38
|
delete attrs.mention_notifications;
|
|
39
|
+
delete attrs.milestone_notifications;
|
|
39
40
|
|
|
40
41
|
// @NOTE: used for night shift
|
|
41
42
|
delete attrs.accessibility;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
const readingMinutes = require('@tryghost/helpers').utils.readingMinutes;
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @param {Object} options - frame options
|
|
6
|
+
* @param {import('../../../../../../models/post')} model - Bookshelf model of Post
|
|
7
|
+
* @param {Object} attrs - JSON object of Post
|
|
8
|
+
* @returns {void} - modifies attrs
|
|
9
|
+
*/
|
|
10
|
+
module.exports.forPost = (options, model, attrs) => {
|
|
4
11
|
const _ = require('lodash');
|
|
5
12
|
// This function is split up in 3 conditions for 3 different purposes:
|
|
6
13
|
// 1. Gets excerpt from post's plaintext. If custom_excerpt exists, it overrides the excerpt but the key remains excerpt.
|
|
7
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
8
|
-
if (_.includes(
|
|
14
|
+
if (Object.prototype.hasOwnProperty.call(options, 'columns') || _.includes(options.columns, 'excerpt') || _.includes(options.columns, 'excerpt') && options.formats && options.formats.includes('plaintext')) {
|
|
15
|
+
if (_.includes(options.columns, 'excerpt')) {
|
|
9
16
|
if (!attrs.custom_excerpt || attrs.custom_excerpt === null) {
|
|
10
17
|
let plaintext = model.get('plaintext');
|
|
11
18
|
if (plaintext) {
|
|
@@ -13,21 +20,22 @@ module.exports.forPost = (frame, model, attrs) => {
|
|
|
13
20
|
} else {
|
|
14
21
|
attrs.excerpt = null;
|
|
15
22
|
}
|
|
16
|
-
if (!
|
|
23
|
+
if (!options.columns.includes('custom_excerpt')) {
|
|
17
24
|
delete attrs.custom_excerpt;
|
|
18
25
|
}
|
|
19
26
|
} else {
|
|
20
27
|
attrs.excerpt = attrs.custom_excerpt;
|
|
21
|
-
if (!_.includes(
|
|
28
|
+
if (!_.includes(options.columns, 'custom_excerpt')) {
|
|
22
29
|
delete attrs.custom_excerpt;
|
|
23
30
|
}
|
|
24
31
|
}
|
|
25
32
|
}
|
|
26
33
|
}
|
|
34
|
+
|
|
27
35
|
// 2. Displays plaintext if requested by user as a field. Also works if used as format.
|
|
28
|
-
if (_.includes(
|
|
36
|
+
if (_.includes(options.columns, 'plaintext') || options.formats && options.formats.includes('plaintext')) {
|
|
29
37
|
let plaintext = model.get('plaintext');
|
|
30
|
-
if (plaintext){
|
|
38
|
+
if (plaintext) {
|
|
31
39
|
attrs.plaintext = plaintext;
|
|
32
40
|
} else {
|
|
33
41
|
delete attrs.plaintext;
|
|
@@ -36,11 +44,11 @@ module.exports.forPost = (frame, model, attrs) => {
|
|
|
36
44
|
|
|
37
45
|
// 3. Displays excerpt if no columns was requested - specifically needed for the Admin Posts API.
|
|
38
46
|
|
|
39
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
47
|
+
if (!Object.prototype.hasOwnProperty.call(options, 'columns')) {
|
|
40
48
|
let plaintext = model.get('plaintext');
|
|
41
49
|
let customExcerpt = model.get('custom_excerpt');
|
|
42
50
|
|
|
43
|
-
if (customExcerpt !== null){
|
|
51
|
+
if (customExcerpt !== null) {
|
|
44
52
|
attrs.excerpt = customExcerpt;
|
|
45
53
|
} else {
|
|
46
54
|
if (plaintext) {
|
|
@@ -53,8 +61,8 @@ module.exports.forPost = (frame, model, attrs) => {
|
|
|
53
61
|
|
|
54
62
|
// reading_time still only works when used along with formats=html.
|
|
55
63
|
|
|
56
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
57
|
-
(
|
|
64
|
+
if (!Object.prototype.hasOwnProperty.call(options, 'columns') ||
|
|
65
|
+
(options.columns.includes('reading_time'))) {
|
|
58
66
|
if (attrs.html) {
|
|
59
67
|
let additionalImages = 0;
|
|
60
68
|
|
|
@@ -46,7 +46,8 @@ const BACKUP_TABLES = [
|
|
|
46
46
|
'members_click_events',
|
|
47
47
|
'members_feedback',
|
|
48
48
|
'suppressions',
|
|
49
|
-
'email_spam_complaint_events'
|
|
49
|
+
'email_spam_complaint_events',
|
|
50
|
+
'milestones'
|
|
50
51
|
];
|
|
51
52
|
|
|
52
53
|
// NOTE: exposing only tables which are going to be included in a "default" export file
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const {addTable} = require('../../utils');
|
|
2
|
+
|
|
3
|
+
module.exports = addTable('milestones', {
|
|
4
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
5
|
+
type: {type: 'string', maxlength: 24, nullable: false},
|
|
6
|
+
value: {type: 'integer', nullable: false},
|
|
7
|
+
currency: {type: 'string', maxlength: 24, nullable: true},
|
|
8
|
+
created_at: {type: 'dateTime', nullable: false},
|
|
9
|
+
email_sent_at: {type: 'dateTime', nullable: true}
|
|
10
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const logging = require('@tryghost/logging');
|
|
2
|
+
const {createTransactionalMigration} = require('../../utils');
|
|
3
|
+
|
|
4
|
+
// Set outbound_link_tagging to the current value of members_track_sources
|
|
5
|
+
module.exports = createTransactionalMigration(
|
|
6
|
+
async function up(connection) {
|
|
7
|
+
const reuseValueOfSetting = await connection('settings')
|
|
8
|
+
.where('key', '=', 'members_track_sources')
|
|
9
|
+
.first();
|
|
10
|
+
|
|
11
|
+
if (!reuseValueOfSetting) {
|
|
12
|
+
logging.warn(`Skipped setting outbound_link_tagging to current value of members_track_sources - members_track_sources not found`);
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const affectedRows = await connection('settings')
|
|
17
|
+
.update({
|
|
18
|
+
value: reuseValueOfSetting.value
|
|
19
|
+
})
|
|
20
|
+
.where('key', '=', 'outbound_link_tagging');
|
|
21
|
+
|
|
22
|
+
if (affectedRows === 1) {
|
|
23
|
+
logging.info(`Set outbound_link_tagging to ${reuseValueOfSetting.value} (current members_track_sources value)`);
|
|
24
|
+
} else {
|
|
25
|
+
logging.warn(`Tried setting outbound_link_tagging to ${reuseValueOfSetting.value} — ${affectedRows} changes`);
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
async function down() {
|
|
29
|
+
// no-op: we don't need to change it back
|
|
30
|
+
}
|
|
31
|
+
);
|
|
@@ -155,6 +155,7 @@ module.exports = {
|
|
|
155
155
|
paid_subscription_started_notification: {type: 'boolean', nullable: false, defaultTo: true},
|
|
156
156
|
paid_subscription_canceled_notification: {type: 'boolean', nullable: false, defaultTo: false},
|
|
157
157
|
mention_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
158
|
+
milestone_notifications: {type: 'boolean', nullable: false, defaultTo: true},
|
|
158
159
|
created_at: {type: 'dateTime', nullable: false},
|
|
159
160
|
created_by: {type: 'string', maxlength: 24, nullable: false},
|
|
160
161
|
updated_at: {type: 'dateTime', nullable: true},
|
|
@@ -997,5 +998,13 @@ module.exports = {
|
|
|
997
998
|
payload: {type: 'text', maxlength: 65535, nullable: true},
|
|
998
999
|
deleted: {type: 'boolean', nullable: false, defaultTo: false},
|
|
999
1000
|
verified: {type: 'boolean', nullable: false, defaultTo: false}
|
|
1001
|
+
},
|
|
1002
|
+
milestones: {
|
|
1003
|
+
id: {type: 'string', maxlength: 24, nullable: false, primary: true},
|
|
1004
|
+
type: {type: 'string', maxlength: 24, nullable: false},
|
|
1005
|
+
value: {type: 'integer', nullable: false},
|
|
1006
|
+
currency: {type: 'string', maxlength: 24, nullable: true},
|
|
1007
|
+
created_at: {type: 'dateTime', nullable: false},
|
|
1008
|
+
email_sent_at: {type: 'dateTime', nullable: true}
|
|
1000
1009
|
}
|
|
1001
1010
|
};
|
|
@@ -20,22 +20,32 @@ function isPrivateIp(addr) {
|
|
|
20
20
|
async function errorIfHostnameResolvesToPrivateIp(options) {
|
|
21
21
|
// allow requests through to local Ghost instance
|
|
22
22
|
const siteUrl = new URL(config.get('url'));
|
|
23
|
-
const requestUrl = new URL(options.href);
|
|
23
|
+
const requestUrl = new URL(options.url.href);
|
|
24
24
|
if (requestUrl.host === siteUrl.host) {
|
|
25
25
|
return Promise.resolve();
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
const result = await dnsPromises.lookup(options.hostname);
|
|
28
|
+
const result = await dnsPromises.lookup(options.url.hostname);
|
|
29
29
|
|
|
30
30
|
if (isPrivateIp(result.address)) {
|
|
31
31
|
return Promise.reject(new errors.InternalServerError({
|
|
32
32
|
message: 'URL resolves to a non-permitted private IP block',
|
|
33
33
|
code: 'URL_PRIVATE_INVALID',
|
|
34
|
-
context: options.href
|
|
34
|
+
context: options.url.href
|
|
35
35
|
}));
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
async function errorIfInvalidUrl(options) {
|
|
40
|
+
if (!options.url.hostname || !validator.isURL(options.url.hostname)) {
|
|
41
|
+
throw new errors.InternalServerError({
|
|
42
|
+
message: 'URL invalid.',
|
|
43
|
+
code: 'URL_MISSING_INVALID',
|
|
44
|
+
context: options.url.href
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
39
49
|
// same as our normal request lib but if any request in a redirect chain resolves
|
|
40
50
|
// to a private IP address it will be blocked before the request is made.
|
|
41
51
|
const externalRequest = got.extend({
|
|
@@ -44,16 +54,7 @@ const externalRequest = got.extend({
|
|
|
44
54
|
},
|
|
45
55
|
timeout: 10000, // default is no timeout
|
|
46
56
|
hooks: {
|
|
47
|
-
|
|
48
|
-
if (!options.hostname || !validator.isURL(options.hostname)) {
|
|
49
|
-
throw new errors.InternalServerError({
|
|
50
|
-
message: 'URL empty or invalid.',
|
|
51
|
-
code: 'URL_MISSING_INVALID',
|
|
52
|
-
context: options.href
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}],
|
|
56
|
-
beforeRequest: [errorIfHostnameResolvesToPrivateIp],
|
|
57
|
+
beforeRequest: [errorIfInvalidUrl,errorIfHostnameResolvesToPrivateIp],
|
|
57
58
|
beforeRedirect: [errorIfHostnameResolvesToPrivateIp]
|
|
58
59
|
}
|
|
59
60
|
});
|
|
@@ -69,7 +69,8 @@ User = ghostBookshelf.Model.extend({
|
|
|
69
69
|
free_member_signup_notification: true,
|
|
70
70
|
paid_subscription_started_notification: true,
|
|
71
71
|
paid_subscription_canceled_notification: false,
|
|
72
|
-
mention_notifications: true
|
|
72
|
+
mention_notifications: true,
|
|
73
|
+
milestone_notifications: true
|
|
73
74
|
};
|
|
74
75
|
},
|
|
75
76
|
|
|
@@ -507,6 +508,8 @@ User = ghostBookshelf.Model.extend({
|
|
|
507
508
|
filter += '+paid_subscription_canceled_notification:true';
|
|
508
509
|
} else if (type === 'mention-received') {
|
|
509
510
|
filter += '+mention_notifications:true';
|
|
511
|
+
} else if (type === 'milestone-received') {
|
|
512
|
+
filter += '+milestone_notifications:true';
|
|
510
513
|
}
|
|
511
514
|
const updatedOptions = _.merge({}, options, {filter, withRelated: ['roles']});
|
|
512
515
|
return this.findAll(updatedOptions).then((users) => {
|