ghost 4.22.1 → 4.23.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/.c8rc.json +24 -0
- package/.eslintrc.js +6 -0
- package/Gruntfile.js +1 -1
- package/content/public/README.md +3 -0
- package/core/boot.js +20 -12
- package/core/built/assets/{chunk.3.1148677ff3b78e5aeaee.js → chunk.3.8f95b516d88ff4eec64c.js} +18 -18
- package/core/built/assets/{ghost-dark-684ad238e1a858c7cb5be6988de7c6f5.css → ghost-dark-42cf6e0c730578940ec069bda45aea41.css} +1 -1
- package/core/built/assets/{ghost.min-f7037eca328f4d4eb99f0309c19c9bae.js → ghost.min-cccc107e881b74c7aaf1a73e1e5e0dee.js} +189 -143
- package/core/built/assets/{ghost.min-66e08535f8bb797a8c40e0a2b31f1e9e.css → ghost.min-fcf6a0738421f86c47c55f20d00c5ba9.css} +1 -1
- package/core/built/assets/icons/powered-by-tenor.svg +35 -0
- package/core/built/assets/icons/tenor.svg +7 -0
- package/core/built/assets/{vendor.min-7c8fdd90f7ecd2e94328a07ea3b64608.js → vendor.min-c9002845b6c30ac978abdadde9f33d7c.js} +8189 -7601
- package/core/frontend/apps/amp/lib/views/amp.hbs +104 -0
- package/core/frontend/apps/private-blogging/lib/router.js +1 -1
- package/core/frontend/services/card-assets/service.js +21 -13
- package/core/frontend/services/routing/CollectionRouter.js +4 -5
- package/core/frontend/services/routing/EmailRouter.js +1 -1
- package/core/frontend/services/routing/ParentRouter.js +0 -8
- package/core/frontend/services/routing/PreviewRouter.js +1 -1
- package/core/frontend/services/routing/StaticPagesRouter.js +1 -1
- package/core/frontend/services/routing/StaticRoutesRouter.js +4 -4
- package/core/frontend/services/routing/TaxonomyRouter.js +3 -3
- package/core/frontend/services/routing/{middlewares → middleware}/index.js +0 -0
- package/core/frontend/services/routing/{middlewares → middleware}/page-param.js +0 -0
- package/core/frontend/services/routing/router-manager.js +7 -2
- package/core/frontend/services/rss/generate-feed.js +2 -1
- package/core/frontend/src/cards/css/bookmark.css +66 -48
- package/core/frontend/src/cards/css/button.css +30 -0
- package/core/frontend/src/cards/css/callout.css +50 -0
- package/core/frontend/src/cards/css/gallery.css +8 -13
- package/core/frontend/src/cards/css/nft.css +94 -0
- package/core/frontend/src/cards/css/toggle.css +47 -0
- package/core/frontend/src/cards/js/toggle.js +16 -0
- package/core/frontend/web/middleware/serve-public-file.js +14 -8
- package/core/frontend/web/routes.js +0 -1
- package/core/frontend/web/site.js +15 -12
- package/core/server/adapters/storage/LocalFilesStorage.js +17 -0
- package/core/server/adapters/storage/LocalImagesStorage.js +1 -0
- package/core/server/adapters/storage/LocalMediaStorage.js +2 -1
- package/core/server/adapters/storage/LocalStorageBase.js +30 -5
- package/core/server/api/canary/authentication.js +1 -1
- package/core/server/api/canary/files.js +19 -0
- package/core/server/api/canary/index.js +4 -0
- package/core/server/api/canary/media.js +25 -5
- package/core/server/api/canary/oembed.js +3 -0
- package/core/server/api/canary/utils/serializers/input/index.js +4 -0
- package/core/server/api/canary/utils/serializers/input/media.js +8 -0
- package/core/server/api/canary/utils/serializers/output/config.js +21 -14
- package/core/server/api/canary/utils/serializers/output/files.js +27 -0
- package/core/server/api/canary/utils/serializers/output/index.js +4 -0
- package/core/server/api/canary/utils/serializers/output/media.js +9 -0
- package/core/server/api/canary/utils/validators/input/files.js +7 -0
- package/core/server/api/canary/utils/validators/input/index.js +4 -0
- package/core/server/api/canary/utils/validators/input/media.js +4 -0
- package/core/server/api/v2/authentication.js +1 -1
- package/core/server/api/v3/authentication.js +1 -1
- package/core/server/data/db/connection.js +7 -0
- package/core/server/data/importer/importers/data/data-importer.js +3 -3
- package/core/server/data/migrations/init/2-create-fixtures.js +3 -20
- package/core/server/data/migrations/versions/1.21/1-add-contributor-role.js +5 -5
- package/core/server/data/migrations/versions/2.15/2-insert-zapier-integration.js +3 -3
- package/core/server/data/migrations/versions/2.2/3-insert-admin-integration-role.js +5 -5
- package/core/server/data/migrations/versions/2.27/1-insert-ghost-db-backup-role.js +5 -6
- package/core/server/data/migrations/versions/2.27/2-insert-db-backup-integration.js +3 -4
- package/core/server/data/migrations/versions/2.28/3-insert-ghost-scheduler-role.js +7 -7
- package/core/server/data/migrations/versions/2.28/4-insert-scheduler-integration.js +3 -3
- package/core/server/data/migrations/versions/4.23/01-truncate-offer-names.js +58 -0
- package/core/server/data/schema/fixtures/fixture-manager.js +340 -0
- package/core/server/data/schema/fixtures/index.js +8 -2
- package/core/server/services/mega/post-email-serializer.js +5 -1
- package/core/server/services/mega/segment-parser.js +1 -2
- package/core/server/services/mega/template.js +69 -1
- package/core/server/services/nft-oembed.js +57 -0
- package/core/server/services/oembed.js +161 -126
- package/core/server/services/public-config/config.js +2 -1
- package/core/server/services/stripe/index.js +4 -2
- package/core/server/services/url/Resource.js +1 -1
- package/core/server/services/url/Resources.js +36 -23
- package/core/server/services/url/UrlGenerator.js +23 -20
- package/core/server/services/url/UrlService.js +123 -21
- package/core/server/services/url/Urls.js +7 -2
- package/core/server/services/url/index.js +9 -1
- package/core/server/web/admin/app.js +6 -6
- package/core/server/web/admin/views/default-prod.html +4 -4
- package/core/server/web/admin/views/default.html +4 -4
- package/core/server/web/api/app.js +1 -1
- package/core/server/web/api/canary/admin/app.js +4 -4
- package/core/server/web/api/canary/admin/middleware.js +6 -6
- package/core/server/web/api/canary/admin/routes.js +20 -5
- package/core/server/web/api/canary/content/app.js +4 -4
- package/core/server/web/api/canary/content/middleware.js +3 -3
- package/core/server/web/api/middleware/cors.js +7 -7
- package/core/server/web/api/v2/admin/app.js +4 -4
- package/core/server/web/api/v2/admin/middleware.js +6 -6
- package/core/server/web/api/v2/admin/routes.js +5 -5
- package/core/server/web/api/v2/content/app.js +4 -4
- package/core/server/web/api/v2/content/middleware.js +3 -3
- package/core/server/web/api/v3/admin/app.js +4 -4
- package/core/server/web/api/v3/admin/middleware.js +6 -6
- package/core/server/web/api/v3/admin/routes.js +5 -5
- package/core/server/web/api/v3/content/app.js +4 -4
- package/core/server/web/api/v3/content/middleware.js +3 -3
- package/core/server/web/members/app.js +7 -7
- package/core/server/web/oauth/app.js +1 -1
- package/core/server/web/parent/app.js +2 -3
- package/core/server/web/parent/frontend.js +1 -1
- package/core/server/web/shared/index.js +2 -2
- package/core/server/web/shared/{middlewares → middleware}/api/index.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/api/spam-prevention.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/brute.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/cache-control.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/error-handler.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/index.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/maintenance.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/pretty-urls.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/uncapitalise.js +0 -0
- package/core/server/web/shared/{middlewares → middleware}/url-redirects.js +0 -0
- package/core/shared/config/defaults.json +10 -2
- package/core/shared/config/helpers.js +44 -0
- package/core/shared/config/loader.js +1 -1
- package/core/shared/config/overrides.json +2 -2
- package/core/shared/labs.js +8 -1
- package/loggingrc.js +19 -20
- package/package.json +35 -35
- package/urls.json +597 -0
- package/yarn.lock +655 -339
- package/core/server/data/schema/fixtures/utils.js +0 -321
- package/core/server/web/parent/vhost-utils.js +0 -39
|
@@ -457,6 +457,110 @@
|
|
|
457
457
|
margin: 0 .5em;
|
|
458
458
|
}
|
|
459
459
|
|
|
460
|
+
.kg-nft-card-container {
|
|
461
|
+
position: relative;
|
|
462
|
+
display: flex;
|
|
463
|
+
flex: auto;
|
|
464
|
+
flex-direction: column;
|
|
465
|
+
text-decoration: none;
|
|
466
|
+
font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;
|
|
467
|
+
font-size: 1.4rem;
|
|
468
|
+
font-weight: 400;
|
|
469
|
+
box-shadow: 0 2px 6px -2px rgb(0 0 0 / 10%), 0 0 1px rgb(0 0 0 / 40%);
|
|
470
|
+
width: 100%;
|
|
471
|
+
max-width: 512px;
|
|
472
|
+
color: #15212A;
|
|
473
|
+
background: #fff;
|
|
474
|
+
border-radius: 5px;
|
|
475
|
+
transition: none;
|
|
476
|
+
margin: 0 auto;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
.kg-nft-metadata {
|
|
480
|
+
padding: 2.0rem;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.kg-nft-image-container {
|
|
484
|
+
position: relative;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.kg-nft-image {
|
|
488
|
+
display: flex;
|
|
489
|
+
border-radius: 5px 5px 0 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.kg-nft-header {
|
|
493
|
+
display: flex;
|
|
494
|
+
justify-content: space-between;
|
|
495
|
+
align-items: flex-start;
|
|
496
|
+
gap: 20px;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
.kg-nft-header h4.kg-nft-title {
|
|
500
|
+
font-size: 1.9rem;
|
|
501
|
+
font-weight: 700;
|
|
502
|
+
margin: 0;
|
|
503
|
+
color: #15212A;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.kg-nft-header amp-img {
|
|
507
|
+
max-width: 114px;
|
|
508
|
+
max-height: 26px;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
.kg-nft-opensea-logo {
|
|
512
|
+
margin-top: 2px;
|
|
513
|
+
width: 100px;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.kg-nft-creator {
|
|
517
|
+
font-family: inherit;
|
|
518
|
+
color: #95A1AD;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.kg-nft-creator span {
|
|
522
|
+
font-weight: 500;
|
|
523
|
+
color: #15212A;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.kg-nft-card p.kg-nft-description {
|
|
527
|
+
font-size: 1.4rem;
|
|
528
|
+
line-height: 1.4em;
|
|
529
|
+
margin: 2.0rem 0 0;
|
|
530
|
+
color: #222;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
.kg-button-card {
|
|
534
|
+
display: flex;
|
|
535
|
+
position: static;
|
|
536
|
+
align-items: center;
|
|
537
|
+
width: 100%;
|
|
538
|
+
justify-content: center;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
.kg-btn {
|
|
542
|
+
display: flex;
|
|
543
|
+
position: static;
|
|
544
|
+
align-items: center;
|
|
545
|
+
padding: 0 2.0rem;
|
|
546
|
+
height: 4.0rem;
|
|
547
|
+
line-height: 4.0rem;
|
|
548
|
+
font-size: 1.65rem;
|
|
549
|
+
font-weight: 600;
|
|
550
|
+
text-decoration: none;
|
|
551
|
+
border-radius: 5px;
|
|
552
|
+
transition: opacity 0.2s ease-in-out;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.kg-btn:hover {
|
|
556
|
+
opacity: 0.85;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.kg-btn-accent {
|
|
560
|
+
background-color: var(--ghost-accent-color, #1292EE);
|
|
561
|
+
color: #fff;
|
|
562
|
+
}
|
|
563
|
+
|
|
460
564
|
.kg-width-full.kg-card-hascaption {
|
|
461
565
|
display: grid;
|
|
462
566
|
grid-template-columns: inherit;
|
|
@@ -2,12 +2,13 @@ const Minifier = require('@tryghost/minifier');
|
|
|
2
2
|
const _ = require('lodash');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const fs = require('fs').promises;
|
|
5
|
+
const logging = require('@tryghost/logging');
|
|
6
|
+
const config = require('../../../shared/config');
|
|
5
7
|
|
|
6
8
|
class CardAssetService {
|
|
7
9
|
constructor(options = {}) {
|
|
8
|
-
|
|
9
|
-
this.
|
|
10
|
-
this.dest = options.dest || path.join(__dirname, '../../public');
|
|
10
|
+
this.src = options.src || path.join(config.get('paths').assetSrc, 'cards');
|
|
11
|
+
this.dest = options.dest || config.getContentPath('public');
|
|
11
12
|
this.minifier = new Minifier({src: this.src, dest: this.dest});
|
|
12
13
|
|
|
13
14
|
if ('config' in options) {
|
|
@@ -49,7 +50,14 @@ class CardAssetService {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
async minify(globs) {
|
|
52
|
-
|
|
53
|
+
try {
|
|
54
|
+
return await this.minifier.minify(globs);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
// @TODO: Convert this back to a proper error once the underlying bug is fixed
|
|
57
|
+
if (err.code === 'EACCES') {
|
|
58
|
+
logging.warn('Ghost was not able to write card asset files due to permissions.');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
async clearFiles() {
|
|
@@ -59,8 +67,8 @@ class CardAssetService {
|
|
|
59
67
|
try {
|
|
60
68
|
await fs.unlink(path.join(this.dest, 'cards.min.css'));
|
|
61
69
|
} catch (error) {
|
|
62
|
-
// Don't worry if the file didn't exist
|
|
63
|
-
if (error.code !== 'ENOENT') {
|
|
70
|
+
// Don't worry if the file didn't exist or we don't have perms here
|
|
71
|
+
if (error.code !== 'ENOENT' && error.code !== 'EACCES') {
|
|
64
72
|
throw error;
|
|
65
73
|
}
|
|
66
74
|
}
|
|
@@ -68,8 +76,8 @@ class CardAssetService {
|
|
|
68
76
|
try {
|
|
69
77
|
await fs.unlink(path.join(this.dest, 'cards.min.js'));
|
|
70
78
|
} catch (error) {
|
|
71
|
-
// Don't worry if the file didn't exist
|
|
72
|
-
if (error.code !== 'ENOENT') {
|
|
79
|
+
// Don't worry if the file didn't exist or we don't have perms here
|
|
80
|
+
if (error.code !== 'ENOENT' && error.code !== 'EACCES') {
|
|
73
81
|
throw error;
|
|
74
82
|
}
|
|
75
83
|
}
|
|
@@ -82,19 +90,19 @@ class CardAssetService {
|
|
|
82
90
|
/**
|
|
83
91
|
* A theme can declare which cards it supports, and we'll do the rest
|
|
84
92
|
*
|
|
85
|
-
* @param {Array|boolean}
|
|
93
|
+
* @param {Array|boolean} cardAssetConfig
|
|
86
94
|
* @returns
|
|
87
95
|
*/
|
|
88
|
-
async load(
|
|
89
|
-
if (
|
|
90
|
-
this.config =
|
|
96
|
+
async load(cardAssetConfig) {
|
|
97
|
+
if (cardAssetConfig) {
|
|
98
|
+
this.config = cardAssetConfig;
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
await this.clearFiles();
|
|
94
102
|
|
|
95
103
|
const globs = this.generateGlobs();
|
|
96
104
|
|
|
97
|
-
this.files = await this.minify(globs);
|
|
105
|
+
this.files = await this.minify(globs) || [];
|
|
98
106
|
}
|
|
99
107
|
}
|
|
100
108
|
|
|
@@ -3,7 +3,7 @@ const urlUtils = require('../../../shared/url-utils');
|
|
|
3
3
|
const ParentRouter = require('./ParentRouter');
|
|
4
4
|
|
|
5
5
|
const controllers = require('./controllers');
|
|
6
|
-
const
|
|
6
|
+
const middleware = require('./middleware');
|
|
7
7
|
const RSSRouter = require('./RSSRouter');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -27,7 +27,6 @@ class CollectionRouter extends ParentRouter {
|
|
|
27
27
|
this.rss = object.rss !== false;
|
|
28
28
|
|
|
29
29
|
this.permalinks = {
|
|
30
|
-
originalValue: object.permalink,
|
|
31
30
|
value: object.permalink
|
|
32
31
|
};
|
|
33
32
|
|
|
@@ -71,7 +70,7 @@ class CollectionRouter extends ParentRouter {
|
|
|
71
70
|
this.mountRoute(this.route.value, controllers.collection);
|
|
72
71
|
|
|
73
72
|
// REGISTER: enable pagination by default
|
|
74
|
-
this.router().param('page',
|
|
73
|
+
this.router().param('page', middleware.pageParam);
|
|
75
74
|
this.mountRoute(urlUtils.urlJoin(this.route.value, 'page', ':page(\\d+)'), controllers.collection);
|
|
76
75
|
|
|
77
76
|
// REGISTER: is rss enabled?
|
|
@@ -93,7 +92,7 @@ class CollectionRouter extends ParentRouter {
|
|
|
93
92
|
}
|
|
94
93
|
|
|
95
94
|
/**
|
|
96
|
-
* @description Prepare index context for further
|
|
95
|
+
* @description Prepare index context for further middleware/controllers.
|
|
97
96
|
*/
|
|
98
97
|
_prepareEntriesContext(req, res, next) {
|
|
99
98
|
res.routerOptions = {
|
|
@@ -116,7 +115,7 @@ class CollectionRouter extends ParentRouter {
|
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
/**
|
|
119
|
-
* @description Prepare entry context for further
|
|
118
|
+
* @description Prepare entry context for further middleware/controllers.
|
|
120
119
|
*/
|
|
121
120
|
_prepareEntryContext(req, res, next) {
|
|
122
121
|
res.routerOptions.context = ['post'];
|
|
@@ -30,7 +30,7 @@ class EmailRouter extends ParentRouter {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* @description Prepare context for further
|
|
33
|
+
* @description Prepare context for further middleware/controllers.
|
|
34
34
|
* @param {Object} req
|
|
35
35
|
* @param {Object} res
|
|
36
36
|
* @param {Function} next
|
|
@@ -180,14 +180,6 @@ class ParentRouter {
|
|
|
180
180
|
return this.permalinks;
|
|
181
181
|
}
|
|
182
182
|
|
|
183
|
-
/**
|
|
184
|
-
* @description Get configured filter of this router.
|
|
185
|
-
* @returns {String}
|
|
186
|
-
*/
|
|
187
|
-
getFilter() {
|
|
188
|
-
return this.filter;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
183
|
/**
|
|
192
184
|
* @description Get main route of this router.
|
|
193
185
|
*
|
|
@@ -30,7 +30,7 @@ class PreviewRouter extends ParentRouter {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* @description Prepare context for further
|
|
33
|
+
* @description Prepare context for further middleware/controllers.
|
|
34
34
|
* @param {Object} req
|
|
35
35
|
* @param {Object} res
|
|
36
36
|
* @param {Function} next
|
|
@@ -52,7 +52,7 @@ class StaticPagesRouter extends ParentRouter {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
/**
|
|
55
|
-
* @description Prepare context for futher
|
|
55
|
+
* @description Prepare context for futher middleware/controllers.
|
|
56
56
|
* @param {Object} req
|
|
57
57
|
* @param {Object} res
|
|
58
58
|
* @param {Function} next
|
|
@@ -3,7 +3,7 @@ const errors = require('@tryghost/errors');
|
|
|
3
3
|
const urlUtils = require('../../../shared/url-utils');
|
|
4
4
|
const RSSRouter = require('./RSSRouter');
|
|
5
5
|
const controllers = require('./controllers');
|
|
6
|
-
const
|
|
6
|
+
const middleware = require('./middleware');
|
|
7
7
|
const ParentRouter = require('./ParentRouter');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -59,14 +59,14 @@ class StaticRoutesRouter extends ParentRouter {
|
|
|
59
59
|
this.mountRoute(this.route.value, controllers[this.controller]);
|
|
60
60
|
|
|
61
61
|
// REGISTER: pagination
|
|
62
|
-
this.router().param('page',
|
|
62
|
+
this.router().param('page', middleware.pageParam);
|
|
63
63
|
this.mountRoute(urlUtils.urlJoin(this.route.value, 'page', ':page(\\d+)'), controllers[this.controller]);
|
|
64
64
|
|
|
65
65
|
this.routerCreated(this);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
|
-
* @description Prepare channel context for further
|
|
69
|
+
* @description Prepare channel context for further middleware/controllers.
|
|
70
70
|
* @param {Object} req
|
|
71
71
|
* @param {Object} res
|
|
72
72
|
* @param {Function} next
|
|
@@ -102,7 +102,7 @@ class StaticRoutesRouter extends ParentRouter {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* @description Prepare static route context for further
|
|
105
|
+
* @description Prepare static route context for further middleware/controllers.
|
|
106
106
|
* @param {Object} req
|
|
107
107
|
* @param {Object} res
|
|
108
108
|
* @param {Function} next
|
|
@@ -4,7 +4,7 @@ const ParentRouter = require('./ParentRouter');
|
|
|
4
4
|
const RSSRouter = require('./RSSRouter');
|
|
5
5
|
const urlUtils = require('../../../shared/url-utils');
|
|
6
6
|
const controllers = require('./controllers');
|
|
7
|
-
const
|
|
7
|
+
const middleware = require('./middleware');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @description Taxonomies are groupings of posts based on a common relation.
|
|
@@ -51,7 +51,7 @@ class TaxonomyRouter extends ParentRouter {
|
|
|
51
51
|
this.mountRoute(this.permalinks.getValue(), controllers.channel);
|
|
52
52
|
|
|
53
53
|
// REGISTER: enable pagination for each taxonomy by default
|
|
54
|
-
this.router().param('page',
|
|
54
|
+
this.router().param('page', middleware.pageParam);
|
|
55
55
|
this.mountRoute(urlUtils.urlJoin(this.permalinks.value, 'page', ':page(\\d+)'), controllers.channel);
|
|
56
56
|
|
|
57
57
|
// REGISTER: edit redirect to admin client e.g. /tag/:slug/edit
|
|
@@ -63,7 +63,7 @@ class TaxonomyRouter extends ParentRouter {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
|
-
* @description Prepare context for routing
|
|
66
|
+
* @description Prepare context for routing middleware/controllers.
|
|
67
67
|
* @param {Object} req
|
|
68
68
|
* @param {Object} res
|
|
69
69
|
* @param {Function} next
|
|
File without changes
|
|
File without changes
|
|
@@ -43,7 +43,12 @@ class RouterManager {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
this.urlService.onRouterAddedType(
|
|
46
|
+
this.urlService.onRouterAddedType(
|
|
47
|
+
router.identifier,
|
|
48
|
+
router.filter,
|
|
49
|
+
router.getResourceType(),
|
|
50
|
+
router.getPermalinks().getValue()
|
|
51
|
+
);
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
/**
|
|
@@ -179,7 +184,7 @@ class RouterManager {
|
|
|
179
184
|
if (collectionRouter.getPermalinks().getValue().match(/:year|:month|:day/)) {
|
|
180
185
|
debug('handleTimezoneEdit: trigger regeneration');
|
|
181
186
|
|
|
182
|
-
this.urlService.onRouterUpdated(collectionRouter);
|
|
187
|
+
this.urlService.onRouterUpdated(collectionRouter.identifier);
|
|
183
188
|
}
|
|
184
189
|
}
|
|
185
190
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
const downsize = require('downsize');
|
|
2
2
|
const Promise = require('bluebird');
|
|
3
|
-
const cheerio = require('cheerio');
|
|
4
3
|
const RSS = require('rss');
|
|
5
4
|
const urlUtils = require('../../../shared/url-utils');
|
|
6
5
|
const {routerManager} = require('../routing');
|
|
@@ -19,6 +18,8 @@ const generateTags = function generateTags(data) {
|
|
|
19
18
|
};
|
|
20
19
|
|
|
21
20
|
const generateItem = function generateItem(post, secure) {
|
|
21
|
+
const cheerio = require('cheerio');
|
|
22
|
+
|
|
22
23
|
const itemUrl = routerManager.getUrlByResourceId(post.id, {secure, absolute: true});
|
|
23
24
|
const htmlContent = cheerio.load(post.html || '');
|
|
24
25
|
const item = {
|
|
@@ -1,83 +1,101 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
.kg-bookmark-card {
|
|
4
|
-
width: 100%;
|
|
1
|
+
.kg-bookmark-card,
|
|
2
|
+
.kg-bookmark-publisher {
|
|
5
3
|
position: relative;
|
|
4
|
+
width: 100%;
|
|
6
5
|
}
|
|
7
6
|
|
|
8
|
-
.kg-bookmark-container
|
|
9
|
-
display: flex;
|
|
10
|
-
flex-wrap: wrap;
|
|
11
|
-
flex-direction: row-reverse;
|
|
12
|
-
color: currentColor;
|
|
13
|
-
font-family: inherit;
|
|
14
|
-
text-decoration: none;
|
|
15
|
-
border: 1px solid rgba(0, 0, 0, 0.1);
|
|
16
|
-
}
|
|
17
|
-
|
|
7
|
+
.kg-bookmark-container,
|
|
18
8
|
.kg-bookmark-container:hover {
|
|
9
|
+
display: flex;
|
|
19
10
|
text-decoration: none;
|
|
11
|
+
border-radius: 4px;
|
|
12
|
+
box-shadow: inset 0 0 0 1px rgb(124 139 154 / 25%);
|
|
13
|
+
overflow: hidden;
|
|
20
14
|
}
|
|
21
15
|
|
|
22
16
|
.kg-bookmark-content {
|
|
23
|
-
|
|
24
|
-
flex-
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
flex-grow: 1;
|
|
20
|
+
flex-basis: 100%;
|
|
21
|
+
align-items: flex-start;
|
|
22
|
+
justify-content: flex-start;
|
|
25
23
|
padding: 20px;
|
|
26
|
-
order: 1;
|
|
27
24
|
}
|
|
28
25
|
|
|
29
26
|
.kg-bookmark-title {
|
|
27
|
+
font-size: 1.5rem;
|
|
28
|
+
line-height: 1.4em;
|
|
30
29
|
font-weight: 600;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
.kg-bookmark-metadata,
|
|
34
32
|
.kg-bookmark-description {
|
|
35
|
-
|
|
33
|
+
display: -webkit-box;
|
|
34
|
+
font-size: 1.4rem;
|
|
35
|
+
line-height: 1.5em;
|
|
36
|
+
margin-top: 3px;
|
|
37
|
+
font-weight: 400;
|
|
38
|
+
max-height: 44px;
|
|
39
|
+
overflow-y: hidden;
|
|
40
|
+
opacity: 0.7;
|
|
41
|
+
-webkit-line-clamp: 2;
|
|
42
|
+
-webkit-box-orient: vertical;
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
.kg-bookmark-metadata {
|
|
46
|
+
display: flex;
|
|
39
47
|
align-items: center;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
margin-top: 22px;
|
|
49
|
+
width: 100%;
|
|
50
|
+
font-size: 1.4rem;
|
|
51
|
+
font-weight: 500;
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
.kg-bookmark-
|
|
46
|
-
|
|
47
|
-
-webkit-box-orient: vertical;
|
|
48
|
-
-webkit-line-clamp: 2;
|
|
49
|
-
overflow: hidden;
|
|
54
|
+
.kg-bookmark-metadata > *:not(img) {
|
|
55
|
+
opacity: 0.7;
|
|
50
56
|
}
|
|
51
57
|
|
|
52
58
|
.kg-bookmark-icon {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
vertical-align: text-bottom;
|
|
57
|
-
margin-right: .5em;
|
|
58
|
-
margin-bottom: .05em;
|
|
59
|
+
width: 20px;
|
|
60
|
+
height: 20px;
|
|
61
|
+
margin-right: 6px;
|
|
59
62
|
}
|
|
60
63
|
|
|
61
|
-
.kg-bookmark-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
flex-grow: 1;
|
|
64
|
+
.kg-bookmark-author,
|
|
65
|
+
.kg-bookmark-publisher {
|
|
66
|
+
display: inline;
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
.kg-bookmark-
|
|
68
|
-
max-width: 100%;
|
|
69
|
-
height: auto;
|
|
70
|
-
vertical-align: bottom;
|
|
71
|
-
object-fit: cover;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.kg-bookmark-author {
|
|
75
|
-
white-space: nowrap;
|
|
69
|
+
.kg-bookmark-publisher {
|
|
76
70
|
text-overflow: ellipsis;
|
|
77
71
|
overflow: hidden;
|
|
72
|
+
max-width: 240px;
|
|
73
|
+
white-space: nowrap;
|
|
74
|
+
display: block;
|
|
75
|
+
line-height: 1.65em;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.kg-bookmark-metadata > span:nth-of-type(2) {
|
|
79
|
+
font-weight: 400;
|
|
78
80
|
}
|
|
79
81
|
|
|
80
|
-
.kg-bookmark-
|
|
82
|
+
.kg-bookmark-metadata > span:nth-of-type(2):before {
|
|
81
83
|
content: "•";
|
|
82
|
-
margin: 0
|
|
84
|
+
margin: 0 6px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.kg-bookmark-thumbnail {
|
|
88
|
+
position: relative;
|
|
89
|
+
flex-grow: 1;
|
|
90
|
+
min-width: 33%;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.kg-bookmark-thumbnail img {
|
|
94
|
+
width: 100%;
|
|
95
|
+
height: 100%;
|
|
96
|
+
object-fit: cover;
|
|
97
|
+
position: absolute;
|
|
98
|
+
top: 0;
|
|
99
|
+
left: 0;
|
|
100
|
+
border-radius: 0 4px 4px 0;
|
|
83
101
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.kg-button-card {
|
|
2
|
+
display: flex;
|
|
3
|
+
position: static;
|
|
4
|
+
align-items: center;
|
|
5
|
+
width: 100%;
|
|
6
|
+
justify-content: center;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
a.kg-btn {
|
|
10
|
+
display: flex;
|
|
11
|
+
position: static;
|
|
12
|
+
align-items: center;
|
|
13
|
+
padding: 0 2.0rem;
|
|
14
|
+
height: 4.0rem;
|
|
15
|
+
line-height: 4.0rem;
|
|
16
|
+
font-size: 1.65rem;
|
|
17
|
+
font-weight: 600;
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
border-radius: 5px;
|
|
20
|
+
transition: opacity 0.2s ease-in-out;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
a.kg-btn:hover {
|
|
24
|
+
opacity: 0.85;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
a.kg-btn-accent {
|
|
28
|
+
background-color: var(--ghost-accent-color);
|
|
29
|
+
color: #fff;
|
|
30
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
.kg-card-callout {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: center;
|
|
4
|
+
padding: 20px 28px;
|
|
5
|
+
border-radius: 3px;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.kg-card-callout-grey {
|
|
9
|
+
background: rgba(124, 139, 154, 0.13);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.kg-card-callout-white {
|
|
13
|
+
background: transparent;
|
|
14
|
+
box-shadow: inset 0 0 0 1px rgba(124, 139, 154, 0.25);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.kg-card-callout-blue {
|
|
18
|
+
background: rgba(33, 172, 232, 0.12);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.kg-card-callout-green {
|
|
22
|
+
background: rgba(52, 183, 67, 0.12);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.kg-card-callout-yellow {
|
|
26
|
+
background: rgba(240, 165, 15, 0.13);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.kg-card-callout-red {
|
|
30
|
+
background: rgba(209, 46, 46, 0.11);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.kg-card-callout-pink {
|
|
34
|
+
background: rgba(225, 71, 174, 0.11);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.kg-card-callout-purple {
|
|
38
|
+
background: rgba(135, 85, 236, 0.12);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.kg-card-callout-accent {
|
|
42
|
+
background: var(--ghost-accent-color);
|
|
43
|
+
color: #fff;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.kg-callout-emoji {
|
|
47
|
+
padding-right: 12px;
|
|
48
|
+
line-height: 1.6;
|
|
49
|
+
font-size: 2rem;
|
|
50
|
+
}
|
|
@@ -1,17 +1,12 @@
|
|
|
1
|
-
.kg-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
margin: -1.0em 0 1.5em;
|
|
1
|
+
.kg-image-card:not(.kg-card-hascaption) + .kg-image-card,
|
|
2
|
+
.kg-image-card:not(.kg-card-hascaption) + .kg-gallery-card,
|
|
3
|
+
.kg-gallery-card:not(.kg-card-hascaption) + .kg-image-card,
|
|
4
|
+
.kg-gallery-card:not(.kg-card-hascaption) + .kg-gallery-card {
|
|
5
|
+
margin-top: 1.2rem;
|
|
7
6
|
}
|
|
8
7
|
|
|
9
8
|
.kg-gallery-container {
|
|
10
|
-
|
|
11
|
-
flex-direction: column;
|
|
12
|
-
margin: 1.5em auto;
|
|
13
|
-
max-width: 1040px;
|
|
14
|
-
width: 100vw;
|
|
9
|
+
position: relative;
|
|
15
10
|
}
|
|
16
11
|
|
|
17
12
|
.kg-gallery-row {
|
|
@@ -28,9 +23,9 @@
|
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
.kg-gallery-row:not(:first-of-type) {
|
|
31
|
-
margin:
|
|
26
|
+
margin: 1.2rem 0 0;
|
|
32
27
|
}
|
|
33
28
|
|
|
34
29
|
.kg-gallery-image:not(:first-of-type) {
|
|
35
|
-
margin: 0 0 0
|
|
30
|
+
margin: 0 0 0 1.2rem;
|
|
36
31
|
}
|