mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Merge pull request #6771 from acburdine/hidden-tags-for-the-win
Internal Tags
This commit is contained in:
commit
fd2bf5aab7
11 changed files with 161 additions and 6 deletions
|
@ -33,6 +33,7 @@ function getBaseConfig() {
|
|||
useGoogleFonts: {value: !config.isPrivacyDisabled('useGoogleFonts'), type: 'bool'},
|
||||
useGravatar: {value: !config.isPrivacyDisabled('useGravatar'), type: 'bool'},
|
||||
publicAPI: labsFlag('publicAPI'),
|
||||
internalTags: labsFlag('internalTags'),
|
||||
blogUrl: {value: config.url.replace(/\/$/, ''), type: 'string'},
|
||||
blogTitle: {value: config.theme.title, type: 'string'},
|
||||
routeKeywords: {value: JSON.stringify(config.routeKeywords), type: 'json'}
|
||||
|
|
|
@ -54,7 +54,7 @@ tags = {
|
|||
* @return {Promise<Tag>} Tag
|
||||
*/
|
||||
read: function read(options) {
|
||||
var attrs = ['id', 'slug'],
|
||||
var attrs = ['id', 'slug', 'visibility'],
|
||||
tasks;
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ var _ = require('lodash'),
|
|||
errors = require('../../errors'),
|
||||
filters = require('../../filters'),
|
||||
safeString = require('../../utils/index').safeString,
|
||||
labs = require('../../utils/labs'),
|
||||
handleError = require('./error'),
|
||||
fetchData = require('./fetch-data'),
|
||||
formatResponse = require('./format-response'),
|
||||
|
@ -21,6 +22,15 @@ function renderChannel(req, res, next) {
|
|||
channelOpts.postOptions.page = pageParam;
|
||||
channelOpts.slugParam = slugParam;
|
||||
|
||||
// this is needed here because the channel config is cloned,
|
||||
// and thus changes to labs flags don't update the config
|
||||
// Once internal tags is moved out of labs the functionality can be
|
||||
// moved back into the channel config
|
||||
if (labs.isSet('internalTags') && channelOpts.name === 'tag') {
|
||||
channelOpts.postOptions.filter = 'tags:\'%s\'+tags.visibility:\'public\'';
|
||||
channelOpts.data.tag.options = {slug: '%s', visibility: 'public'};
|
||||
}
|
||||
|
||||
// Call fetchData to get everything we need from the API
|
||||
return fetchData(channelOpts).then(function handleResult(result) {
|
||||
// If page is greater than number of pages we have, go straight to 404
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
var hbs = require('express-hbs'),
|
||||
_ = require('lodash'),
|
||||
config = require('../config'),
|
||||
labs = require('../utils/labs'),
|
||||
utils = require('./utils'),
|
||||
tags;
|
||||
|
||||
|
@ -26,6 +27,10 @@ tags = function (options) {
|
|||
output = '';
|
||||
|
||||
function createTagList(tags) {
|
||||
if (labs.isSet('internalTags')) {
|
||||
tags = _.filter(tags, 'visibility', 'public');
|
||||
}
|
||||
|
||||
if (autolink) {
|
||||
return _.map(tags, function (tag) {
|
||||
return utils.linkTemplate({
|
||||
|
|
|
@ -15,6 +15,7 @@ var _ = require('lodash'),
|
|||
Promise = require('bluebird'),
|
||||
schema = require('../../data/schema'),
|
||||
utils = require('../../utils'),
|
||||
labs = require('../../utils/labs'),
|
||||
uuid = require('node-uuid'),
|
||||
validation = require('../../data/validation'),
|
||||
plugins = require('../plugins'),
|
||||
|
@ -494,6 +495,15 @@ ghostBookshelf.Model = ghostBookshelf.Model.extend({
|
|||
slug = (slug.indexOf('-') > -1) ? slug.substr(0, slug.indexOf('-')) : slug;
|
||||
}
|
||||
|
||||
if (!_.has(options, 'importing') || !options.importing) {
|
||||
// TODO: remove the labs requirement when internal tags is out of beta
|
||||
// This checks if the first character of a tag name is a #. If it is, this
|
||||
// is an internal tag, and as such we should add 'hash' to the beginning of the slug
|
||||
if (labs.isSet('internalTags') && baseName === 'tag' && /^#/.test(base)) {
|
||||
slug = 'hash-' + slug;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the filtered slug doesn't match any of the reserved keywords
|
||||
return filters.doFilter('slug.reservedSlugs', config.slugs.reserved).then(function then(slugList) {
|
||||
// Some keywords cannot be changed
|
||||
|
|
|
@ -33,8 +33,9 @@ tagUpdate = {
|
|||
},
|
||||
|
||||
createTagThenAttachTagToPost: function createTagThenAttachTagToPost(TagModel, post, tag, index, options) {
|
||||
var fields = ['name', 'slug', 'description', 'image', 'visibility', 'parent_id', 'meta_title', 'meta_description'];
|
||||
return function () {
|
||||
return TagModel.add({name: tag.name}, options).then(function then(createdTag) {
|
||||
return TagModel.add(_.pick(tag, fields), options).then(function then(createdTag) {
|
||||
return tagUpdate.attachTagToPost(post, createdTag, index, options)();
|
||||
});
|
||||
};
|
||||
|
|
|
@ -76,7 +76,8 @@ Tag = ghostBookshelf.Model.extend({
|
|||
// these are the only options that can be passed to Bookshelf / Knex.
|
||||
validOptions = {
|
||||
findPage: ['page', 'limit', 'columns', 'filter', 'order'],
|
||||
findAll: ['columns']
|
||||
findAll: ['columns'],
|
||||
findOne: ['visibility']
|
||||
};
|
||||
|
||||
if (validOptions[methodName]) {
|
||||
|
|
|
@ -4,7 +4,7 @@ var config = require('../config'),
|
|||
flagIsSet = function flagIsSet(flag) {
|
||||
var labsConfig = config.labs;
|
||||
|
||||
return !!labsConfig[flag] && labsConfig[flag] === true;
|
||||
return labsConfig && labsConfig[flag] && labsConfig[flag] === true;
|
||||
};
|
||||
|
||||
module.exports.isSet = flagIsSet;
|
||||
|
|
24
core/test/unit/controllers/frontend/channel-config_spec.js
Normal file
24
core/test/unit/controllers/frontend/channel-config_spec.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*globals describe, it*/
|
||||
/*jshint expr:true*/
|
||||
var should = require('should'),
|
||||
channelConfig = require('../../../../server/controllers/frontend/channel-config').get;
|
||||
|
||||
describe('Channel Config', function () {
|
||||
it('should get the index config', function () {
|
||||
var result = channelConfig('index');
|
||||
should.exist(result);
|
||||
result.name.should.eql('index');
|
||||
});
|
||||
|
||||
it('should get the author config', function () {
|
||||
var result = channelConfig('author');
|
||||
should.exist(result);
|
||||
result.name.should.eql('author');
|
||||
});
|
||||
|
||||
it('should get the tag config', function () {
|
||||
var result = channelConfig('tag');
|
||||
should.exist(result);
|
||||
result.name.should.eql('tag');
|
||||
});
|
||||
});
|
68
core/test/unit/controllers/frontend/render-channel_spec.js
Normal file
68
core/test/unit/controllers/frontend/render-channel_spec.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*globals describe, it, beforeEach, afterEach*/
|
||||
/*jshint expr:true*/
|
||||
var should = require('should'),
|
||||
rewire = require('rewire'),
|
||||
sinon = require('sinon'),
|
||||
channelConfig = require('../../../../server/controllers/frontend/channel-config').get,
|
||||
|
||||
// stuff being tested
|
||||
labs = require('../../../../server/utils/labs'),
|
||||
renderChannel = rewire('../../../../server/controllers/frontend/render-channel'),
|
||||
|
||||
sandbox = sinon.sandbox.create(),
|
||||
originalFetchData;
|
||||
|
||||
// stop jshint complaining
|
||||
should.equal(true, true);
|
||||
|
||||
describe('Render Channel', function () {
|
||||
beforeEach(function () {
|
||||
originalFetchData = renderChannel.__get__('fetchData');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
|
||||
renderChannel.__set__('fetchData', originalFetchData);
|
||||
});
|
||||
|
||||
describe('internal tags labs flag', function () {
|
||||
var req = {
|
||||
channelConfig: channelConfig('tag'),
|
||||
params: {}
|
||||
},
|
||||
promise = {
|
||||
then: function () {
|
||||
return {catch: function () {}};
|
||||
}
|
||||
};
|
||||
|
||||
it('should return normal tag config if labs flag is not set', function () {
|
||||
sandbox.stub(labs, 'isSet').returns(false);
|
||||
|
||||
renderChannel.__set__('fetchData', function (channelOpts) {
|
||||
channelOpts.name.should.eql('tag');
|
||||
channelOpts.postOptions.filter.should.eql('tags:\'%s\'');
|
||||
channelOpts.data.tag.options.should.eql({slug: '%s'});
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
renderChannel(req);
|
||||
});
|
||||
|
||||
it('should return new tag config if labs flag is set', function () {
|
||||
sandbox.stub(labs, 'isSet').returns(true);
|
||||
|
||||
renderChannel.__set__('fetchData', function (channelOpts) {
|
||||
channelOpts.name.should.eql('tag');
|
||||
channelOpts.postOptions.filter.should.eql('tags:\'%s\'+tags.visibility:\'public\'');
|
||||
channelOpts.data.tag.options.should.eql({slug: '%s', visibility: 'public'});
|
||||
|
||||
return promise;
|
||||
});
|
||||
|
||||
renderChannel(req);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,18 +1,27 @@
|
|||
/*globals describe, before, it*/
|
||||
/*globals describe, afterEach, before, it*/
|
||||
|
||||
var should = require('should'),
|
||||
sinon = require('sinon'),
|
||||
hbs = require('express-hbs'),
|
||||
utils = require('./utils'),
|
||||
rewire = require('rewire'),
|
||||
|
||||
// Stuff we are testing
|
||||
handlebars = hbs.handlebars,
|
||||
helpers = rewire('../../../server/helpers');
|
||||
labs = require('../../../server/utils/labs'),
|
||||
helpers = rewire('../../../server/helpers'),
|
||||
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
describe('{{tags}} helper', function () {
|
||||
before(function () {
|
||||
utils.loadHelpers();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it('has loaded tags helper', function () {
|
||||
should.exist(handlebars.helpers.tags);
|
||||
});
|
||||
|
@ -174,4 +183,30 @@ describe('{{tags}} helper', function () {
|
|||
|
||||
String(rendered).should.equal('<a href="/tag/foo-bar/">foo</a>, <a href="/tag/bar/">bar</a>, <a href="/tag/baz/">baz</a>');
|
||||
});
|
||||
|
||||
describe('Hidden/Internal tags', function () {
|
||||
// @TODO: remove these once internal tags are out of beta
|
||||
it('Should output internal tags when the labs flag IS NOT set', function () {
|
||||
sandbox.stub(labs, 'isSet').returns(false);
|
||||
var tags = [{name: 'foo', slug: 'foo-bar', visibility: 'public'}, {name: 'bar', slug: 'bar', visibility: 'public'}],
|
||||
rendered = helpers.tags.call(
|
||||
{tags: tags}
|
||||
);
|
||||
should.exist(rendered);
|
||||
|
||||
String(rendered).should.equal('<a href="/tag/foo-bar/">foo</a>, <a href="/tag/bar/">bar</a>');
|
||||
});
|
||||
|
||||
it('Should NOT output internal tags when the labs flag IS set', function () {
|
||||
sandbox.stub(labs, 'isSet').returns(true);
|
||||
|
||||
var tags = [{name: 'foo', slug: 'foo-bar', visibility: 'public'}, {name: 'bar', slug: 'bar', visibility: 'internal'}],
|
||||
rendered = helpers.tags.call(
|
||||
{tags: tags}
|
||||
);
|
||||
should.exist(rendered);
|
||||
|
||||
String(rendered).should.equal('<a href="/tag/foo-bar/">foo</a>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue