Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Add v3.38.0
Browse files Browse the repository at this point in the history
YannickRe committed Nov 17, 2020
1 parent 7b81ae0 commit fe9d9f6
Showing 103 changed files with 1,700 additions and 1,646 deletions.
1 change: 0 additions & 1 deletion Gruntfile.js
Original file line number Diff line number Diff line change
@@ -40,7 +40,6 @@ const configureGrunt = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-symlink');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-express-server');
grunt.loadNpmTasks('grunt-mocha-cli');
2 changes: 1 addition & 1 deletion content/themes/casper/assets/built/screen.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion content/themes/casper/assets/built/screen.css.map

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions content/themes/casper/assets/css/screen.css
Original file line number Diff line number Diff line change
@@ -2263,9 +2263,9 @@ Usage (In Ghost editor):
flex-wrap: wrap;
align-items: center;
margin-top: 14px;
color: color-mod(var(--midgrey) l(-10%));
color: var(--darkgrey);
font-size: 1.5rem;
font-weight: 400;
font-weight: 500;
}

.post-full-content .kg-bookmark-icon {
@@ -2289,6 +2289,8 @@ Usage (In Ghost editor):
line-height: 1.5em;
text-overflow: ellipsis;
white-space: nowrap;
color: color-mod(var(--midgrey) l(-10%));
font-weight: 400;
}

