Switch to Eslint (#9197)

refs #9178

* Add eslint deps, remove old lint deps
* Add eslint config, remove old lint configs
* Config for server and tests are different
* Tweaked rules to suit us
* Fix linting in codebase - lots of indent changes.
* Fix a real broken test
This commit is contained in:
Hannah Wolfe 2017-11-01 13:44:54 +00:00 committed by GitHub
parent a7fe464d64
commit bcf5a1bc34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 1608 additions and 1032 deletions

300
.eslintrc.json Normal file
View File

@ -0,0 +1,300 @@
{
"env": {
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": "off",
"array-bracket-spacing": [
"error",
"never"
],
"array-callback-return": "off",
"array-element-newline": "off",
"arrow-body-style": "error",
"arrow-parens": [
"error",
"always"
],
"arrow-spacing": [
"error",
{
"after": true,
"before": true
}
],
"block-scoped-var": "error",
"brace-style": [
"error",
"1tbs",
{
"allowSingleLine": true
}
],
"callback-return": "error",
"camelcase": [
"error",
{
"properties": "never"
}
],
"capitalized-comments": "off",
"class-methods-use-this": "off",
"comma-dangle": "error",
"comma-spacing": "error",
"comma-style": [
"error",
"last"
],
"complexity": "off",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "error",
"default-case": "error",
"dot-location": [
"error",
"property"
],
"dot-notation": "error",
"eol-last": "error",
"eqeqeq": "error",
"for-direction": "error",
"func-call-spacing": "error",
"func-name-matching": "off",
"func-names": "off",
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "error",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"indent": [
"error",
4,
{
"SwitchCase": 1
}
],
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "error",
"keyword-spacing": "error",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "off",
"lines-around-directive": "off",
"lines-between-class-members": [
"error",
"always"
],
"max-depth": "error",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-comment-style": "off",
"multiline-ternary": "off",
"new-parens": "error",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "off",
"no-buffer-constructor": "off",
"no-caller": "error",
"no-catch-shadow": "error",
"no-confusing-arrow": "error",
"no-continue": "error",
"no-div-regex": "off",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "error",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "off",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "off",
"no-multi-assign": "off",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "error",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "off",
"no-plusplus": "error",
"no-process-env": "off",
"no-process-exit": "off",
"no-proto": "error",
"no-prototype-builtins": "off",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sync": "off",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "off",
"no-use-before-define": "off",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "off",
"no-useless-constructor": "error",
"no-useless-escape": "off",
"no-useless-rename": "error",
"no-useless-return": "error",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": "error",
"object-curly-newline": [
"error",
{
"consistent": true
}
],
"object-curly-spacing": [
"error",
"never"
],
"object-property-newline": [
"error",
{
"allowMultiplePropertiesPerLine": true
}
],
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": "off",
"padded-blocks": [
"error",
"never"
],
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "off",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": [
"error",
"as-needed"
],
"quotes": ["error", "single"],
"radix": "off",
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": ["error", "always"],
"semi-spacing": "error",
"semi-style": [
"error",
"last"
],
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "error",
"space-before-function-paren": [
"error",
{
"anonymous": "always",
"named": "never"
}
],
"space-in-parens": [
"error",
"never"
],
"space-infix-ops": "error",
"space-unary-ops": "error",
"spaced-comment": "error",
"strict": "off",
"switch-colon-spacing": "error",
"symbol-description": "error",
"template-curly-spacing": [
"error",
"never"
],
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "off",
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yield-star-spacing": "error",
"yoda": "error"
}
}

75
.jscsrc
View File

@ -1,75 +0,0 @@
{
"requireCurlyBraces": [
"if",
"else",
"for",
"while",
"do",
"try",
"catch"
],
"requireSpaceAfterKeywords": [
"if",
"else",
"for",
"while",
"do",
"switch",
"case",
"return",
"try",
"catch",
"function",
"typeof"
],
"requireSpaceBeforeBlockStatements": true,
"requireParenthesesAroundIIFE": true,
"requireSpacesInConditionalExpression": true,
"disallowSpacesInNamedFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionDeclaration": {
"beforeOpeningRoundBrace": true
},
"requireSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"requireMultipleVarDecl": "onevar",
"requireBlocksOnNewline": 1,
"disallowPaddingNewlinesInBlocks": true,
"disallowEmptyBlocks": true,
"disallowSpacesInsideObjectBrackets": "all",
"disallowSpacesInsideArrayBrackets": true,
"disallowSpacesInsideParentheses": true,
"disallowQuotedKeysInObjects": true,
"disallowSpaceAfterObjectKeys": true,
"requireCommaBeforeLineBreak": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowSpaceBeforePostfixUnaryOperators": true,
"disallowSpaceBeforeBinaryOperators": [
","
],
"requireSpaceBeforeBinaryOperators": true,
"requireSpaceAfterBinaryOperators": true,
"requireCamelCaseOrUpperCaseIdentifiers": "ignoreProperties",
"disallowKeywords": [ "with" ],
"disallowMultipleLineBreaks": true,
"validateQuoteMarks": "'",
"validateIndentation": 4,
"disallowMixedSpacesAndTabs": true,
"disallowTrailingWhitespace": true,
"disallowTrailingComma": true,
"disallowKeywordsOnNewLine": [ "else" ],
"requireLineFeedAtFileEnd": true,
"requireCapitalizedConstructors": true,
"safeContextKeyword": ["self"],
"requireDotNotation": true,
"disallowYodaConditions": true,
"jsDoc": {
"checkParamNames": true,
"checkRedundantParams": true,
"requireParamTypes": true
},
"requireSpaceAfterLineComment": true,
"disallowNewlineBeforeBlockStatements": true
}

View File

@ -1,27 +0,0 @@
{
"node": true,
"browser": false,
"strict": false,
"sub": true,
"eqeqeq": true,
"laxbreak": true,
"bitwise": true,
"curly": true,
"forin": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"plusplus": true,
"regexp": true,
"undef": true,
"unused": true,
"mocha": true,
"indent": 4,
"predef": [
"-Promise"
],
"esversion": 6
}

View File

