mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-30 22:34:01 -05:00
Initial card asset service implementation
- Requires the new @tryghost/minifier package - Adds a new service that will handle taking config from the theme and optionally including assets for Koenig editor cards - It supports both css and js as cards may need one or both - For any given config, the tool can find the matching files to include and concat and minify them into one file per type - Currently has an override in place so that this is not yet customisable in the theme - will remove this override when we're ready for the feature
This commit is contained in:
parent
df5c87fae3
commit
fdf38ba8c6
15 changed files with 514 additions and 15 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -123,7 +123,8 @@ test/coverage
|
|||
# Built asset files
|
||||
/core/built
|
||||
/core/server/web/admin/views/*.html
|
||||
/core/frontend/public/ghost.min.css
|
||||
/core/frontend/public/*.min.css
|
||||
/core/frontend/public/*.min.js
|
||||
|
||||
# Caddyfile - for local development with ssl + caddy
|
||||
Caddyfile
|
||||
|
|
|
@ -74,6 +74,7 @@ module.exports = function (grunt) {
|
|||
'core/server/**/*.js',
|
||||
'core/shared/**/*.js',
|
||||
'core/frontend/**/*.js',
|
||||
'!core/frontend/public/**',
|
||||
'core/*.js',
|
||||
'index.js',
|
||||
'config.*.json',
|
||||
|
|
|
@ -141,6 +141,9 @@ async function initFrontend() {
|
|||
const helperService = require('./frontend/services/helpers');
|
||||
await helperService.init();
|
||||
|
||||
const cardAssetService = require('./frontend/services/card-assets');
|
||||
await cardAssetService.init();
|
||||
|
||||
debug('End: initFrontend');
|
||||
}
|
||||
|
||||
|
|
|
@ -85,8 +85,22 @@ class Bridge {
|
|||
}
|
||||
}
|
||||
|
||||
getCardAssetConfig() {
|
||||
if (this.getActiveTheme()) {
|
||||
return this.getActiveTheme().config('card_assets');
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
reloadFrontend() {
|
||||
const apiVersion = this.getFrontendApiVersion();
|
||||
const cardAssetConfig = this.getCardAssetConfig();
|
||||
|
||||
debug('reload card assets config', cardAssetConfig);
|
||||
const cardAssetService = require('./frontend/services/card-assets');
|
||||
cardAssetService.load(cardAssetConfig);
|
||||
|
||||
debug('reload frontend', apiVersion);
|
||||
const siteApp = require('./frontend/web/site');
|
||||
siteApp.reload({apiVersion});
|
||||
|
|
16
core/frontend/services/card-assets/index.js
Normal file
16
core/frontend/services/card-assets/index.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
const debug = require('@tryghost/debug')('card-assets');
|
||||
const themeEngine = require('../theme-engine');
|
||||
|
||||
const CardAssetService = require('./service');
|
||||
let cardAssetService = new CardAssetService();
|
||||
|
||||
const initFn = async () => {
|
||||
const cardAssetConfig = themeEngine.getActive().config('card_assets');
|
||||
debug('initialising with config', cardAssetConfig);
|
||||
|
||||
await cardAssetService.load(cardAssetConfig);
|
||||
};
|
||||
|
||||
module.exports = cardAssetService;
|
||||
|
||||
module.exports.init = initFn;
|
96
core/frontend/services/card-assets/service.js
Normal file
96
core/frontend/services/card-assets/service.js
Normal file
|
@ -0,0 +1,96 @@
|
|||
const Minifier = require('@tryghost/minifier');
|
||||
const _ = require('lodash');
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
|
||||
const defaultConfig = false;
|
||||
|
||||
class CardAssetService {
|
||||
constructor(options = {}) {
|
||||
// @TODO: use our config paths concept
|
||||
this.src = options.src || path.join(__dirname, '../../src/cards');
|
||||
this.dest = options.dest || path.join(__dirname, '../../public');
|
||||
this.config = 'config' in options ? options.config : defaultConfig;
|
||||
this.minifier = new Minifier({src: this.src, dest: this.dest});
|
||||
|
||||
this.files = [];
|
||||
}
|
||||
|
||||
generateGlobs() {
|
||||
// CASE: The theme has asked for all card assets to be included by default
|
||||
if (this.config === true) {
|
||||
return {
|
||||
'cards.min.css': 'css/*.css',
|
||||
'cards.min.js': 'js/*.js'
|
||||
};
|
||||
}
|
||||
|
||||
// CASE: the theme has declared an include directive, we should include exactly these assets
|
||||
// Include rules take precedence over exclude rules.
|
||||
if (_.has(this.config, 'include')) {
|
||||
return {
|
||||
'cards.min.css': `css/(${this.config.include.join('|')}).css`,
|
||||
'cards.min.js': `js/(${this.config.include.join('|')}).js`
|
||||
};
|
||||
}
|
||||
|
||||
// CASE: the theme has declared an exclude directive, we should include exactly these assets
|
||||
if (_.has(this.config, 'exclude')) {
|
||||
return {
|
||||
'cards.min.css': `css/!(${this.config.exclude.join('|')}).css`,
|
||||
'cards.min.js': `js/!(${this.config.exclude.join('|')}).js`
|
||||
};
|
||||
}
|
||||
|
||||
// CASE: theme has asked that no assets be included
|
||||
// CASE: we didn't understand config, don't do anything
|
||||
return {};
|
||||
}
|
||||
|
||||
async minify(globs) {
|
||||
return await this.minifier.minify(globs);
|
||||
}
|
||||
|
||||
async clearFiles() {
|
||||
this.files = [];
|
||||
|
||||
// @deprecated switch this to use fs.rm when we drop support for Node v12
|
||||
try {
|
||||
await fs.unlink(path.join(this.dest, 'cards.min.css'));
|
||||
} catch (error) {
|
||||
// Don't worry if the file didn't exist
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.unlink(path.join(this.dest, 'cards.min.js'));
|
||||
} catch (error) {
|
||||
// Don't worry if the file didn't exist
|
||||
if (error.code !== 'ENOENT') {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A theme can declare which cards it supports, and we'll do the rest
|
||||
*
|
||||
* @param {Array|boolean} config
|
||||
* @returns
|
||||
*/
|
||||
async load(config) {
|
||||
if (config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
await this.clearFiles();
|
||||
|
||||
const globs = this.generateGlobs();
|
||||
|
||||
this.files = await this.minify(globs);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CardAssetService;
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
"posts_per_page": 5
|
||||
"posts_per_page": 5,
|
||||
"card_assets": false
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const _ = require('lodash');
|
||||
const defaultConfig = require('./defaults');
|
||||
const allowedKeys = ['posts_per_page', 'image_sizes'];
|
||||
const allowedKeys = ['posts_per_page', 'image_sizes', 'card_assets'];
|
||||
|
||||
module.exports.create = function configLoader(packageJson) {
|
||||
let config = _.cloneDeep(defaultConfig);
|
||||
|
@ -9,5 +9,9 @@ module.exports.create = function configLoader(packageJson) {
|
|||
config = _.assign(config, _.pick(packageJson.config, allowedKeys));
|
||||
}
|
||||
|
||||
// @TOD0: remove this guard when we're ready
|
||||
// Temporary override to prevent themes from controlling this until we're ready
|
||||
config.card_assets = defaultConfig.card_assets;
|
||||
|
||||
return config;
|
||||
};
|
||||
|
|
83
core/frontend/src/cards/css/bookmark.css
Normal file
83
core/frontend/src/cards/css/bookmark.css
Normal file
|
@ -0,0 +1,83 @@
|
|||
/* style.css */
|
||||
|
||||
.kg-bookmark-card {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.kg-bookmark-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row-reverse;
|
||||
color: currentColor;
|
||||
font-family: inherit;
|
||||
text-decoration: none;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.kg-bookmark-container:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.kg-bookmark-content {
|
||||
flex-basis: 0;
|
||||
flex-grow: 999;
|
||||
padding: 20px;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.kg-bookmark-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.kg-bookmark-metadata,
|
||||
.kg-bookmark-description {
|
||||
margin-top: .5em;
|
||||
}
|
||||
|
||||
.kg-bookmark-metadata {
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.kg-bookmark-description {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.kg-bookmark-icon {
|
||||
display: inline-block;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: text-bottom;
|
||||
margin-right: .5em;
|
||||
margin-bottom: .05em;
|
||||
}
|
||||
|
||||
.kg-bookmark-thumbnail {
|
||||
display: flex;
|
||||
flex-basis: 24rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.kg-bookmark-thumbnail img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
vertical-align: bottom;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.kg-bookmark-author {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.kg-bookmark-publisher::before {
|
||||
content: "•";
|
||||
margin: 0 .5em;
|
||||
}
|
36
core/frontend/src/cards/css/gallery.css
Normal file
36
core/frontend/src/cards/css/gallery.css
Normal file
|
@ -0,0 +1,36 @@
|
|||
.kg-gallery-card {
|
||||
margin: 0 0 1.5em;
|
||||
}
|
||||
|
||||
.kg-gallery-card figcaption {
|
||||
margin: -1.0em 0 1.5em;
|
||||
}
|
||||
|
||||
.kg-gallery-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 1.5em auto;
|
||||
max-width: 1040px;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.kg-gallery-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.kg-gallery-image img {
|
||||
display: block;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.kg-gallery-row:not(:first-of-type) {
|
||||
margin: 0.75em 0 0 0;
|
||||
}
|
||||
|
||||
.kg-gallery-image:not(:first-of-type) {
|
||||
margin: 0 0 0 0.75em;
|
||||
}
|
8
core/frontend/src/cards/js/gallery.js
Normal file
8
core/frontend/src/cards/js/gallery.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
var images = document.querySelectorAll('.kg-gallery-image img');
|
||||
images.forEach(function (image) {
|
||||
var container = image.closest('.kg-gallery-image');
|
||||
var width = image.attributes.width.value;
|
||||
var height = image.attributes.height.value;
|
||||
var ratio = width / height;
|
||||
container.style.flex = ratio + ' 1 0%';
|
||||
})
|
|
@ -37,7 +37,7 @@
|
|||
"test:int:slow": "yarn test:integration --reporter=mocha-slow-test-reporter",
|
||||
"test:e2e:slow": "yarn test:e2e --reporter=mocha-slow-test-reporter",
|
||||
"test:reg:slow": "mocha --require=./test/utils/overrides.js --exit --trace-warnings --recursive --extension=test.js './test/regression' --timeout=60000 --reporter=mocha-slow-test-reporter",
|
||||
"cov:unit": "c8 report --all -n 'core/{*.js,frontend,server,shared}' --reporter text --reporter html",
|
||||
"cov:unit": "c8 report --all -n 'core/{*.js,frontend,server,shared}' -x 'core/frontend/public' --reporter text --reporter html",
|
||||
"lint:server": "eslint --ignore-path .eslintignore 'core/server/**/*.js' 'core/*.js' '*.js'",
|
||||
"lint:shared": "eslint --ignore-path .eslintignore 'core/shared/**/*.js'",
|
||||
"lint:frontend": "eslint --ignore-path .eslintignore 'core/frontend/**/*.js'",
|
||||
|
@ -85,6 +85,7 @@
|
|||
"@tryghost/members-offers": "0.10.1",
|
||||
"@tryghost/members-ssr": "1.0.15",
|
||||
"@tryghost/metrics": "1.0.0",
|
||||
"@tryghost/minifier": "0.1.0",
|
||||
"@tryghost/mw-session-from-token": "0.1.26",
|
||||
"@tryghost/nodemailer": "0.3.6",
|
||||
"@tryghost/package-json": "1.0.6",
|
||||
|
|
176
test/unit/frontend/services/card-assets.test.js
Normal file
176
test/unit/frontend/services/card-assets.test.js
Normal file
|
@ -0,0 +1,176 @@
|
|||
const should = require('should');
|
||||
const sinon = require('sinon');
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs').promises;
|
||||
const os = require('os');
|
||||
|
||||
const cardAssetService = require('../../../../core/frontend/services/card-assets');
|
||||
const CardAssetService = require('../../../../core/frontend/services/card-assets/service');
|
||||
|
||||
const themeEngine = require('../../../../core/frontend/services/theme-engine');
|
||||
|
||||
describe('Card Asset Init', function () {
|
||||
it('calls loader with config', function () {
|
||||
sinon.stub(themeEngine, 'getActive').returns({
|
||||
config: function (key) {
|
||||
if (key === 'card_assets') {
|
||||
return 'random-test-value';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let serviceStub = sinon.stub(cardAssetService, 'load');
|
||||
|
||||
cardAssetService.init();
|
||||
serviceStub.calledOnce.should.eql(true);
|
||||
serviceStub.calledWith('random-test-value').should.eql(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Card Asset Service', function () {
|
||||
let testDir,
|
||||
srcDir,
|
||||
destDir;
|
||||
|
||||
before(async function () {
|
||||
testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'ghost-tests-'));
|
||||
srcDir = path.join(testDir, 'src');
|
||||
destDir = path.join(testDir, 'dest');
|
||||
|
||||
await fs.mkdir(srcDir);
|
||||
await fs.mkdir(destDir);
|
||||
await fs.mkdir(path.join(srcDir, 'css'));
|
||||
await fs.mkdir(path.join(srcDir, 'js'));
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await fs.rmdir(testDir, {recursive: true});
|
||||
});
|
||||
|
||||
it('can load nothing', async function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
src: srcDir,
|
||||
dest: destDir
|
||||
});
|
||||
|
||||
await cardAssets.load();
|
||||
|
||||
cardAssets.files.should.eql([]);
|
||||
});
|
||||
|
||||
it('can load a single css file', async function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
src: srcDir,
|
||||
dest: destDir
|
||||
});
|
||||
|
||||
await fs.writeFile(path.join(srcDir, 'css', 'test.css'), '.test { color: #fff }');
|
||||
|
||||
await cardAssets.load(true);
|
||||
|
||||
cardAssets.files.should.eql(['cards.min.css']);
|
||||
});
|
||||
|
||||
it('can clearFiles', async function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
src: srcDir,
|
||||
dest: destDir
|
||||
});
|
||||
|
||||
await fs.writeFile(path.join(destDir, 'cards.min.css'), 'test-css');
|
||||
await fs.writeFile(path.join(destDir, 'cards.min.js'), 'test-js');
|
||||
|
||||
await cardAssets.clearFiles();
|
||||
|
||||
try {
|
||||
await fs.readFile(path.join(destDir, 'cards.min.css'), 'utf-8');
|
||||
should.fail(cardAssets, 'CSS file should not exist');
|
||||
} catch (error) {
|
||||
if (error instanceof should.AssertionError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
error.code.should.eql('ENOENT');
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.readFile(path.join(destDir, 'cards.min.js'), 'utf-8');
|
||||
should.fail(cardAssets, 'JS file should not exist');
|
||||
} catch (error) {
|
||||
if (error instanceof should.AssertionError) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
error.code.should.eql('ENOENT');
|
||||
}
|
||||
});
|
||||
|
||||
describe('Generate the correct glob strings', function () {
|
||||
// @TODO: change the default
|
||||
it('DEFAULT CASE: do nothing [temp]', function () {
|
||||
const cardAssets = new CardAssetService();
|
||||
|
||||
cardAssets.generateGlobs().should.eql({});
|
||||
});
|
||||
|
||||
it('CASE: card_assets = true, all cards assets should be included', function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
config: true
|
||||
});
|
||||
|
||||
cardAssets.generateGlobs().should.eql({
|
||||
'cards.min.css': 'css/*.css',
|
||||
'cards.min.js': 'js/*.js'
|
||||
});
|
||||
});
|
||||
|
||||
it('CASE: card_assets = false, no card assets should be included', function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
config: false
|
||||
});
|
||||
|
||||
cardAssets.generateGlobs().should.eql({});
|
||||
});
|
||||
|
||||
it('CASE: card_assets is an object with an exclude property, generate inverse match strings', function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
config: {
|
||||
exclude: ['bookmarks']
|
||||
}
|
||||
});
|
||||
|
||||
cardAssets.generateGlobs().should.eql({
|
||||
'cards.min.css': 'css/!(bookmarks).css',
|
||||
'cards.min.js': 'js/!(bookmarks).js'
|
||||
});
|
||||
});
|
||||
|
||||
it('CASE: card_assets is an object with an include property, generate match strings', function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
config: {
|
||||
include: ['gallery']
|
||||
}
|
||||
});
|
||||
|
||||
cardAssets.generateGlobs().should.eql({
|
||||
'cards.min.css': 'css/(gallery).css',
|
||||
'cards.min.js': 'js/(gallery).js'
|
||||
});
|
||||
});
|
||||
|
||||
it('CASE: card_assets has include and exclude, include should win', function () {
|
||||
const cardAssets = new CardAssetService({
|
||||
config: {
|
||||
include: ['gallery'],
|
||||
exclude: ['bookmark']
|
||||
}
|
||||
});
|
||||
|
||||
cardAssets.generateGlobs().should.eql({
|
||||
'cards.min.css': 'css/(gallery).css',
|
||||
'cards.min.js': 'js/(gallery).js'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -11,25 +11,37 @@ describe('Themes', function () {
|
|||
it('handles no package.json', function () {
|
||||
const config = themeConfig.create();
|
||||
|
||||
config.should.eql({posts_per_page: 5});
|
||||
config.should.eql({
|
||||
posts_per_page: 5,
|
||||
card_assets: false
|
||||
});
|
||||
});
|
||||
|
||||
it('handles package.json without config', function () {
|
||||
const config = themeConfig.create({name: 'casper'});
|
||||
|
||||
config.should.eql({posts_per_page: 5});
|
||||
config.should.eql({
|
||||
posts_per_page: 5,
|
||||
card_assets: false
|
||||
});
|
||||
});
|
||||
|
||||
it('handles allows package.json to overrideg default', function () {
|
||||
const config = themeConfig.create({name: 'casper', config: {posts_per_page: 3}});
|
||||
|
||||
config.should.eql({posts_per_page: 3});
|
||||
config.should.eql({
|
||||
posts_per_page: 3,
|
||||
card_assets: false
|
||||
});
|
||||
});
|
||||
|
||||
it('handles ignores non-allowed config', function () {
|
||||
const config = themeConfig.create({name: 'casper', config: {magic: 'roundabout'}});
|
||||
|
||||
config.should.eql({posts_per_page: 5});
|
||||
config.should.eql({
|
||||
posts_per_page: 5,
|
||||
card_assets: false
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
61
yarn.lock
61
yarn.lock
|
@ -1350,7 +1350,7 @@
|
|||
"@tryghost/tpl" "^0.1.4"
|
||||
lodash "^4.17.21"
|
||||
|
||||
"@tryghost/debug@0.1.9", "@tryghost/debug@^0.1.2", "@tryghost/debug@^0.1.4", "@tryghost/debug@^0.1.5", "@tryghost/debug@^0.1.9":
|
||||
"@tryghost/debug@0.1.9", "@tryghost/debug@^0.1.2", "@tryghost/debug@^0.1.4", "@tryghost/debug@^0.1.5", "@tryghost/debug@^0.1.8", "@tryghost/debug@^0.1.9":
|
||||
version "0.1.9"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/debug/-/debug-0.1.9.tgz#9cb4b5debca96ffb010b73811f01da6ca581935d"
|
||||
integrity sha512-//j7JykptEvKWuxNnE8FgjNrUqkZReVEonMvMZdP25JUqza/3gNhju6vcwsl9lZwGk4Lnn/NEGZil7Gg+Y76BQ==
|
||||
|
@ -1395,7 +1395,7 @@
|
|||
ghost-ignition "^4.2.4"
|
||||
lodash "^4.17.20"
|
||||
|
||||
"@tryghost/errors@0.2.17", "@tryghost/errors@^0.2.10", "@tryghost/errors@^0.2.11", "@tryghost/errors@^0.2.12", "@tryghost/errors@^0.2.13", "@tryghost/errors@^0.2.14", "@tryghost/errors@^0.2.17", "@tryghost/errors@^0.2.9":
|
||||
"@tryghost/errors@0.2.17", "@tryghost/errors@^0.2.10", "@tryghost/errors@^0.2.11", "@tryghost/errors@^0.2.12", "@tryghost/errors@^0.2.13", "@tryghost/errors@^0.2.14", "@tryghost/errors@^0.2.16", "@tryghost/errors@^0.2.17", "@tryghost/errors@^0.2.9":
|
||||
version "0.2.17"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/errors/-/errors-0.2.17.tgz#9b89f3845256ace5650593f41cc86d64965b56ed"
|
||||
integrity sha512-Mj+bedWOwfooNA8fQdp6gIcRvWcKhJ/hOyGzu6OLFDLgEosFEeuFgXE6SsAWkf9+9NTYX30w88qGIWZqOhEAmQ==
|
||||
|
@ -1666,6 +1666,18 @@
|
|||
optionalDependencies:
|
||||
promise.allsettled "^1.0.5"
|
||||
|
||||
"@tryghost/minifier@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/minifier/-/minifier-0.1.0.tgz#121f30694c5a0e3755dfe77a1d5df6dd5191e862"
|
||||
integrity sha512-ofP+wuYV/je7IrfzwYQVR7FGtsXNSHrjpTxcqIvP6SuNhJu0npob6k/67T+95sOyy+Qu24HK8su277azmgDxXA==
|
||||
dependencies:
|
||||
"@tryghost/debug" "^0.1.8"
|
||||
"@tryghost/errors" "^0.2.16"
|
||||
"@tryghost/tpl" "^0.1.7"
|
||||
csso "4.2.0"
|
||||
terser "^5.9.0"
|
||||
tiny-glob "^0.2.9"
|
||||
|
||||
"@tryghost/mobiledoc-kit@^0.12.4-ghost.1":
|
||||
version "0.12.4-ghost.1"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/mobiledoc-kit/-/mobiledoc-kit-0.12.4-ghost.1.tgz#32060242b4c7e787a9605ba856454c6a26141925"
|
||||
|
@ -1781,7 +1793,7 @@
|
|||
dependencies:
|
||||
unidecode "^0.1.8"
|
||||
|
||||
"@tryghost/tpl@0.1.8", "@tryghost/tpl@^0.1.2", "@tryghost/tpl@^0.1.3", "@tryghost/tpl@^0.1.4", "@tryghost/tpl@^0.1.5", "@tryghost/tpl@^0.1.8":
|
||||
"@tryghost/tpl@0.1.8", "@tryghost/tpl@^0.1.2", "@tryghost/tpl@^0.1.3", "@tryghost/tpl@^0.1.4", "@tryghost/tpl@^0.1.5", "@tryghost/tpl@^0.1.7", "@tryghost/tpl@^0.1.8":
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/@tryghost/tpl/-/tpl-0.1.8.tgz#28acd930b11b71a23372f1855cb8b92282c20bdd"
|
||||
integrity sha512-0M02hZ3VNhlH9KeUXV75l3UUeNSRhmXUZfWn4vrosu8B3YCwIx+Q/cpWl5DiZ0QuIaVT7YwYDEHtFMgsKk0gXQ==
|
||||
|
@ -3163,7 +3175,7 @@ commander@5.1.0:
|
|||
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
|
||||
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
|
||||
|
||||
commander@^2.19.0:
|
||||
commander@^2.19.0, commander@^2.20.0:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
@ -3556,7 +3568,7 @@ cssnano@5.0.9:
|
|||
lilconfig "^2.0.3"
|
||||
yaml "^1.10.2"
|
||||
|
||||
csso@^4.2.0:
|
||||
csso@4.2.0, csso@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
|
||||
integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==
|
||||
|
@ -5320,6 +5332,16 @@ globals@^13.6.0, globals@^13.9.0:
|
|||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globalyzer@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
|
||||
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
|
||||
|
||||
globrex@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
|
||||
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
|
||||
|
||||
globule@^1.0.0:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/globule/-/globule-1.3.3.tgz#811919eeac1ab7344e905f2e3be80a13447973c2"
|
||||
|
@ -10163,6 +10185,14 @@ source-map-resolve@^0.5.0:
|
|||
source-map-url "^0.4.0"
|
||||
urix "^0.1.0"
|
||||
|
||||
source-map-support@~0.5.20:
|
||||
version "0.5.20"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9"
|
||||
integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-url@^0.4.0:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56"
|
||||
|
@ -10173,12 +10203,12 @@ source-map@^0.5.0, source-map@^0.5.6:
|
|||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
|
||||
integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
|
||||
|
||||
source-map@^0.6.1, source-map@~0.6.1:
|
||||
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@^0.7.3:
|
||||
source-map@^0.7.3, source-map@~0.7.2:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
@ -10613,6 +10643,15 @@ tarn@^3.0.1:
|
|||
resolved "https://registry.yarnpkg.com/tarn/-/tarn-3.0.1.tgz#ebac2c6dbc6977d34d4526e0a7814200386a8aec"
|
||||
integrity sha512-6usSlV9KyHsspvwu2duKH+FMUhqJnAh6J5J/4MITl8s94iSUQTLkJggdiewKv4RyARQccnigV48Z+khiuVZDJw==
|
||||
|
||||
terser@^5.9.0:
|
||||
version "5.9.0"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351"
|
||||
integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
source-map "~0.7.2"
|
||||
source-map-support "~0.5.20"
|
||||
|
||||
test-exclude@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
|
||||
|
@ -10647,6 +10686,14 @@ timsort@^0.3.0:
|
|||
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
|
||||
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
|
||||
|
||||
tiny-glob@^0.2.9:
|
||||
version "0.2.9"
|
||||
resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2"
|
||||
integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==
|
||||
dependencies:
|
||||
globalyzer "0.1.0"
|
||||
globrex "^0.1.2"
|
||||
|
||||
tiny-lr@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.1.1.tgz#9fa547412f238fedb068ee295af8b682c98b2aab"
|
||||
|
|
Loading…
Reference in a new issue