@media (max-width: 800px) {
10 changes: 5 additions & 5 deletions content/themes/casper/package.json
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
"name": "casper",
"description": "A clean, minimal default theme for the Ghost publishing platform",
"demo": "https://demo.ghost.io",
"version": "3.1.1",
"version": "3.1.2",
"engines": {
"ghost": ">=3.0.0",
"ghost-api": "v3"
@@ -46,19 +46,19 @@
"bugs": "https://github.com/TryGhost/Casper/issues",
"contributors": "https://github.com/TryGhost/Casper/graphs/contributors",
"devDependencies": {
"@tryghost/release-utils": "0.6.7",
"autoprefixer": "10.0.1",
"@tryghost/release-utils": "0.6.8",
"autoprefixer": "10.0.2",
"beeper": "2.0.0",
"cssnano": "4.1.10",
"gscan": "3.5.7",
"gscan": "3.6.0",
"gulp": "4.0.2",
"gulp-concat": "2.6.1",
"gulp-livereload": "4.0.2",
"gulp-postcss": "9.0.0",
"gulp-uglify": "3.0.2",
"gulp-zip": "5.0.2",
"inquirer": "7.3.3",
"postcss": "8.1.2",
"postcss": "8.1.7",
"postcss-color-mod-function": "3.0.3",
"postcss-easy-import": "3.0.0",
"pump": "3.0.0"
459 changes: 257 additions & 202 deletions content/themes/casper/yarn.lock

Large diffs are not rendered by default.

This file was deleted.

Large diffs are not rendered by default.

This file was deleted.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions core/built/assets/icons/heart.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion core/frontend/helpers/ghost_head.js
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@ function getMembersHelper() {
const stripeConnectAccountId = settingsCache.get('stripe_connect_account_id');

let membersHelper = `<script defer src="https://unpkg.com/@tryghost/portal@latest/umd/portal.min.js" data-ghost="${urlUtils.getSiteUrl()}"></script>`;
membersHelper += (`<style type='text/css'> ${templateStyles}</style>`);
membersHelper += (`<style> ${templateStyles}</style>`);
if ((!!stripeDirectSecretKey && !!stripeDirectPublishableKey) || !!stripeConnectAccountId) {
membersHelper += '<script async src="https://js.stripe.com/v3/"></script>';
}
195 changes: 173 additions & 22 deletions core/frontend/services/redirects/settings.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
const fs = require('fs-extra');
const path = require('path');
const Promise = require('bluebird');
const moment = require('moment-timezone');

const yaml = require('js-yaml');
const Promise = require('bluebird');
const validation = require('./validation');

const config = require('../../../shared/config');
const {i18n} = require('../../../server/lib/common');
const errors = require('@tryghost/errors');

/**
* Redirect configuration object
* @typedef {Object} RedirectConfig
* @property {String} from - Defines the relative incoming URL or pattern (regex)
* @property {String} to - Defines where the incoming traffic should be redirected to, which can be a static URL, or a dynamic value using regex (example: "to": "/$1/")
* @property {boolean} permanent - Can be defined with true for a permanent HTTP 301 redirect, or false for a temporary HTTP 302 redirect
*/

const readRedirectsFile = (redirectsPath) => {
return fs.readFile(redirectsPath, 'utf-8')
.then((content) => {
try {
content = JSON.parse(content);
} catch (err) {
throw new errors.BadRequestError({
message: i18n.t('errors.general.jsonParse', {context: err.message})
});
}

return content;
})
.catch((err) => {
if (err.code === 'ENOENT') {
return Promise.resolve([]);
@@ -37,16 +34,126 @@ const readRedirectsFile = (redirectsPath) => {
});
};

const setFromFilePath = (filePath) => {
const redirectsPath = path.join(config.getContentPath('data'), 'redirects.json');
const backupRedirectsPath = path.join(config.getContentPath('data'), `redirects-${moment().format('YYYY-MM-DD-HH-mm-ss')}.json`);
/**
*
* @param {String} content serialized JSON or YAML configuration
* @param {String} ext one of `.json` or `.yaml` extensions
*
* @returns {RedirectConfig[]} of parsed redirect config objects
*/
const parseRedirectsFile = (content, ext) => {
if (ext === '.json') {
let redirects;

try {
redirects = JSON.parse(content);
} catch (err) {
throw new errors.BadRequestError({
message: i18n.t('errors.general.jsonParse', {context: err.message})
});
}

return redirects;
}

if (ext === '.yaml') {
let redirects = [];
let configYaml = yaml.safeLoad(content);

// yaml.safeLoad passes almost every yaml code.
// Because of that, it's hard to detect if there's an error in the file.
// But one of the obvious errors is the plain string output.
// Here we check if the user made this mistake.
if (typeof configYaml === 'string') {
throw new errors.BadRequestError({
message: i18n.t('errors.api.redirects.yamlParse'),
help: 'https://ghost.org/docs/api/handlebars-themes/routing/redirects/'
});
}

/**
* 302: Temporary redirects
*/
for (const redirect in configYaml['302']) {
redirects.push({
from: redirect,
to: configYaml['302'][redirect],
permanent: false
});
}

/**
* 301: Permanent redirects
*/
for (const redirect in configYaml['301']) {
redirects.push({
from: redirect,
to: configYaml['301'][redirect],
permanent: true
});
}

return redirects;
}

throw new errors.IncorrectUsageError();
};

const createRedirectsFilePath = (ext) => {
return path.join(config.getContentPath('data'), `redirects${ext}`);
};

const getRedirectsFilePath = async () => {
const yamlPath = createRedirectsFilePath('.yaml');
const jsonPath = createRedirectsFilePath('.json');

const yamlExists = await fs.pathExists(yamlPath);

if (yamlExists) {
return yamlPath;
}

const jsonExist = await fs.pathExists(jsonPath);

return fs.pathExists(redirectsPath)
.then((redirectExists) => {
if (!redirectExists) {
if (jsonExist) {
return jsonPath;
}

return null;
};

const getCurrentRedirectsFilePathSync = () => {
const yamlPath = createRedirectsFilePath('.yaml');
const jsonPath = createRedirectsFilePath('.json');

if (fs.existsSync(yamlPath)) {
return yamlPath;
}

if (fs.existsSync(jsonPath)) {
return jsonPath;
}

return null;
};

const getBackupRedirectsFilePath = (filePath) => {
const {dir, name, ext} = path.parse(filePath);

return path.join(dir, `${name}-${moment().format('YYYY-MM-DD-HH-mm-ss')}${ext}`);
};

// '.json' is the default here because 'yaml' redirects file format is added later in v3.
// @TODO: change the default to '.yaml' in v4. It may be even removed if '.json' format is deprecated.
const setFromFilePath = (filePath, ext = '.json') => {
return getRedirectsFilePath()
.then((redirectsFilePath) => {
if (!redirectsFilePath) {
return null;
}

const backupRedirectsPath = getBackupRedirectsFilePath(redirectsFilePath);

return fs.pathExists(backupRedirectsPath)
.then((backupExists) => {
if (!backupExists) {
@@ -56,21 +163,65 @@ const setFromFilePath = (filePath) => {
return fs.unlink(backupRedirectsPath);
})
.then(() => {
return fs.move(redirectsPath, backupRedirectsPath);
return fs.move(redirectsFilePath, backupRedirectsPath);
});
})
.then(() => {
return readRedirectsFile(filePath)
.then((content) => {
return parseRedirectsFile(content, ext);
})
.then((content) => {
validation.validate(content);
return fs.writeFile(redirectsPath, JSON.stringify(content), 'utf-8');

if (ext === '.json') {
return fs.writeFile(createRedirectsFilePath('.json'), JSON.stringify(content), 'utf-8');
}

if (ext === '.yaml') {
return fs.copy(filePath, createRedirectsFilePath('.yaml'));
}
});
});
};

// @TODO: When yaml has been changed as the default redirects file format,
// change this like `const defaultRedirectsContent = ''`.
// Default json content is []. But the default YAML content is an empty string.
const defaultJsonFileContent = [];

const get = () => {
return readRedirectsFile(path.join(config.getContentPath('data'), 'redirects.json'));
return getRedirectsFilePath().then((filePath) => {
if (filePath === null) {
return defaultJsonFileContent;
}

return readRedirectsFile(filePath).then((content) => {
return path.extname(filePath) === '.json'
? parseRedirectsFile(content, '.json')
: content;
});
});
};

/**
* Syncrounously loads current oncifg file and parses it's content
*
* @returns {{RedirectConfig[]}} of parsed redirect configurations
*/
const loadRedirectsFile = () => {
const filePath = getCurrentRedirectsFilePathSync();

if (filePath === null) {
return defaultJsonFileContent;
}

const content = fs.readFileSync(filePath);

return parseRedirectsFile(content, path.extname(filePath));
};

module.exports.get = get;
module.exports.setFromFilePath = setFromFilePath;
module.exports.getRedirectsFilePath = getRedirectsFilePath;
module.exports.loadRedirectsFile = loadRedirectsFile;
1 change: 1 addition & 0 deletions core/frontend/services/routing/settings.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Promise = require('bluebird');
const moment = require('moment-timezone');
const fs = require('fs-extra');
const path = require('path');
2 changes: 1 addition & 1 deletion core/frontend/services/settings/ensure-settings.js
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@ module.exports = function ensureSettingsFiles(knownSettings) {
const defaultFileName = `default-${fileName}`;
const filePath = path.join(contentPath, fileName);

return fs.readFile(filePath, 'utf8')
return Promise.resolve(fs.readFile(filePath, 'utf8'))
.catch({code: 'ENOENT'}, () => {
const defaultFilePath = path.join(defaultSettingsPath, defaultFileName);
// CASE: file doesn't exist, copy it from our defaults
4 changes: 4 additions & 0 deletions core/frontend/services/url/Resource.js
Original file line number Diff line number Diff line change
@@ -6,6 +6,10 @@ const errors = require('@tryghost/errors');
* Resource cache.
*/
class Resource extends EventEmitter {
/**
* @param {('posts'|'pages'|'tags'|'authors')} type - of the resource
* @param {Object} obj - object data to sotre
*/
constructor(type, obj) {
super();

14 changes: 2 additions & 12 deletions core/frontend/services/url/UrlGenerator.js
Original file line number Diff line number Diff line change
@@ -142,7 +142,7 @@ class UrlGenerator {

/**
* @description Try to own a resource and generate it's url if so.
* @param {Resource} resource
* @param {import('./Resource')} resource - instance of the Resource class
* @returns {boolean}
* @private
*/
@@ -161,17 +161,7 @@ class UrlGenerator {

// CASE 1: route has no custom filter, it will own the resource for sure
// CASE 2: find out if my filter matches the resource
if (!this.filter) {
this.urls.add({
url: url,
generatorId: this.uid,
resource: resource
});

resource.reserve();
this._resourceListeners(resource);
return true;
} else if (this.nql.queryJSON(resource.data)) {
if ((!this.filter) || (this.nql.queryJSON(resource.data))) {
this.urls.add({
url: url,
generatorId: this.uid,
1 change: 1 addition & 0 deletions core/server/api/canary/images.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Promise = require('bluebird');
const storage = require('../../adapters/storage');

module.exports = {
Loading

0 comments on commit fe9d9f6

Please sign in to comment.