@ -6,9 +6,9 @@
//
// **Debug tip:** If you have any problems with any Grunt tasks, try running them with the `--verbose` command
// jshint unused: false
var overrides = require('./core/server/overrides'),
config = require('./core/server/config'),
require('./core/server/overrides');
var config = require('./core/server/config'),
utils = require('./core/server/utils'),
_ = require('lodash'),
chalk = require('chalk'),
@ -68,8 +68,8 @@ var overrides = require('./core/server/overrides'),
}
},
express: {
files: ['core/ghost-server.js', 'core/server/**/*.js', 'config.*.json', '!config.testing.json'],
tasks: ['express:dev'],
files: ['core/ghost-server.js', 'core/server/**/*.js', 'config.*.json', '!config.testing.json'],
tasks: ['express:dev'],
options: {
nospawn: true,
livereload: true
@ -95,42 +95,31 @@ var overrides = require('./core/server/overrides'),
}
},
// ### grunt-contrib-jshint
// ### grunt-eslint
// Linting rules, run as part of `grunt validate`. See [grunt validate](#validate) and its subtasks for
// more information.
jshint: {
options: {
jshintrc: '.jshintrc'
},
server: [
'*.js',
'!config.*.json', // note: i added this, do we want this linted?
'core/*.js',
'core/server/**/*.js',
'core/test/**/*.js',
'!core/test/coverage/**',
'!core/server/public/**/*.js'
]
},
jscs: {
options: {
config: true
},
eslint: {
server: {
files: {
src: [
'*.js',
'!config.*.json', // note: i added this, do we want this linted?
'core/*.js',
'core/server/**/*.js',
'core/test/**/*.js',
'!core/test/coverage/**',
'!core/server/public/**/*.js'
]
}
options: {
config: '.eslintrc.json'
},
src: [
'*.js',
'core/*.js',
'core/server/*.js',
'core/server/**/*.js',
'!core/server/public/**/*.js'
]
},
test: {
options: {
config: './core/test/.eslintrc.json'
},
src: [
'core/test/*.js',
'core/test/**/*.js',
'!core/test/coverage/**'
]
}
},
@ -403,7 +392,7 @@ var overrides = require('./core/server/overrides'),
grunt.registerTask('help',
'Outputs help information if you type `grunt help` instead of `grunt --help`',
function () {
console.log('Type `grunt --help` to get the details of available grunt tasks.');
grunt.log.writeln('Type `grunt --help` to get the details of available grunt tasks.');
});
// ### Documentation
@ -516,9 +505,9 @@ var overrides = require('./core/server/overrides'),
// ### Lint
//
// `grunt lint` will run the linter and the code style checker so you can make sure your code is pretty
grunt.registerTask('lint', 'Run the code style checks and linter for server',
['jshint', 'jscs']
// `grunt lint` will run the linter
grunt.registerTask('lint', 'Run the code style checks for server & tests',
['eslint']
);
// ### test-setup *(utility)(
@ -630,11 +619,11 @@ var overrides = require('./core/server/overrides'),
grunt.registerTask('master-warn',
'Outputs a warning to runners of grunt prod, that master shouldn\'t be used for live blogs',
function () {
console.log(chalk.red(
grunt.log.writeln(chalk.red(
'Use the ' + chalk.bold('stable') + ' branch for live blogs. '
+ chalk.bold.underline('Never') + ' master!'
));
console.log('>', 'Always two there are, no more, no less. A master and a ' + chalk.bold('stable') + '.');
grunt.log.writeln('>', 'Always two there are, no more, no less. A master and a ' + chalk.bold('stable') + '.');
});
// ## Building assets

View File

@ -40,9 +40,8 @@ exports.createAdapter = function (options) {
// CASE: only throw error if module does exist
if (err.code !== 'MODULE_NOT_FOUND') {
return Promise.reject(new errors.IncorrectUsageError({err: err}));
}
// CASE: if module not found it can be an error within the adapter (cannot find bluebird for example)
else if (err.code === 'MODULE_NOT_FOUND' && err.message.indexOf(contentPath + activeAdapter) === -1) {
} else if (err.code === 'MODULE_NOT_FOUND' && err.message.indexOf(contentPath + activeAdapter) === -1) {
return Promise.reject(new errors.IncorrectUsageError({err: err, help: 'Please check the imports are valid in ' + contentPath + activeAdapter}));
}
}

View File

@ -1,5 +1,3 @@
// jscs:disable requireMultipleVarDecl
'use strict';
// # Local File System Image Storage module
@ -18,7 +16,6 @@ var serveStatic = require('express').static,
StorageBase = require('ghost-storage-base');
class LocalFileStore extends StorageBase {
constructor() {
super();

View File

@ -37,16 +37,14 @@ function getStorage() {
help: 'Add \'use strict\'; on top of your adapter.',
err: err
});
}
// CASE: if module not found it can be an error within the adapter (cannot find bluebird for example)
else if (err.code === 'MODULE_NOT_FOUND' && err.message.indexOf(config.getContentPath('storage') + storageChoice) === -1) {
} else if (err.code === 'MODULE_NOT_FOUND' && err.message.indexOf(config.getContentPath('storage') + storageChoice) === -1) {
throw new errors.IncorrectUsageError({
message: 'We have detected an error in your custom storage adapter.',
err: err
});
}
// CASE: only throw error if module does exist
else if (err.code !== 'MODULE_NOT_FOUND') {
} else if (err.code !== 'MODULE_NOT_FOUND') {
throw new errors.IncorrectUsageError({
message: 'We have detected an unknown error in your custom storage adapter.',
err: err

View File

@ -11,7 +11,6 @@ var debug = require('ghost-ignition').debug('admin:controller'),
// Path: /ghost/
// Method: GET
module.exports = function adminController(req, res) {
/*jslint unparam:true*/
debug('index called');
updateCheck().then(function then() {
@ -27,7 +26,11 @@ module.exports = function adminController(req, res) {
location: 'upgrade.new-version-available',
dismissible: false,
message: i18n.t('notices.controllers.newVersionAvailable',
{version: updateVersion, link: '<a href="https://docs.ghost.org/docs/upgrade" target="_blank">Click here</a>'})};
{
version: updateVersion,
link: '<a href="https://docs.ghost.org/docs/upgrade" target="_blank">Click here</a>'
})
};
return api.notifications.browse({context: {internal: true}}).then(function then(results) {
if (!_.some(results.notifications, {message: notification.message})) {

View File

@ -5,7 +5,6 @@ var debug = require('ghost-ignition').debug('admin:serviceworker'),
// Path: /ghost/sw.js|sw-registration.js
// Method: GET
module.exports = function adminController(req, res) {
/*jslint unparam:true*/
debug('serviceworker called');
var sw = path.join(__dirname, '..', '..', 'built', 'assets', 'sw.js'),

View File

@ -25,11 +25,11 @@ function getAboutConfig() {
function getBaseConfig() {
return {
useGravatar: !config.isPrivacyDisabled('useGravatar'),
publicAPI: config.get('publicAPI') === true,
blogUrl: apiUtils.url.urlFor('home', true),
blogTitle: settingsCache.get('title'),
routeKeywords: config.get('routeKeywords'),
useGravatar: !config.isPrivacyDisabled('useGravatar'),
publicAPI: config.get('publicAPI') === true,
blogUrl: apiUtils.url.urlFor('home', true),
blogTitle: settingsCache.get('title'),
routeKeywords: config.get('routeKeywords'),
clientExtensions: config.get('clientExtensions')
};
}

View File

@ -123,9 +123,9 @@ db = {
return Promise.each(collections, function then(Collection) {
return Collection.invokeThen('destroy', queryOpts);
}).return({db: []})
.catch(function (err) {
throw new errors.GhostError({err: err});
});
.catch(function (err) {
throw new errors.GhostError({err: err});
});
}
tasks = [

View File

@ -93,7 +93,7 @@ notifications = {
id: ObjectId.generate()
});
existingNotification = _.find(notificationsStore, {message:notification.message});
existingNotification = _.find(notificationsStore, {message: notification.message});
if (!existingNotification) {
notificationsStore.push(notification);

View File

@ -59,8 +59,10 @@ exports.publishPost = function publishPost(object, options) {
return Promise.reject(new errors.NotFoundError({message: i18n.t('errors.api.job.publishInThePast')}));
}
return postsAPI.edit({
posts: [{status: 'published'}]},
return postsAPI.edit(
{
posts: [{status: 'published'}]
},
_.pick(cleanOptions, ['context', 'id', 'transacting', 'forUpdate', 'opts'])
);
});

View File

@ -10,8 +10,9 @@ var Promise = require('bluebird'),
settingsCache = require('../settings/cache'),
docName = 'settings',
settings,
settingsFilter,
settingsResult,
canEditAllSettings,
canEditAllSettings;
// ## Helpers

View File

@ -25,26 +25,26 @@ var Promise = require('bluebird'),
ampHTML;
allowedAMPTags = ['html', 'body', 'article', 'section', 'nav', 'aside', 'h1', 'h2',
'h3', 'h4', 'h5', 'h6', 'header', 'footer', 'address', 'p', 'hr',
'pre', 'blockquote', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'figure',
'figcaption', 'div', 'main', 'a', 'em', 'strong', 'small', 's', 'cite',
'q', 'dfn', 'abbr', 'data', 'time', 'code', 'var', 'samp', 'kbd', 'sub',
'sup', 'i', 'b', 'u', 'mark', 'ruby', 'rb', 'rt', 'rtc', 'rp', 'bdi',
'bdo', 'span', 'br', 'wbr', 'ins', 'del', 'source', 'track', 'svg', 'g',
'path', 'glyph', 'glyphref', 'marker', 'view', 'circle', 'line', 'polygon',
'polyline', 'rect', 'text', 'textpath', 'tref', 'tspan', 'clippath',
'filter', 'lineargradient', 'radialgradient', 'mask', 'pattern', 'vkern',
'hkern', 'defs', 'stop', 'use', 'foreignobject', 'symbol', 'desc', 'title',
'table', 'caption', 'colgroup', 'col', 'tbody', 'thead', 'tfoot', 'tr', 'td',
'th', 'button', 'noscript', 'acronym', 'center', 'dir', 'hgroup', 'listing',
'multicol', 'nextid', 'nobr', 'spacer', 'strike', 'tt', 'xmp', 'amp-img',
'amp-video', 'amp-ad', 'amp-embed', 'amp-anim', 'amp-iframe', 'amp-pixel',
'amp-audio', 'O:P'];
'h3', 'h4', 'h5', 'h6', 'header', 'footer', 'address', 'p', 'hr',
'pre', 'blockquote', 'ol', 'ul', 'li', 'dl', 'dt', 'dd', 'figure',
'figcaption', 'div', 'main', 'a', 'em', 'strong', 'small', 's', 'cite',
'q', 'dfn', 'abbr', 'data', 'time', 'code', 'var', 'samp', 'kbd', 'sub',
'sup', 'i', 'b', 'u', 'mark', 'ruby', 'rb', 'rt', 'rtc', 'rp', 'bdi',
'bdo', 'span', 'br', 'wbr', 'ins', 'del', 'source', 'track', 'svg', 'g',
'path', 'glyph', 'glyphref', 'marker', 'view', 'circle', 'line', 'polygon',
'polyline', 'rect', 'text', 'textpath', 'tref', 'tspan', 'clippath',
'filter', 'lineargradient', 'radialgradient', 'mask', 'pattern', 'vkern',
'hkern', 'defs', 'stop', 'use', 'foreignobject', 'symbol', 'desc', 'title',
'table', 'caption', 'colgroup', 'col', 'tbody', 'thead', 'tfoot', 'tr', 'td',
'th', 'button', 'noscript', 'acronym', 'center', 'dir', 'hgroup', 'listing',
'multicol', 'nextid', 'nobr', 'spacer', 'strike', 'tt', 'xmp', 'amp-img',
'amp-video', 'amp-ad', 'amp-embed', 'amp-anim', 'amp-iframe', 'amp-pixel',
'amp-audio', 'O:P'];
allowedAMPAttributes = {
'*': ['itemid', 'itemprop', 'itemref', 'itemscope', 'itemtype', 'accesskey', 'class', 'dir', 'draggable',
'id', 'lang', 'tabindex', 'title', 'translate', 'aria-*', 'role', 'placeholder', 'fallback', 'lightbox',
'overflow', 'amp-access', 'amp-access-*', 'i-amp-access-id'],
'id', 'lang', 'tabindex', 'title', 'translate', 'aria-*', 'role', 'placeholder', 'fallback', 'lightbox',
'overflow', 'amp-access', 'amp-access-*', 'i-amp-access-id'],
h1: ['align'],
h2: ['align'],
h3: ['align'],
@ -105,14 +105,14 @@ allowedAMPAttributes = {
'amp-img': ['media', 'noloading', 'alt', 'attribution', 'placeholder', 'src', 'srcset', 'width', 'height', 'layout'],
'amp-pixel': ['src'],
'amp-video': ['src', 'srcset', 'media', 'noloading', 'width', 'height', 'layout', 'alt', 'attribution',
'autoplay', 'controls', 'loop', 'muted', 'poster', 'preload'],
'autoplay', 'controls', 'loop', 'muted', 'poster', 'preload'],
'amp-embed': ['media', 'noloading', 'width', 'height', 'layout', 'type', 'data-*', 'json'],
'amp-ad': ['media', 'noloading', 'width', 'height', 'layout', 'type', 'data-*', 'json'],
// extended components we support
'amp-anim': ['media', 'noloading', 'alt', 'attribution', 'placeholder', 'src', 'srcset', 'width', 'height', 'layout'],
'amp-audio': ['src', 'width', 'height', 'autoplay', 'loop', 'muted', 'controls'],
'amp-iframe': ['src', 'srcdoc', 'width', 'height', 'layout', 'frameborder', 'allowfullscreen', 'allowtransparency',
'sandbox', 'referrerpolicy']
'sandbox', 'referrerpolicy']
};
function getAmperizeHTML(html, post) {

View File

@ -1,12 +1,12 @@
var SimpleDom = require('simple-dom'),
tokenizer = require('simple-html-tokenizer').tokenize,
var SimpleDom = require('simple-dom'),
tokenizer = require('simple-html-tokenizer').tokenize,
parser;
module.exports = {
name: 'card-html',
type: 'dom',
render(opts) {
parser = new SimpleDom.HTMLParser(tokenizer, opts.env.dom, SimpleDom.voidMap);
return parser.parse('<div class="kg-card-html">' + opts.payload.html + '</div>');
}
};
name: 'card-html',
type: 'dom',
render(opts) {
parser = new SimpleDom.HTMLParser(tokenizer, opts.env.dom, SimpleDom.voidMap);
return parser.parse('<div class="kg-card-html">' + opts.payload.html + '</div>');
}
};

View File

@ -1,19 +1,19 @@
module.exports = {
name: 'card-markdown',
type: 'dom',
render: function (opts) {
var markdownConverter = require('../../../utils/markdown-converter'),
html, element;
name: 'card-markdown',
type: 'dom',
render: function (opts) {
var markdownConverter = require('../../../utils/markdown-converter'),
html, element;
// convert markdown to HTML ready for insertion into dom
html = '<div class="kg-card-markdown">'
+ markdownConverter.render(opts.payload.markdown || '')
+ '</div>';
// convert markdown to HTML ready for insertion into dom
html = '<div class="kg-card-markdown">'
+ markdownConverter.render(opts.payload.markdown || '')
+ '</div>';
// use the SimpleDOM document to create a raw HTML section.
// avoids parsing/rendering of potentially broken or unsupported HTML
element = opts.env.dom.createRawHTMLSection(html);
// use the SimpleDOM document to create a raw HTML section.
// avoids parsing/rendering of potentially broken or unsupported HTML
element = opts.env.dom.createRawHTMLSection(html);
return element;
}
};
return element;
}
};

View File

@ -2,16 +2,14 @@
// Usage: `{{input_password}}`
//
// Password input used on private.hbs for password-protected blogs
//
// We use the name input_password to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
// (less) dirty requires
var proxy = require('../../../../helpers/proxy'),
SafeString = proxy.SafeString,
templates = proxy.templates;
module.exports = function input_password(options) {
// We use the name input_password to match the helper for consistency:
module.exports = function input_password(options) { // eslint-disable-line camelcase
options = options || {};
options.hash = options.hash || {};

View File

@ -2,16 +2,14 @@
// Usage: `{{input_email}}`
//
// Used by `{{subscribe_form}}`
//
// We use the name input_email to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
// (less) dirty requires
var proxy = require('../../../../helpers/proxy'),
SafeString = proxy.SafeString,
templates = proxy.templates;
module.exports = function input_email(options) {
// We use the name input_email to match the helper for consistency:
module.exports = function input_email(options) { // eslint-disable-line camelcase
options = options || {};
options.hash = options.hash || {};

View File

@ -1,8 +1,5 @@
// # Subscribe Form Helper
// Usage: `{{subscribe_form}}`
//
// We use the name subscribe_form to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var _ = require('lodash'),
// (Less) dirty requires
@ -38,7 +35,8 @@ subscribeScript =
'})(window,document,\'querySelector\',\'value\');' +
'</script>';
module.exports = function subscribe_form(options) {
// We use the name subscribe_form to match the helper for consistency:
module.exports = function subscribe_form(options) { // eslint-disable-line camelcase
var root = options.data.root,
data = _.merge({}, options.hash, _.pick(root, params), {
action: url.urlJoin('/', url.getSubdir(), config.get('routeKeywords').subscribe, '/'),

View File

@ -29,8 +29,6 @@ function controller(req, res) {
* For success cases, we don't have to worry, because then the input contained a valid email address.
*/
function errorHandler(error, req, res, next) {
/*jshint unused:false */
req.body.email = '';
if (error.statusCode !== 404) {

View File

@ -86,7 +86,7 @@ function processQuery(query, slugParam) {
function fetchData(channelOptions) {
// @TODO improve this further
var pageOptions = channelOptions.isRSS ?
{options: channelOptions.postOptions} : fetchPostsPerPage(channelOptions.postOptions),
{options: channelOptions.postOptions} : fetchPostsPerPage(channelOptions.postOptions),
postQuery,
props = {};

View File

@ -11,8 +11,7 @@ JSONHandler = {
contentTypes: ['application/octet-stream', 'application/json'],
directories: [],
loadFile: function (files, startDir) {
/*jshint unused:false */
loadFile: function (files, startDir) { // eslint-disable-line no-unused-vars
// @TODO: Handle multiple JSON files
var filePath = files[0].path;

View File

@ -87,7 +87,6 @@ MarkdownHandler = {
directories: [],
loadFile: function (files, startDir) {
/*jshint unused:false */
var startDirRegex = startDir ? new RegExp('^' + startDir + '/') : new RegExp(''),
posts = [],
ops = [];

View File

@ -132,8 +132,8 @@ class PostsImporter extends BaseImporter {
version: '0.3.1',
markups: [],
atoms: [],
cards: [['card-markdown',{cardName: 'card-markdown',markdown: mobileDocContent}]],
sections:[[10,0]]
cards: [['card-markdown', {cardName: 'card-markdown', markdown: mobileDocContent}]],
sections: [[10, 0]]
});
}
}

View File

@ -8,7 +8,6 @@ function getExcerpt(html, truncateOptions) {
// Strip other html
excerpt = excerpt.replace(/<\/?[^>]+>/gi, '');
excerpt = excerpt.replace(/(\r\n|\n|\r)+/gm, ' ');
/*jslint regexp:false */
if (!truncateOptions.words && !truncateOptions.characters) {
truncateOptions.words = 50;

View File

@ -28,50 +28,50 @@ var Promise = require('bluebird'),
function getMetaData(data, root) {
var metaData = {
url: getUrl(data, true),
canonicalUrl: getCanonicalUrl(data),
ampUrl: getAmpUrl(data),
previousUrl: getPaginatedUrl('prev', data, true),
nextUrl: getPaginatedUrl('next', data, true),
authorUrl: getAuthorUrl(data, true),
rssUrl: getRssUrl(data, true),
metaTitle: getTitle(data, root),
metaDescription: getDescription(data, root) || null,
coverImage: {
url: getCoverImage(data, true)
url: getUrl(data, true),
canonicalUrl: getCanonicalUrl(data),
ampUrl: getAmpUrl(data),
previousUrl: getPaginatedUrl('prev', data, true),
nextUrl: getPaginatedUrl('next', data, true),
authorUrl: getAuthorUrl(data, true),
rssUrl: getRssUrl(data, true),
metaTitle: getTitle(data, root),
metaDescription: getDescription(data, root) || null,
coverImage: {
url: getCoverImage(data, true)
},
authorImage: {
url: getAuthorImage(data, true)
},
ogImage: {
url: getOgImage(data, true)
},
ogTitle: getTitle(data, root, {property: 'og'}),
ogDescription: getDescription(data, root, {property: 'og'}),
twitterImage: getTwitterImage(data, true),
twitterTitle: getTitle(data, root, {property: 'twitter'}),
twitterDescription: getDescription(data, root, {property: 'twitter'}),
authorFacebook: getAuthorFacebook(data),
creatorTwitter: getCreatorTwitter(data),
keywords: getKeywords(data),
publishedDate: getPublishedDate(data),
modifiedDate: getModifiedDate(data),
ogType: getOgType(data),
// @TODO: pass into each meta helper - wrap each helper
blog: {
title: settingsCache.get('title'),
description: settingsCache.get('description'),
url: utils.url.urlFor('home', true),
facebook: settingsCache.get('facebook'),
twitter: settingsCache.get('twitter'),
timezone: settingsCache.get('active_timezone'),
navigation: settingsCache.get('navigation'),
icon: settingsCache.get('icon'),
cover_image: settingsCache.get('cover_image'),
logo: getBlogLogo(),
amp: settingsCache.get('amp')
}
},
authorImage: {
url: getAuthorImage(data, true)
},
ogImage: {
url: getOgImage(data, true)
},
ogTitle: getTitle(data, root, {property: 'og'}),
ogDescription: getDescription(data, root, {property: 'og'}),
twitterImage: getTwitterImage(data, true),
twitterTitle: getTitle(data, root, {property: 'twitter'}),
twitterDescription: getDescription(data, root, {property: 'twitter'}),
authorFacebook: getAuthorFacebook(data),
creatorTwitter: getCreatorTwitter(data),
keywords: getKeywords(data),
publishedDate: getPublishedDate(data),
modifiedDate: getModifiedDate(data),
ogType: getOgType(data),
// @TODO: pass into each meta helper - wrap each helper
blog: {
title: settingsCache.get('title'),
description: settingsCache.get('description'),
url: utils.url.urlFor('home', true),
facebook: settingsCache.get('facebook'),
twitter: settingsCache.get('twitter'),
timezone: settingsCache.get('active_timezone'),
navigation: settingsCache.get('navigation'),
icon: settingsCache.get('icon'),
cover_image: settingsCache.get('cover_image'),
logo: getBlogLogo(),
amp: settingsCache.get('amp')
}
},
customExcerpt,
metaDescription,
fallbackExcerpt;

View File

@ -1,4 +1,4 @@
var _ = require('lodash'),
var _ = require('lodash'),
config = require('../../config'),
utils = require('../../utils');
@ -30,7 +30,7 @@ function getPaginatedUrl(page, data, absolute) {
// baseUrl can be undefined, if there was nothing preceding the pagePath (e.g. first page of the index channel)
newRelativeUrl = baseUrl ? utils.url.urlJoin(baseUrl, newRelativeUrl) : newRelativeUrl;
return utils.url.urlFor({relativeUrl: newRelativeUrl, secure: data.secure}, absolute);
return utils.url.urlFor({relativeUrl: newRelativeUrl, secure: data.secure}, absolute);
}
module.exports = getPaginatedUrl;

View File

@ -84,8 +84,8 @@ function getPostSchema(metaData, data) {
url: metaData.authorUrl,
sameAs: trimSameAs(data, 'post'),
description: data.post.author.metaDescription ?
escapeExpression(data.post.author.metaDescription) :
null
escapeExpression(data.post.author.metaDescription) :
null
},
headline: escapeExpression(metaData.metaTitle),
url: metaData.url,
@ -120,8 +120,8 @@ function getHomeSchema(metaData) {
'@id': metaData.blog.url || null
},
description: metaData.metaDescription ?
escapeExpression(metaData.metaDescription) :
null
escapeExpression(metaData.metaDescription) :
null
};
return trimSchema(schema);
}
@ -143,8 +143,8 @@ function getTagSchema(metaData, data) {
'@id': metaData.blog.url || null
},
description: metaData.metaDescription ?
escapeExpression(metaData.metaDescription) :
null
escapeExpression(metaData.metaDescription) :
null
};
return trimSchema(schema);
@ -163,8 +163,8 @@ function getAuthorSchema(metaData, data) {
'@id': metaData.blog.url || null
},
description: metaData.metaDescription ?
escapeExpression(metaData.metaDescription) :
null
escapeExpression(metaData.metaDescription) :
null
};
return trimSchema(schema);

View File

@ -1,5 +1,5 @@
var sqlite3 = require('./sqlite3'),
mysql = require('./mysql');
mysql = require('./mysql');
module.exports = {
sqlite3: sqlite3,

View File

@ -1,4 +1,4 @@
var _ = require('lodash'),
var _ = require('lodash'),
db = require('../../../data/db'),
// private
@ -18,7 +18,9 @@ doRawAndFlatten = function doRaw(query, transaction, flattenFn) {
getTables = function getTables(transaction) {
return doRawAndFlatten('show tables', transaction, function (response) {
return _.map(response[0], function (entry) { return _.values(entry); });
return _.map(response[0], function (entry) {
return _.values(entry);
});
});
};
@ -50,7 +52,7 @@ checkPostTable = function checkPostTable(transaction) {
module.exports = {
checkPostTable: checkPostTable,
getTables: getTables,
getTables: getTables,
getIndexes: getIndexes,
getColumns: getColumns
};

View File

@ -1,4 +1,4 @@
var _ = require('lodash'),
var _ = require('lodash'),
db = require('../../../data/db'),
// private
@ -39,7 +39,7 @@ getColumns = function getColumns(table, transaction) {
};
module.exports = {
getTables: getTables,
getTables: getTables,
getIndexes: getIndexes,
getColumns: getColumns
};

View File

@ -1,4 +1,4 @@
var _ = require('lodash'),
var _ = require('lodash'),
db = require('../../../data/db'),
// private
@ -41,7 +41,7 @@ getColumns = function getColumns(table, transaction) {
};
module.exports = {
getTables: getTables,
getTables: getTables,
getIndexes: getIndexes,
getColumns: getColumns
};

View File

@ -46,7 +46,6 @@ function characterOccurance(stringToTest) {
_.forIn(chars, function (charCount) {
if (charCount >= allowedOccurancy) {
valid = false;
return;
}
});
@ -98,15 +97,15 @@ validatePassword = function validatePassword(password, email, blogTitle) {
disallowedPasswords = ['password', 'ghost', 'passw0rd'],
blogUrl = utils.urlFor('home', true),
badPasswords = [
'1234567890',
'qwertyuiop',
'qwertzuiop',
'asdfghjkl;',
'abcdefghij',
'0987654321',
'1q2w3e4r5t',
'12345asdfg'
];
'1234567890',
'qwertyuiop',
'qwertzuiop',
'asdfghjkl;',
'abcdefghij',
'0987654321',
'1q2w3e4r5t',
'12345asdfg'
];
blogTitle = blogTitle ? blogTitle : settingsCache.get('title');
blogUrl = blogUrl.replace(/^http(s?):\/\//, '');
@ -195,21 +194,34 @@ validateSchema = function validateSchema(tableName, model) {
if (schema[tableName][columnKey].hasOwnProperty('maxlength')) {
if (!validator.isLength(strVal, 0, schema[tableName][columnKey].maxlength)) {
message = i18n.t('notices.data.validation.index.valueExceedsMaxLength',
{tableName: tableName, columnKey: columnKey, maxlength: schema[tableName][columnKey].maxlength});
validationErrors.push(new errors.ValidationError({message: message, context: tableName + '.' + columnKey}));
{
tableName: tableName,
columnKey: columnKey,
maxlength: schema[tableName][columnKey].maxlength
});
validationErrors.push(new errors.ValidationError({
message: message,
context: tableName + '.' + columnKey
}));
}
}
// check validations objects
if (schema[tableName][columnKey].hasOwnProperty('validations')) {
if (schema[tableName][columnKey].hasOwnProperty('validations')) {
validationErrors = validationErrors.concat(validate(strVal, columnKey, schema[tableName][columnKey].validations));
}
// check type
if (schema[tableName][columnKey].hasOwnProperty('type')) {
if (schema[tableName][columnKey].hasOwnProperty('type')) {
if (schema[tableName][columnKey].type === 'integer' && !validator.isInt(strVal)) {
message = i18n.t('notices.data.validation.index.valueIsNotInteger', {tableName: tableName, columnKey: columnKey});
validationErrors.push(new errors.ValidationError({message: message, context: tableName + '.' + columnKey}));
message = i18n.t('notices.data.validation.index.valueIsNotInteger', {
tableName: tableName,
columnKey: columnKey
});
validationErrors.push(new errors.ValidationError({
message: message,
context: tableName + '.' + columnKey
}));
}
}
}

View File

@ -9,7 +9,6 @@ function GhostError(options) {
errors.IgnitionError.call(this, options);
}
// jscs:disable
var ghostErrors = {
DataExportError: function DataExportError(options) {
GhostError.call(this, _.merge({
@ -58,13 +57,13 @@ var ghostErrors = {
DisabledFeatureError: function DisabledFeatureError(options) {
GhostError.call(this, _.merge({
statusCode: 409,
errorType: 'DisabledFeatureError',
errorType: 'DisabledFeatureError'
}, options));
},
UpdateCollisionError: function UpdateCollisionError(options) {
GhostError.call(this, _.merge({
statusCode: 409,
errorType: 'UpdateCollisionError',
errorType: 'UpdateCollisionError'
}, options));
}
};

View File

@ -2,15 +2,12 @@
// Usage: `{{body_class}}`
//
// Output classes for the body element
//
// We use the name body_class to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
_ = require('lodash'),
SafeString = proxy.SafeString;
module.exports = function body_class(options) {
// We use the name body_class to match the helper for consistency:
module.exports = function body_class(options) { // eslint-disable-line camelcase
var classes = [],
context = options.data.root.context,
post = this.post,

View File

@ -2,15 +2,12 @@
// Usage: `{{facebook_url}}` or `{{facebook_url author.facebook}}`
//
// Output a url for a twitter username
//
// We use the name facebook_url to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
socialUrls = proxy.socialUrls,
findKey = proxy.utils.findKey;
module.exports = function facebook_url(username, options) {
// We use the name facebook_url to match the helper for consistency:
module.exports = function facebook_url(username, options) { // eslint-disable-line camelcase
if (!options) {
options = username;
username = findKey('facebook', this, options.data.blog);

View File

@ -71,15 +71,14 @@ module.exports = function foreach(items, options) {
}
output = output + fn(items[field], {
data: data,
blockParams: hbsUtils.blockParams([items[field], field], [contextPath + field, null])
});
data: data,
blockParams: hbsUtils.blockParams([items[field], field], [contextPath + field, null])
});
}
function iterateCollection(context) {
// Context is all posts on the blog
var count = 1,
current = 1;
var current = 1;
// For each post, if it is a post number that fits within the from and to
// send the key to execIteration to set to be added to the page
@ -92,7 +91,6 @@ module.exports = function foreach(items, options) {
if (current <= to) {
execIteration(key, current - 1, current === to);
}
count += 1;
current += 1;
});
}

View File

@ -2,16 +2,14 @@
// Usage: `{{ghost_foot}}`
//
// Outputs scripts and other assets at the bottom of a Ghost theme
//
// We use the name ghost_foot to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
_ = require('lodash'),
SafeString = proxy.SafeString,
filters = proxy.filters,
settingsCache = proxy.settingsCache;
module.exports = function ghost_foot(options) {
// We use the name ghost_foot to match the helper for consistency:
module.exports = function ghost_foot(options) { // eslint-disable-line camelcase
var foot = [],
globalCodeinjection = settingsCache.get('ghost_foot'),
postCodeinjection = options.data.root && options.data.root.post ? options.data.root.post.codeinjection_foot : null;

View File

@ -2,10 +2,6 @@
// Usage: `{{ghost_head}}`
//
// Outputs scripts and other assets at the top of a Ghost theme
//
// We use the name ghost_head to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
_ = require('lodash'),
debug = require('ghost-ignition').debug('ghost_head'),
@ -93,7 +89,8 @@ function getAjaxHelper(clientId, clientSecret) {
* `blog`, `labs` and `config` are the templateOptions, search for `hbs.updateTemplateOptions` in the code base.
* Also see how the root object get's created, https://github.com/wycats/handlebars.js/blob/v4.0.6/lib/handlebars/runtime.js#L259
*/
module.exports = function ghost_head(options) {
// We use the name ghost_head to match the helper for consistency:
module.exports = function ghost_head(options) { // eslint-disable-line camelcase
debug('begin');
// if server error page do nothing

View File

@ -14,11 +14,11 @@ function evaluateTagList(expr, tags) {
return v.trim();
}).reduce(function (p, c) {
return p || (_.findIndex(tags, function (item) {
// Escape regex special characters
item = item.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&');
item = new RegExp('^' + item + '$', 'i');
return item.test(c);
}) !== -1);
// Escape regex special characters
item = item.replace(/[\-\/\\\^$*+?.()|\[\]{}]/g, '\\$&');
item = new RegExp('^' + item + '$', 'i');
return item.test(c);
}) !== -1);
}, false);
}

View File

@ -31,9 +31,8 @@ module.exports = function imgUrl(attr, options) {
if (attr) {
return url.urlFor('image', {image: attr}, absolute);
} else {
// CASE: if you pass e.g. cover_image, but it is not set, then attr is null!
// in this case we don't show a warning
return;
}
// CASE: if you pass e.g. cover_image, but it is not set, then attr is null!
// in this case we don't show a warning
};

View File

@ -2,17 +2,12 @@
// Usage: `{{meta_description}}`
//
// Page description used for sharing and SEO
//
// We use the name meta_description to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
getMetaDataDescription = proxy.metaData.getMetaDataDescription;
function meta_description(options) {
// We use the name meta_description to match the helper for consistency:
module.exports = function meta_description(options) { // eslint-disable-line camelcase
options = options || {};
return getMetaDataDescription(this, options.data.root) || '';
}
module.exports = meta_description;
};

View File

@ -2,15 +2,10 @@
// Usage: `{{meta_title}}`
//
// Page title used for sharing and SEO
//
// We use the name meta_title to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
getMetaDataTitle = proxy.metaData.getMetaDataTitle;
function meta_title(options) {
// We use the name meta_title to match the helper for consistency:
module.exports = function meta_title(options) { // eslint-disable-line camelcase
return getMetaDataTitle(this, options.data.root);
}
module.exports = meta_title;
};

View File

@ -3,15 +3,12 @@
// *Usage example:*
// `{{page_url 2}}`
//
// Returns the URL for the page specified in the current object
// context.
//
// We use the name page_url to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
// Returns the URL for the page specified in the current object context.
var proxy = require('./proxy'),
getPaginatedUrl = proxy.metaData.getPaginatedUrl;
module.exports = function page_url(page, options) {
// We use the name page_url to match the helper for consistency:
module.exports = function page_url(page, options) { // eslint-disable-line camelcase
if (!options) {
options = page;
page = 1;

View File

@ -10,7 +10,6 @@ var proxy = require('./proxy'),
pagination;
pagination = function (options) {
/*jshint unused:false*/
if (!_.isObject(this.pagination) || _.isFunction(this.pagination)) {
throw new errors.IncorrectUsageError({
message: i18n.t('warnings.helpers.pagination.invalidData')

View File

@ -2,15 +2,12 @@
// Usage: `{{post_class}}`
//
// Output classes for the body element
//
// We use the name body_class to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
_ = require('lodash'),
SafeString = proxy.SafeString;
module.exports = function post_class() {
// We use the name post_class to match the helper for consistency:
module.exports = function post_class() { // eslint-disable-line camelcase
var classes = ['post'],
tags = this.post && this.post.tags ? this.post.tags : this.tags || [],
featured = this.post && this.post.featured ? this.post.featured : this.featured || false,

View File

@ -29,7 +29,7 @@ buildApiOptions = function buildApiOptions(options, post) {
limit: 1,
// This line deliberately uses double quotes because GQL cannot handle either double quotes
// or escaped singles, see TryGhost/GQL#34
filter: "slug:-" + slug + "+published_at:" + op + "'" + publishedAt + "'", // jscs:ignore
filter: "slug:-" + slug + "+published_at:" + op + "'" + publishedAt + "'" // eslint-disable-line quotes
};
if (_.get(options, 'hash.in')) {

View File

@ -2,15 +2,12 @@
// Usage: `{{twitter_url}}` or `{{twitter_url author.twitter}}`
//
// Output a url for a twitter username
//
// We use the name twitter_url to match the helper for consistency:
// jscs:disable requireCamelCaseOrUpperCaseIdentifiers
var proxy = require('./proxy'),
socialUrls = proxy.socialUrls,
findKey = proxy.utils.findKey;
module.exports = function twitter_url(username, options) {
// We use the name twitter_url to match the helper for consistency:
module.exports = function twitter_url(username, options) { // eslint-disable-line camelcase
if (!options) {
options = username;
username = findKey('twitter', this, options.data.blog);

View File

@ -53,25 +53,25 @@ globalBlock = function globalBlock() {
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
tablename: 'brute',
createTable: false,
knex: db.knex
});
globalBlockInstance = globalBlockInstance || new ExpressBrute(store,
_.extend({
attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
{rfa: spamGlobalBlock.freeRetries + 1 || 5, rfp: spamGlobalBlock.lifetime || 60 * 60}),
help: i18n.t('errors.middleware.spamprevention.tooManyAttempts')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamGlobalBlock, spamConfigKeys))
);
_.extend({
attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
{rfa: spamGlobalBlock.freeRetries + 1 || 5, rfp: spamGlobalBlock.lifetime || 60 * 60}),
help: i18n.t('errors.middleware.spamprevention.tooManyAttempts')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamGlobalBlock, spamConfigKeys))
);
return globalBlockInstance;
};
@ -82,26 +82,26 @@ globalReset = function globalReset() {
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
tablename: 'brute',
createTable: false,
knex: db.knex
});
globalResetInstance = globalResetInstance || new ExpressBrute(store,
_.extend({
attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) {
// TODO use i18n again
return next(new errors.TooManyRequestsError({
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
{rfa: spamGlobalReset.freeRetries + 1 || 5, rfp: spamGlobalReset.lifetime || 60 * 60}),
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.context')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamGlobalReset, spamConfigKeys))
);
_.extend({
attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) {
// TODO use i18n again
return next(new errors.TooManyRequestsError({
message: 'Too many attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.error',
{rfa: spamGlobalReset.freeRetries + 1 || 5, rfp: spamGlobalReset.lifetime || 60 * 60}),
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordIp.context')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamGlobalReset, spamConfigKeys))
);
return globalResetInstance;
};
@ -116,25 +116,25 @@ userLogin = function userLogin() {
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
tablename: 'brute',
createTable: false,
knex: db.knex
});
userLoginInstance = userLoginInstance || new ExpressBrute(store,
_.extend({
attachResetToRequest: true,
failCallback: function (req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: 'Too many sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
// TODO add more options to i18n
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context'),
help: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamUserLogin, spamConfigKeys))
);
_.extend({
attachResetToRequest: true,
failCallback: function (req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: 'Too many sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
// TODO add more options to i18n
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context'),
help: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamUserLogin, spamConfigKeys))
);
return userLoginInstance;
};
@ -148,25 +148,25 @@ userReset = function userReset() {
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
tablename: 'brute',
createTable: false,
knex: db.knex
});
userResetInstance = userResetInstance || new ExpressBrute(store,
_.extend({
attachResetToRequest: true,
failCallback: function (req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: 'Too many password reset attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.error',
{rfa: spamUserReset.freeRetries + 1 || 5, rfp: spamUserReset.lifetime || 60 * 60}),
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.context')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamUserReset, spamConfigKeys))
);
_.extend({
attachResetToRequest: true,
failCallback: function (req, res, next, nextValidRequestDate) {
return next(new errors.TooManyRequestsError({
message: 'Too many password reset attempts try again in ' + moment(nextValidRequestDate).fromNow(true),
context: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.error',
{rfa: spamUserReset.freeRetries + 1 || 5, rfp: spamUserReset.lifetime || 60 * 60}),
help: i18n.t('errors.middleware.spamprevention.forgottenPasswordEmail.context')
}));
},
handleStoreError: handleStoreError
}, _.pick(spamUserReset, spamConfigKeys))
);
return userResetInstance;
};
@ -179,28 +179,28 @@ privateBlog = function privateBlog() {
db = require('../../data/db');
store = store || new BruteKnex({
tablename: 'brute',
createTable: false,
knex: db.knex
});
tablename: 'brute',
createTable: false,
knex: db.knex
});
privateBlogInstance = privateBlogInstance || new ExpressBrute(store,
_.extend({
attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) {
logging.error(new errors.GhostError({
message: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.error',
{rfa: spamPrivateBlog.freeRetries + 1 || 5, rfp: spamPrivateBlog.lifetime || 60 * 60}),
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
}));
_.extend({
attachResetToRequest: false,
failCallback: function (req, res, next, nextValidRequestDate) {
logging.error(new errors.GhostError({
message: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.error',
{rfa: spamPrivateBlog.freeRetries + 1 || 5, rfp: spamPrivateBlog.lifetime || 60 * 60}),
context: i18n.t('errors.middleware.spamprevention.tooManySigninAttempts.context')
}));
return next(new errors.GhostError({
message: 'Too many private sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true)
}));
},
handleStoreError: handleStoreError
}, _.pick(spamPrivateBlog, spamConfigKeys))
);
return next(new errors.GhostError({
message: 'Too many private sign-in attempts try again in ' + moment(nextValidRequestDate).fromNow(true)
}));
},
handleStoreError: handleStoreError
}, _.pick(spamPrivateBlog, spamConfigKeys))
);
return privateBlogInstance;
};

View File

@ -59,7 +59,7 @@ _private.prepareError = function prepareError(err, req, res, next) {
next(err);
};
_private.JSONErrorRenderer = function JSONErrorRenderer(err, req, res, /*jshint unused:false */ next) {
_private.JSONErrorRenderer = function JSONErrorRenderer(err, req, res, next) { // eslint-disable-line no-unused-vars
// @TODO: jsonapi errors format (http://jsonapi.org/format/#error-objects)
res.json({
errors: [{
@ -115,7 +115,7 @@ _private.HTMLErrorRenderer = function HTMLErrorRender(err, req, res, next) {
});
};
_private.BasicErorRenderer = function BasicErrorRenderer(err, req, res, /*jshint unused:false */ next) {
_private.BasicErorRenderer = function BasicErrorRenderer(err, req, res, next) { // eslint-disable-line no-unused-vars
return res.send(res.statusCode + ' ' + err.message);
};

View File

@ -58,9 +58,7 @@ function serveFavicon() {
res.writeHead(200, content.headers);
res.end(content.body);
})
.catch(function (err) {
next(err);
});
.catch(next);
} else {
originalExtension = path.extname(filePath).toLowerCase();
@ -81,7 +79,7 @@ function serveFavicon() {
});
}
} else {
next();
return next();
}
};
}

View File

@ -44,7 +44,7 @@ function servePublicFile(file, type, maxAge) {
});
}
} else {
next();
return next();
}
};
}

View File

@ -19,14 +19,14 @@ function isWhiteListedFile(file) {
function forwardToExpressStatic(req, res, next) {
if (!themeUtils.getActive()) {
next();
} else {
var configMaxAge = config.get('caching:theme:maxAge');
express.static(themeUtils.getActive().path,
{maxAge: (configMaxAge || configMaxAge === 0) ? configMaxAge : utils.ONE_YEAR_MS}
)(req, res, next);
return next();
}
var configMaxAge = config.get('caching:theme:maxAge');
express.static(themeUtils.getActive().path,
{maxAge: (configMaxAge || configMaxAge === 0) ? configMaxAge : utils.ONE_YEAR_MS}
)(req, res, next);
}
function staticTheme() {

View File

@ -36,13 +36,13 @@ uncapitalise = function uncapitalise(req, res, next) {
*/
if (/[A-Z]/.test(decodeURIComponent(pathToTest))) {
redirectPath = (
utils.removeOpenRedirectFromUrl((req.originalUrl || req.url).replace(pathToTest, pathToTest.toLowerCase()))
utils.removeOpenRedirectFromUrl((req.originalUrl || req.url).replace(pathToTest, pathToTest.toLowerCase()))
);
return utils.url.redirect301(res, redirectPath);
} else {
next();
}
next();
};
module.exports = uncapitalise;

View File

@ -6,7 +6,6 @@ App = ghostBookshelf.Model.extend({
tableName: 'apps',
onSaving: function onSaving(newPage, attr, options) {
/*jshint unused:false*/
var self = this;
ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);

View File

@ -23,7 +23,7 @@ Basetoken = ghostBookshelf.Model.extend({
}
}, {
destroyAllExpired: function destroyAllExpired(options) {
destroyAllExpired: function destroyAllExpired(options) {
options = this.filterOptions(options, 'destroyAll');
return ghostBookshelf.Collection.forge([], {model: this})
.query('where', 'expires', '<', Date.now())

View File

@ -1,4 +1,5 @@
var _ = require('lodash');
var debug = require('ghost-ignition').debug('models:plugin:include-count'),
_ = require('lodash');
module.exports = function (Bookshelf) {
var modelProto = Bookshelf.Model.prototype,
@ -60,9 +61,7 @@ module.exports = function (Bookshelf) {
fetch: function () {
this.addCounts.apply(this, arguments);
if (this.debug) {
console.log('QUERY', this.query().toQuery());
}
debug('QUERY', this.query().toQuery());
// Call parent fetch
return modelProto.fetch.apply(this, arguments);
@ -70,9 +69,7 @@ module.exports = function (Bookshelf) {
fetchAll: function () {
this.addCounts.apply(this, arguments);
if (this.debug) {
console.log('QUERY', this.query().toQuery());
}
debug('QUERY', this.query().toQuery());
// Call parent fetchAll
return modelProto.fetchAll.apply(this, arguments);

View File

@ -1,7 +1,7 @@
// # Pagination
//
// Extends Bookshelf.Model with a `fetchPage` method. Handles everything to do with paginated requests.
var _ = require('lodash'),
var _ = require('lodash'),
defaults,
paginationUtils,
pagination;
@ -66,12 +66,12 @@ paginationUtils = {
formatResponse: function formatResponse(totalItems, options) {
var calcPages = Math.ceil(totalItems / options.limit) || 0,
pagination = {
page: options.page || defaults.page,
page: options.page || defaults.page,
limit: options.limit,
pages: calcPages === 0 ? 1 : calcPages,
total: totalItems,
next: null,
prev: null
next: null,
prev: null
};
if (pagination.pages > 1) {
@ -126,7 +126,7 @@ pagination = function pagination(bookshelf) {
// Extend updates the first object passed to it, no need for an assignment
_.extend(bookshelf.Model.prototype, {
/**
* ### Fetch page
* ### Fetch page
* A `fetch` extension to get a paginated set of items from a collection
*
* We trigger two queries:
@ -148,11 +148,6 @@ pagination = function pagination(bookshelf) {
bookshelf.knex.raw('count(distinct ' + tableName + '.' + idAttribute + ') as aggregate')
);
// the debug flag doesn't work for the raw knex count query!
if (this.debug) {
console.log('COUNT', countPromise.toQuery());
}
// #### Pre count clauses
// Add any where or join clauses which need to be included with the aggregate query

View File

@ -31,7 +31,6 @@ Tag = ghostBookshelf.Model.extend({
},
onSaving: function onSaving(newTag, attr, options) {
/*jshint unused:false*/
var self = this;
ghostBookshelf.Model.prototype.onSaving.apply(this, arguments);

View File

@ -236,8 +236,9 @@ User = ghostBookshelf.Model.extend({
format: function format(options) {
if (!_.isEmpty(options.website) &&
!validator.isURL(options.website, {
require_protocol: true,
protocols: ['http', 'https']})) {
require_protocol: true,
protocols: ['http', 'https']
})) {
options.website = 'http://' + options.website;
}
return ghostBookshelf.Model.prototype.format.call(this, options);
@ -575,7 +576,7 @@ User = ghostBookshelf.Model.extend({
options.withRelated = _.union(options.withRelated, options.include);
userData.slug = null;
return self.edit.call(self, userData, options);
return self.edit(userData, options);
},
/**
@ -792,41 +793,46 @@ User = ghostBookshelf.Model.extend({
var ownerRole,
contextUser;
return Promise.join(ghostBookshelf.model('Role').findOne({name: 'Owner'}),
User.findOne({id: options.context.user}, {include: ['roles']}))
.then(function then(results) {
ownerRole = results[0];
contextUser = results[1];
return Promise.join(
ghostBookshelf.model('Role').findOne({name: 'Owner'}),
User.findOne({id: options.context.user}, {include: ['roles']})
)
.then(function then(results) {
ownerRole = results[0];
contextUser = results[1];
// check if user has the owner role
var currentRoles = contextUser.toJSON(options).roles;
if (!_.some(currentRoles, {id: ownerRole.id})) {
return Promise.reject(new errors.NoPermissionError({message: i18n.t('errors.models.user.onlyOwnerCanTransferOwnerRole')}));
}
// check if user has the owner role
var currentRoles = contextUser.toJSON(options).roles;
if (!_.some(currentRoles, {id: ownerRole.id})) {
return Promise.reject(new errors.NoPermissionError({message: i18n.t('errors.models.user.onlyOwnerCanTransferOwnerRole')}));
}
return Promise.join(ghostBookshelf.model('Role').findOne({name: 'Administrator'}),
User.findOne({id: object.id}, {include: ['roles']}));
}).then(function then(results) {
var adminRole = results[0],
user = results[1],
currentRoles = user.toJSON(options).roles;
return Promise.join(ghostBookshelf.model('Role').findOne({name: 'Administrator'}),
User.findOne({id: object.id}, {include: ['roles']}));
})
.then(function then(results) {
var adminRole = results[0],
user = results[1],
currentRoles = user.toJSON(options).roles;
if (!_.some(currentRoles, {id: adminRole.id})) {
return Promise.reject(new errors.ValidationError({message: i18n.t('errors.models.user.onlyAdmCanBeAssignedOwnerRole')}));
}
if (!_.some(currentRoles, {id: adminRole.id})) {
return Promise.reject(new errors.ValidationError({message: i18n.t('errors.models.user.onlyAdmCanBeAssignedOwnerRole')}));
}
// convert owner to admin
return Promise.join(contextUser.roles().updatePivot({role_id: adminRole.id}),
user.roles().updatePivot({role_id: ownerRole.id}),
user.id);
}).then(function then(results) {
return Users.forge()
.query('whereIn', 'id', [contextUser.id, results[2]])
.fetch({withRelated: ['roles']});
}).then(function then(users) {
options.include = ['roles'];
return users.toJSON(options);
});
// convert owner to admin
return Promise.join(contextUser.roles().updatePivot({role_id: adminRole.id}),
user.roles().updatePivot({role_id: ownerRole.id}),
user.id);
})
.then(function then(results) {
return Users.forge()
.query('whereIn', 'id', [contextUser.id, results[2]])
.fetch({withRelated: ['roles']});
})
.then(function then(users) {
options.include = ['roles'];
return users.toJSON(options);
});
},
// Get the user by email address, enforces case insensitivity rejects if the user is not found

View File

@ -10,19 +10,17 @@ var _ = require('lodash'),
CanThisResult;
// Base class for canThis call results
CanThisResult = function () {
return;
};
CanThisResult = function () {};
CanThisResult.prototype.buildObjectTypeHandlers = function (objTypes, actType, context, permissionLoad) {
var objectTypeModelMap = {
post: models.Post,
role: models.Role,
user: models.User,
post: models.Post,
role: models.Role,
user: models.User,
permission: models.Permission,
setting: models.Settings,
setting: models.Settings,
subscriber: models.Subscriber,
invite: models.Invite
invite: models.Invite
};
// Iterate through the object types, i.e. ['post', 'tag', 'user']

View File

@ -29,7 +29,7 @@ generateProxyFunctions = function (name, permissions, isInternal) {
var permValue = getPermissionToMethod(perm, method);
if (!permValue) {
throw new Error(i18n.t('errors.apps.accessResourceWithoutPermission.error', {name:name, perm: perm, method: method}));
throw new Error(i18n.t('errors.apps.accessResourceWithoutPermission.error', {name: name, perm: perm, method: method}));
}
return wrappedFunc.apply(context, args);
@ -41,8 +41,8 @@ generateProxyFunctions = function (name, permissions, isInternal) {
},
passThruAppContextToApi = function (perm, apiMethods) {
var appContext = {
app: name
};
app: name
};
return _.reduce(apiMethods, function (memo, apiMethod, methodName) {
memo[methodName] = function () {

View File

@ -83,8 +83,6 @@ function ping(post) {
// with all the data we have, we're doing the request now
makeRequest(reqOptions, slackData);
} else {
return;
}
}

View File

@ -1,5 +1,3 @@
// jscs:disable requireMultipleVarDecl
'use strict';
var fs = require('fs-extra'),

View File

@ -63,18 +63,18 @@ function createCustomNotification(message) {
}
var notification = {
status: 'alert',
type: 'info',
custom: true,
uuid: message.id,
dismissible: true,
message: message.content
},
getAllNotifications = api.notifications.browse({context: {internal: true}}),
getSeenNotifications = api.settings.read(_.extend({key: 'seen_notifications'}, internal));
status: 'alert',
type: 'info',
custom: true,
uuid: message.id,
dismissible: true,
message: message.content
},
getAllNotifications = api.notifications.browse({context: {internal: true}}),
getSeenNotifications = api.settings.read(_.extend({key: 'seen_notifications'}, internal));
return Promise.join(getAllNotifications, getSeenNotifications, function joined(all, seen) {
var isSeen = _.includes(JSON.parse(seen.settings[0].value || []), notification.id),
var isSeen = _.includes(JSON.parse(seen.settings[0].value || []), notification.id),
isDuplicate = _.some(all.notifications, {message: notification.message});
if (!isSeen && !isDuplicate) {
@ -233,7 +233,7 @@ function updateCheck() {
if (nextUpdateCheck && nextUpdateCheck.value && nextUpdateCheck.value > moment().unix()) {
// It's not time to check yet
return;
return; // eslint-disable-line no-useless-return
} else {
// We need to do a check
return updateCheckRequest()

View File

@ -21,6 +21,7 @@ utils = {
/**
* Timespans in seconds and milliseconds for better readability
*/
/* eslint-disable key-spacing */
ONE_HOUR_S: 3600,
ONE_DAY_S: 86400,
ONE_MONTH_S: 2628000,
@ -33,6 +34,7 @@ utils = {
ONE_MONTH_MS: 2628000000,
SIX_MONTH_MS: 15768000000,
ONE_YEAR_MS: 31536000000,
// eslint-enable key-spacing */
/**
* Return a unique identifier with the given `len`.

View File

@ -4,45 +4,42 @@ var MarkdownIt = require('markdown-it'),
breaks: true,
linkify: true
})
.use(require('markdown-it-footnote'))
.use(require('markdown-it-lazy-headers'))
.use(require('markdown-it-mark'))
.use(function namedHeaders(md) {
// jscs:disable
.use(require('markdown-it-footnote'))
.use(require('markdown-it-lazy-headers'))
.use(require('markdown-it-mark'))
.use(function namedHeaders(md) {
// match legacy Showdown IDs
var slugify = function (inputString, usedHeaders) {
var slug = inputString.replace(/[^\w]/g, '').toLowerCase();
if (usedHeaders[slug]) {
usedHeaders[slug] += 1;
slug += usedHeaders[slug];
}
return slug;
};
var originalHeadingOpen = md.renderer.rules.heading_open;
// match legacy Showdown IDs
var slugify = function (inputString, usedHeaders) {
var slug = inputString.replace(/[^\w]/g, '').toLowerCase();
if (usedHeaders[slug]) {
usedHeaders[slug] += 1;
slug += usedHeaders[slug];
}
return slug;
};
var originalHeadingOpen = md.renderer.rules.heading_open;
// originally from https://github.com/leff/markdown-it-named-headers
// moved here to avoid pulling in http://stringjs.com dependency
md.renderer.rules.heading_open = function (tokens, idx, something, somethingelse, self) {
var usedHeaders = {};
// originally from https://github.com/leff/markdown-it-named-headers
// moved here to avoid pulling in http://stringjs.com dependency
md.renderer.rules.heading_open = function (tokens, idx, something, somethingelse, self) {
var used_headers = {};
tokens[idx].attrs = tokens[idx].attrs || [];
tokens[idx].attrs = tokens[idx].attrs || [];
var title = tokens[idx + 1].children.reduce(function (acc, t) {
return acc + t.content;
}, '');
var title = tokens[idx + 1].children.reduce(function (acc, t) {
return acc + t.content;
}, '');
var slug = slugify(title, usedHeaders);
tokens[idx].attrs.push(['id', slug]);
var slug = slugify(title, used_headers);
tokens[idx].attrs.push(['id', slug]);
if (originalHeadingOpen) {
return originalHeadingOpen.apply(this, arguments);
} else {
return self.renderToken.apply(self, arguments);
}
};
// jscs:enable
});
if (originalHeadingOpen) {
return originalHeadingOpen.apply(this, arguments);
} else {
return self.renderToken.apply(self, arguments);
}
};
});
// configure linkify-it
converter.linkify.set({

View File

@ -1,9 +1,9 @@
var SimpleDom = require('simple-dom'),
Renderer = require('mobiledoc-dom-renderer').default,
config = require('../config'),
logging = require('../logging'),
errors = require('../errors'),
defaults = require(config.get('paths').internalAppPath + 'default-cards'),
var SimpleDom = require('simple-dom'),
Renderer = require('mobiledoc-dom-renderer').default,
config = require('../config'),
logging = require('../logging'),
errors = require('../errors'),
defaults = require(config.get('paths').internalAppPath + 'default-cards'),
options = {
dom: new SimpleDom.Document(),
cards: defaults.cards,
@ -38,9 +38,9 @@ var SimpleDom = require('simple-dom'),
module.exports = {
render: function (mobiledoc) {
var renderer = new Renderer(options),
rendered = renderer.render(mobiledoc),
serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap),
html = serializer.serializeChildren(rendered.result);
rendered = renderer.render(mobiledoc),
serializer = new SimpleDom.HTMLSerializer(SimpleDom.voidMap),
html = serializer.serializeChildren(rendered.result);
return html;
}
};

View File

@ -1,7 +1,6 @@
/**
* Dependencies
*/
var parsePackageJson = require('./parse-package-json'),
errors = require('../../errors'),
Promise = require('bluebird'),

View File

@ -13,46 +13,46 @@ function readCSV(options) {
readFile.on('err', function (err) {
reject(err);
})
.pipe(csvParser())
.on('data', function (row) {
rows.push(row);
})
.on('end', function () {
// If CSV is single column - return all values including header
var headers = _.keys(rows[0]), result = {}, columnMap = {};
if (columnsToExtract.length === 1 && headers.length === 1) {
results = _.map(rows, function (value) {
.pipe(csvParser())
.on('data', function (row) {
rows.push(row);
})
.on('end', function () {
// If CSV is single column - return all values including header
var headers = _.keys(rows[0]), result = {}, columnMap = {};
if (columnsToExtract.length === 1 && headers.length === 1) {
results = _.map(rows, function (value) {
result = {};
result[columnsToExtract[0].name] = value[headers[0]];
return result;
});
// Add first row
result = {};
result[columnsToExtract[0].name] = value[headers[0]];
return result;
});
result[columnsToExtract[0].name] = headers[0];
results = [result].concat(results);
} else {
// If there are multiple columns in csv file
// try to match headers using lookup value
// Add first row
result = {};
result[columnsToExtract[0].name] = headers[0];
results = [result].concat(results);
} else {
// If there are multiple columns in csv file
// try to match headers using lookup value
_.map(columnsToExtract, function findMatches(column) {
_.each(headers, function checkheader(header) {
if (column.lookup.test(header)) {
columnMap[column.name] = header;
}
_.map(columnsToExtract, function findMatches(column) {
_.each(headers, function checkheader(header) {
if (column.lookup.test(header)) {
columnMap[column.name] = header;
}
});
});
});
results = _.map(rows, function evaluateRow(row) {
var result = {};
_.each(columnMap, function returnMatches(value, key) {
result[key] = row[value];
results = _.map(rows, function evaluateRow(row) {
var result = {};
_.each(columnMap, function returnMatches(value, key) {
result[key] = row[value];
});
return result;
});
return result;
});
}
resolve(results);
});
}
resolve(results);
});
});
}

View File

@ -19,7 +19,8 @@ function removeOpenRedirectFromUrl(urlString) {
var parsedUrl = url.parse(urlString);
return (
(parsedUrl.protocol ? parsedUrl.protocol + '//' : '') + // http://
// http://
(parsedUrl.protocol ? parsedUrl.protocol + '//' : '') +
(parsedUrl.auth || '') +
(parsedUrl.host || '') +
removeDoubleCharacters('/', parsedUrl.path) +

View File

@ -43,7 +43,6 @@ exports.resetToken = {
email: email
};
},
/*jslint bitwise:true*/
compare: function compare(options) {
options = options || {};

View File

@ -227,13 +227,13 @@ function urlFor(context, data, absolute) {
knownObjects = ['post', 'tag', 'author', 'image', 'nav'], baseUrl,
hostname,
// this will become really big
knownPaths = {
home: '/',
rss: '/rss/',
api: API_PATH,
sitemap_xsl: '/sitemap.xsl'
};
// this will become really big
knownPaths = {
home: '/',
rss: '/rss/',
api: API_PATH,
sitemap_xsl: '/sitemap.xsl'
};
// Make data properly optional
if (_.isBoolean(data)) {
@ -278,7 +278,7 @@ function urlFor(context, data, absolute) {
if (urlPath.indexOf(hostname) > -1
&& !urlPath.split(hostname)[0].match(/\.|mailto:/)
&& urlPath.split(hostname)[1].substring(0,1) !== ':') {
&& urlPath.split(hostname)[1].substring(0, 1) !== ':') {
// make link relative to account for possible
// mismatch in http/https etc, force absolute
// do not do so if link is a subdomain of blog url

288
core/test/.eslintrc.json Normal file
View File

@ -0,0 +1,288 @@
{
"env": {
"es6": true,
"node": true,
"mocha": true
},
"extends": "eslint:recommended",
"rules": {
"accessor-pairs": "error",
"array-bracket-newline": "off",
"array-bracket-spacing": [
"error",
"never"
],
"array-callback-return": "off",
"array-element-newline": "off",
"arrow-body-style": "error",
"arrow-parens": [
"error",
"always"
],
"arrow-spacing": [
"error",
{
"after": true,
"before": true
}
],
"block-scoped-var": "error",
"brace-style": [
"error",
"1tbs",
{
"allowSingleLine": true
}
],
"callback-return": "error",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "off",
"comma-dangle": "error",
"comma-spacing": "error",
"comma-style": [
"error",
"last"
],
"complexity": "off",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "error",
"default-case": "error",
"dot-location": [
"error",
"property"
],
"dot-notation": "off",
"eol-last": "error",
"eqeqeq": "error",
"for-direction": "error",
"func-call-spacing": "error",
"func-name-matching": "off",
"func-names": "off",
"func-style": "off",
"function-paren-newline": "off",
"generator-star-spacing": "error",
"getter-return": "error",
"global-require": "off",
"guard-for-in": "error",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"indent": "off",
"indent-legacy": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "error",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "off",
"lines-around-directive": "off",
"lines-between-class-members": [
"error",
"always"
],
"max-depth": "error",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "error",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-comment-style": "off",
"multiline-ternary": "off",
"new-parens": "error",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "error",
"no-array-constructor": "error",
"no-await-in-loop": "error",
"no-bitwise": "off",
"no-buffer-constructor": "off",
"no-caller": "error",
"no-catch-shadow": "error",
"no-confusing-arrow": "error",
"no-console": "off",
"no-continue": "error",
"no-div-regex": "off",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-globals": "error",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "error",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "off",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "off",
"no-multi-assign": "off",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "error",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "error",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "off",
"no-plusplus": "error",
"no-process-env": "off",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "off",
"no-regex-spaces": "off",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "off",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-spaced-func": "error",
"no-sync": "off",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "off",
"no-unused-vars": "off",
"no-use-before-define": "off",
"no-useless-call": "error",
"no-useless-computed-key": "error",
"no-useless-concat": "off",
"no-useless-constructor": "error",
"no-useless-escape": "off",
"no-useless-rename": "error",
"no-useless-return": "error",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"nonblock-statement-body-position": "error",
"object-curly-newline": [
"error",
{
"consistent": true
}
],
"object-curly-spacing": [
"error",
"never"
],
"object-property-newline": "off",
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": "off",
"padded-blocks": [
"error",
"never"
],
"padding-line-between-statements": "error",
"prefer-arrow-callback": "off",
"prefer-const": "off",
"prefer-destructuring": "off",
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "off",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": [
"error",
"as-needed"
],
"quotes": "off",
"radix": "off",
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": ["error", "always"],
"semi-spacing": "error",
"semi-style": [
"error",
"last"
],
"sort-imports": "error",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "error",
"space-before-function-paren": [
"error",
{
"anonymous": "always",
"named": "never"
}
],
"space-in-parens": [
"error",
"never"
],
"space-infix-ops": "error",
"space-unary-ops": "error",
"spaced-comment": "off",
"strict": "off",
"switch-colon-spacing": "error",
"symbol-description": "error",
"template-curly-spacing": [
"error",
"never"
],
"template-tag-spacing": "error",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "off",
"vars-on-top": "off",
"wrap-iife": "off",
"wrap-regex": "off",
"yield-star-spacing": "error",
"yoda": "error"
}
}

View File

@ -38,6 +38,10 @@ describe('Configuration API', function () {
.expect('Cache-Control', testUtils.cacheRules.private)
.expect(200)
.end(function (err, res) {
if (err) {
done(err);
}
should.exist(res.body.configuration);
done();
});

View File

@ -100,9 +100,12 @@ describe('Frontend Routing', function () {
var date = moment().format('YYYY/MM/DD');
request.get('/2016/04/01/welcome/')
.expect('Content-Type', /html/)
.end(function (err, res) {
res.status.should.eql(301);
.expect(301)
.end(function (err) {
if (err) {
return done(err);
}
request.get('/' + date + '/welcome/')
.expect(200)
.expect('Content-Type', /html/)

View File

@ -54,7 +54,7 @@ describe('Import', function () {
it('removes duplicate posts', function (done) {
var exportData;
testUtils.fixtures.loadExportFixture('export-003',{lts:true}).then(function (exported) {
testUtils.fixtures.loadExportFixture('export-003', {lts:true}).then(function (exported) {
exportData = exported;
return dataImporter.doImport(exportData);
}).then(function (importResult) {
@ -97,7 +97,7 @@ describe('Import', function () {
it('cares about invalid dates', function (done) {
var exportData;
testUtils.fixtures.loadExportFixture('export-003',{lts:true}).then(function (exported) {
testUtils.fixtures.loadExportFixture('export-003', {lts:true}).then(function (exported) {
exportData = exported;
return dataImporter.doImport(exportData);
}).then(function (importResult) {

View File

@ -137,8 +137,7 @@ function forkGhost(newConfig) {
resolve(child);
}
});
socket.on('error', function (err) {
/*jshint unused:false*/
socket.on('error', function () {
pingTries = pingTries + 1;
// continue checking

View File

@ -95,28 +95,26 @@
"sqlite3": "3.1.8"
},
"devDependencies": {
"eslint": "4.10.0",
"grunt": "1.0.1",
"grunt-bg-shell": "2.3.3",
"grunt-cli": "1.2.0",
"grunt-contrib-clean": "1.1.0",
"grunt-contrib-compress": "1.4.3",
"grunt-contrib-copy": "1.0.0",
"grunt-contrib-jshint": "1.1.0",
"grunt-contrib-symlink": "^1.0.0",
"grunt-contrib-uglify": "2.0.0",
"grunt-contrib-watch": "1.0.0",
"grunt-cssnano": "2.1.0",
"grunt-docker": "0.0.11",
"grunt-eslint": "20.1.0",
"grunt-express-server": "0.5.3",
"grunt-jscs": "3.0.1",
"grunt-mocha-cli": "2.1.0",
"grunt-mocha-istanbul": "5.0.2",
"grunt-shell": "1.3.1",
"grunt-subgrunt": "1.2.0",
"grunt-update-submodules": "0.4.1",
"istanbul": "0.4.5",
"jshint": "2.9.5",
"jshint-stylish": "2.2.1",
"matchdep": "1.0.1",
"minimist": "1.2.0",
"mocha": "3.5.3",

874
yarn.lock

File diff suppressed because it is too large Load Diff