mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-24 06:35:49 +03:00
Merge branch '0.3.1-wip'
Conflicts: core/server/controllers/admin.js
This commit is contained in:
commit
6bd62538af
410
Gruntfile.js
410
Gruntfile.js
@ -1,13 +1,13 @@
|
|||||||
var path = require('path'),
|
var path = require('path'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
semver = require("semver"),
|
semver = require('semver'),
|
||||||
fs = require("fs"),
|
fs = require('fs'),
|
||||||
path = require("path"),
|
path = require('path'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
spawn = require("child_process").spawn,
|
spawn = require("child_process").spawn,
|
||||||
buildDirectory = path.resolve(process.cwd(), '.build'),
|
buildDirectory = path.resolve(process.cwd(), '.build'),
|
||||||
distDirectory = path.resolve(process.cwd(), '.dist'),
|
distDirectory = path.resolve(process.cwd(), '.dist'),
|
||||||
configLoader = require('./core/config-loader.js'),
|
configLoader = require('./core/config-loader.js'),
|
||||||
|
|
||||||
buildGlob = [
|
buildGlob = [
|
||||||
'**',
|
'**',
|
||||||
@ -94,7 +94,7 @@ var path = require('path'),
|
|||||||
// Start our server in development
|
// Start our server in development
|
||||||
express: {
|
express: {
|
||||||
options: {
|
options: {
|
||||||
script: "index.js"
|
script: 'index.js'
|
||||||
},
|
},
|
||||||
|
|
||||||
dev: {
|
dev: {
|
||||||
@ -136,9 +136,9 @@ var path = require('path'),
|
|||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
src: [
|
src: [
|
||||||
"*.js",
|
'*.js',
|
||||||
"core/*.js",
|
'core/*.js',
|
||||||
"core/server/**/*.js"
|
'core/server/**/*.js'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -156,11 +156,11 @@ var path = require('path'),
|
|||||||
unparam: true
|
unparam: true
|
||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
src: "core/client/**/*.js"
|
src: 'core/client/**/*.js'
|
||||||
},
|
},
|
||||||
exclude: [
|
exclude: [
|
||||||
"core/client/assets/**/*.js",
|
'core/client/assets/**/*.js',
|
||||||
"core/client/tpl/**/*.js"
|
'core/client/tpl/**/*.js'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
shared: {
|
shared: {
|
||||||
@ -180,19 +180,19 @@ var path = require('path'),
|
|||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
src: [
|
src: [
|
||||||
"core/shared/**/*.js"
|
'core/shared/**/*.js'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
exclude: [
|
exclude: [
|
||||||
"core/shared/vendor/**/*.js"
|
'core/shared/vendor/**/*.js'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mochacli: {
|
mochacli: {
|
||||||
options: {
|
options: {
|
||||||
ui: "bdd",
|
ui: 'bdd',
|
||||||
reporter: "spec"
|
reporter: 'spec'
|
||||||
},
|
},
|
||||||
|
|
||||||
all: {
|
all: {
|
||||||
@ -245,14 +245,14 @@ var path = require('path'),
|
|||||||
handlebars: {
|
handlebars: {
|
||||||
core: {
|
core: {
|
||||||
options: {
|
options: {
|
||||||
namespace: "JST",
|
namespace: 'JST',
|
||||||
processName: function (filename) {
|
processName: function (filename) {
|
||||||
filename = filename.replace('core/client/tpl/', '');
|
filename = filename.replace('core/client/tpl/', '');
|
||||||
return filename.replace('.hbs', '');
|
return filename.replace('.hbs', '');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
files: {
|
files: {
|
||||||
"core/client/tpl/hbs-tpl.js": "core/client/tpl/**/*.hbs"
|
'core/client/tpl/hbs-tpl.js': 'core/client/tpl/**/*.hbs'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -260,19 +260,19 @@ var path = require('path'),
|
|||||||
groc: {
|
groc: {
|
||||||
docs: {
|
docs: {
|
||||||
options: {
|
options: {
|
||||||
"out": "./docs/",
|
'out': './docs/',
|
||||||
"glob": [
|
'glob': [
|
||||||
"README.md",
|
'README.md',
|
||||||
"config.example.js",
|
'config.example.js',
|
||||||
"index.js",
|
'index.js',
|
||||||
"core/*.js",
|
'core/*.js',
|
||||||
"core/server/**/*.js",
|
'core/server/**/*.js',
|
||||||
"core/shared/**/*.js",
|
'core/shared/**/*.js',
|
||||||
"core/client/**/*.js"
|
'core/client/**/*.js'
|
||||||
],
|
],
|
||||||
"except": [
|
'except': [
|
||||||
"!core/**/vendor/**/*.js",
|
'!core/**/vendor/**/*.js',
|
||||||
"!core/client/tpl/**/*.js"
|
'!core/client/tpl/**/*.js'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +280,7 @@ var path = require('path'),
|
|||||||
|
|
||||||
clean: {
|
clean: {
|
||||||
build: {
|
build: {
|
||||||
src: ["<%= paths.buildBuild %>/**"]
|
src: ['<%= paths.buildBuild %>/**']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -289,21 +289,21 @@ var path = require('path'),
|
|||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
src: buildGlob,
|
src: buildGlob,
|
||||||
dest: "<%= paths.nightlyBuild %>/<%= pkg.version %>/"
|
dest: '<%= paths.nightlyBuild %>/<%= pkg.version %>/'
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
weekly: {
|
weekly: {
|
||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
src: buildGlob,
|
src: buildGlob,
|
||||||
dest: "<%= paths.weeklyBuild %>/<%= pkg.version %>/"
|
dest: '<%= paths.weeklyBuild %>/<%= pkg.version %>/'
|
||||||
}]
|
}]
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
src: buildGlob,
|
src: buildGlob,
|
||||||
dest: "<%= paths.buildBuild %>/"
|
dest: '<%= paths.buildBuild %>/'
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -311,27 +311,27 @@ var path = require('path'),
|
|||||||
compress: {
|
compress: {
|
||||||
nightly: {
|
nightly: {
|
||||||
options: {
|
options: {
|
||||||
archive: "<%= paths.nightlyDist %>/Ghost-Nightly-<%= pkg.version %>.zip"
|
archive: '<%= paths.nightlyDist %>/Ghost-Nightly-<%= pkg.version %>.zip'
|
||||||
},
|
},
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: "<%= paths.nightlyBuild %>/<%= pkg.version %>/",
|
cwd: '<%= paths.nightlyBuild %>/<%= pkg.version %>/',
|
||||||
src: ["**"]
|
src: ['**']
|
||||||
},
|
},
|
||||||
weekly: {
|
weekly: {
|
||||||
options: {
|
options: {
|
||||||
archive: "<%= paths.weeklyDist %>/Ghost-Weekly-<%= pkg.version %>.zip"
|
archive: '<%= paths.weeklyDist %>/Ghost-Weekly-<%= pkg.version %>.zip'
|
||||||
},
|
},
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: "<%= paths.weeklyBuild %>/<%= pkg.version %>/",
|
cwd: '<%= paths.weeklyBuild %>/<%= pkg.version %>/',
|
||||||
src: ["**"]
|
src: ['**']
|
||||||
},
|
},
|
||||||
build: {
|
build: {
|
||||||
options: {
|
options: {
|
||||||
archive: "<%= paths.buildDist %>/Ghost-Build.zip"
|
archive: '<%= paths.buildDist %>/Ghost-Build.zip'
|
||||||
},
|
},
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: "<%= paths.buildBuild %>/",
|
cwd: '<%= paths.buildBuild %>/',
|
||||||
src: ["**"]
|
src: ['**']
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -340,113 +340,113 @@ var path = require('path'),
|
|||||||
tagName: '%VERSION%',
|
tagName: '%VERSION%',
|
||||||
commitMessage: '<%= buildType %> Release %VERSION%',
|
commitMessage: '<%= buildType %> Release %VERSION%',
|
||||||
tagMessage: '<%= buildType %> Release %VERSION%',
|
tagMessage: '<%= buildType %> Release %VERSION%',
|
||||||
pushTo: "origin build"
|
pushTo: 'origin build'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
concat: {
|
concat: {
|
||||||
dev: {
|
dev: {
|
||||||
files: {
|
files: {
|
||||||
"core/built/scripts/vendor.js": [
|
'core/built/scripts/vendor.js': [
|
||||||
"core/shared/vendor/jquery/jquery.js",
|
'core/shared/vendor/jquery/jquery.js',
|
||||||
"core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js",
|
'core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js',
|
||||||
"core/client/assets/lib/jquery-utils.js",
|
'core/client/assets/lib/jquery-utils.js',
|
||||||
"core/client/assets/lib/uploader.js",
|
'core/client/assets/lib/uploader.js',
|
||||||
"core/shared/vendor/underscore.js",
|
'core/shared/vendor/underscore.js',
|
||||||
"core/shared/vendor/backbone/backbone.js",
|
'core/shared/vendor/backbone/backbone.js',
|
||||||
"core/shared/vendor/handlebars/handlebars-runtime.js",
|
'core/shared/vendor/handlebars/handlebars-runtime.js',
|
||||||
"core/shared/vendor/moment.js",
|
'core/shared/vendor/moment.js',
|
||||||
|
|
||||||
"core/client/assets/vendor/icheck/jquery.icheck.min.js",
|
'core/client/assets/vendor/icheck/jquery.icheck.min.js',
|
||||||
|
|
||||||
"core/shared/vendor/jquery/jquery.ui.widget.js",
|
'core/shared/vendor/jquery/jquery.ui.widget.js',
|
||||||
"core/shared/vendor/jquery/jquery.iframe-transport.js",
|
'core/shared/vendor/jquery/jquery.iframe-transport.js',
|
||||||
"core/shared/vendor/jquery/jquery.fileupload.js",
|
'core/shared/vendor/jquery/jquery.fileupload.js',
|
||||||
|
|
||||||
"core/client/assets/vendor/codemirror/codemirror.js",
|
'core/client/assets/vendor/codemirror/codemirror.js',
|
||||||
"core/client/assets/vendor/codemirror/addon/mode/overlay.js",
|
'core/client/assets/vendor/codemirror/addon/mode/overlay.js',
|
||||||
"core/client/assets/vendor/codemirror/mode/markdown/markdown.js",
|
'core/client/assets/vendor/codemirror/mode/markdown/markdown.js',
|
||||||
"core/client/assets/vendor/codemirror/mode/gfm/gfm.js",
|
'core/client/assets/vendor/codemirror/mode/gfm/gfm.js',
|
||||||
"core/client/assets/vendor/showdown/showdown.js",
|
'core/client/assets/vendor/showdown/showdown.js',
|
||||||
"core/client/assets/vendor/showdown/extensions/ghostdown.js",
|
'core/client/assets/vendor/showdown/extensions/ghostdown.js',
|
||||||
"core/shared/vendor/showdown/extensions/github.js",
|
'core/shared/vendor/showdown/extensions/github.js',
|
||||||
"core/client/assets/vendor/shortcuts.js",
|
'core/client/assets/vendor/shortcuts.js',
|
||||||
"core/client/assets/vendor/validator-client.js",
|
'core/client/assets/vendor/validator-client.js',
|
||||||
"core/client/assets/vendor/countable.js",
|
'core/client/assets/vendor/countable.js',
|
||||||
"core/client/assets/vendor/to-title-case.js",
|
'core/client/assets/vendor/to-title-case.js',
|
||||||
"core/client/assets/vendor/packery.pkgd.min.js",
|
'core/client/assets/vendor/packery.pkgd.min.js',
|
||||||
"core/client/assets/vendor/fastclick.js"
|
'core/client/assets/vendor/fastclick.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
"core/built/scripts/helpers.js": [
|
'core/built/scripts/helpers.js': [
|
||||||
"core/client/init.js",
|
'core/client/init.js',
|
||||||
|
|
||||||
"core/client/mobile-interactions.js",
|
'core/client/mobile-interactions.js',
|
||||||
"core/client/toggle.js",
|
'core/client/toggle.js',
|
||||||
"core/client/markdown-actions.js",
|
'core/client/markdown-actions.js',
|
||||||
"core/client/helpers/index.js"
|
'core/client/helpers/index.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
"core/built/scripts/templates.js": [
|
'core/built/scripts/templates.js': [
|
||||||
"core/client/tpl/hbs-tpl.js"
|
'core/client/tpl/hbs-tpl.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
"core/built/scripts/models.js": [
|
'core/built/scripts/models.js': [
|
||||||
"core/client/models/**/*.js"
|
'core/client/models/**/*.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
"core/built/scripts/views.js": [
|
'core/built/scripts/views.js': [
|
||||||
"core/client/views/**/*.js",
|
'core/client/views/**/*.js',
|
||||||
"core/client/router.js"
|
'core/client/router.js'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
prod: {
|
prod: {
|
||||||
files: {
|
files: {
|
||||||
"core/built/scripts/ghost.js": [
|
'core/built/scripts/ghost.js': [
|
||||||
"core/shared/vendor/jquery/jquery.js",
|
'core/shared/vendor/jquery/jquery.js',
|
||||||
"core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js",
|
'core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js',
|
||||||
"core/client/assets/lib/jquery-utils.js",
|
'core/client/assets/lib/jquery-utils.js',
|
||||||
"core/client/assets/lib/uploader.js",
|
'core/client/assets/lib/uploader.js',
|
||||||
"core/shared/vendor/underscore.js",
|
'core/shared/vendor/underscore.js',
|
||||||
"core/shared/vendor/backbone/backbone.js",
|
'core/shared/vendor/backbone/backbone.js',
|
||||||
"core/shared/vendor/handlebars/handlebars-runtime.js",
|
'core/shared/vendor/handlebars/handlebars-runtime.js',
|
||||||
"core/shared/vendor/moment.js",
|
'core/shared/vendor/moment.js',
|
||||||
|
|
||||||
"core/client/assets/vendor/icheck/jquery.icheck.min.js",
|
'core/client/assets/vendor/icheck/jquery.icheck.min.js',
|
||||||
|
|
||||||
"core/shared/vendor/jquery/jquery.ui.widget.js",
|
'core/shared/vendor/jquery/jquery.ui.widget.js',
|
||||||
"core/shared/vendor/jquery/jquery.iframe-transport.js",
|
'core/shared/vendor/jquery/jquery.iframe-transport.js',
|
||||||
"core/shared/vendor/jquery/jquery.fileupload.js",
|
'core/shared/vendor/jquery/jquery.fileupload.js',
|
||||||
|
|
||||||
"core/client/assets/vendor/codemirror/codemirror.js",
|
'core/client/assets/vendor/codemirror/codemirror.js',
|
||||||
"core/client/assets/vendor/codemirror/addon/mode/overlay.js",
|
'core/client/assets/vendor/codemirror/addon/mode/overlay.js',
|
||||||
"core/client/assets/vendor/codemirror/mode/markdown/markdown.js",
|
'core/client/assets/vendor/codemirror/mode/markdown/markdown.js',
|
||||||
"core/client/assets/vendor/codemirror/mode/gfm/gfm.js",
|
'core/client/assets/vendor/codemirror/mode/gfm/gfm.js',
|
||||||
"core/client/assets/vendor/showdown/showdown.js",
|
'core/client/assets/vendor/showdown/showdown.js',
|
||||||
"core/client/assets/vendor/showdown/extensions/ghostdown.js",
|
'core/client/assets/vendor/showdown/extensions/ghostdown.js',
|
||||||
"core/shared/vendor/showdown/extensions/github.js",
|
'core/shared/vendor/showdown/extensions/github.js',
|
||||||
"core/client/assets/vendor/shortcuts.js",
|
'core/client/assets/vendor/shortcuts.js',
|
||||||
"core/client/assets/vendor/validator-client.js",
|
'core/client/assets/vendor/validator-client.js',
|
||||||
"core/client/assets/vendor/countable.js",
|
'core/client/assets/vendor/countable.js',
|
||||||
"core/client/assets/vendor/to-title-case.js",
|
'core/client/assets/vendor/to-title-case.js',
|
||||||
"core/client/assets/vendor/packery.pkgd.min.js",
|
'core/client/assets/vendor/packery.pkgd.min.js',
|
||||||
"core/client/assets/vendor/fastclick.js",
|
'core/client/assets/vendor/fastclick.js',
|
||||||
|
|
||||||
"core/client/init.js",
|
'core/client/init.js',
|
||||||
|
|
||||||
"core/client/mobile-interactions.js",
|
'core/client/mobile-interactions.js',
|
||||||
"core/client/toggle.js",
|
'core/client/toggle.js',
|
||||||
"core/client/markdown-actions.js",
|
'core/client/markdown-actions.js',
|
||||||
"core/client/helpers/index.js",
|
'core/client/helpers/index.js',
|
||||||
|
|
||||||
"core/client/tpl/hbs-tpl.js",
|
'core/client/tpl/hbs-tpl.js',
|
||||||
|
|
||||||
"core/client/models/**/*.js",
|
'core/client/models/**/*.js',
|
||||||
|
|
||||||
"core/client/views/**/*.js",
|
'core/client/views/**/*.js',
|
||||||
|
|
||||||
"core/client/router.js"
|
'core/client/router.js'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -455,7 +455,7 @@ var path = require('path'),
|
|||||||
uglify: {
|
uglify: {
|
||||||
prod: {
|
prod: {
|
||||||
files: {
|
files: {
|
||||||
"core/built/scripts/ghost.min.js": "core/built/scripts/ghost.js"
|
'core/built/scripts/ghost.min.js': 'core/built/scripts/ghost.js'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -526,17 +526,17 @@ var path = require('path'),
|
|||||||
depth = depth || 0;
|
depth = depth || 0;
|
||||||
|
|
||||||
if (!depth) {
|
if (!depth) {
|
||||||
grunt.log.writeln("git " + args.join(" "));
|
grunt.log.writeln('git ' + args.join(' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
var buffer = [];
|
var buffer = [];
|
||||||
spawn("git", args, {
|
spawn('git', args, {
|
||||||
// We can reasonably assume the gruntfile will be in the root of the repo.
|
// We can reasonably assume the gruntfile will be in the root of the repo.
|
||||||
cwd : __dirname,
|
cwd : __dirname,
|
||||||
|
|
||||||
stdio : ["ignore", "pipe", process.stderr]
|
stdio : ['ignore', 'pipe', process.stderr]
|
||||||
|
|
||||||
}).on("exit", function (code) {
|
}).on('exit', function (code) {
|
||||||
|
|
||||||
// Process exited correctly but we got no output.
|
// Process exited correctly but we got no output.
|
||||||
// Spawn again, but make sure we don't spiral out of control.
|
// Spawn again, but make sure we don't spiral out of control.
|
||||||
@ -552,7 +552,7 @@ var path = require('path'),
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (code === 0) {
|
if (code === 0) {
|
||||||
return callback(buffer.join(""));
|
return callback(buffer.join(''));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We failed. Git returned a non-standard exit code.
|
// We failed. Git returned a non-standard exit code.
|
||||||
@ -560,7 +560,7 @@ var path = require('path'),
|
|||||||
done(false);
|
done(false);
|
||||||
|
|
||||||
// Push returned data into the buffer
|
// Push returned data into the buffer
|
||||||
}).stdout.on("data", buffer.push.bind(buffer));
|
}).stdout.on('data', buffer.push.bind(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crazy function for getting around inconsistencies in tagging
|
// Crazy function for getting around inconsistencies in tagging
|
||||||
@ -575,14 +575,14 @@ var path = require('path'),
|
|||||||
// into sort directly. Could be something to think about
|
// into sort directly. Could be something to think about
|
||||||
// in future.
|
// in future.
|
||||||
|
|
||||||
if (semver.rcompare(a, "0.2.0") < 0 ||
|
if (semver.rcompare(a, '0.2.0') < 0 ||
|
||||||
semver.rcompare(b, "0.2.0") < 0) {
|
semver.rcompare(b, '0.2.0') < 0) {
|
||||||
|
|
||||||
return semver.rcompare(a, b);
|
return semver.rcompare(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
a = a.split("-");
|
a = a.split('-');
|
||||||
b = b.split("-");
|
b = b.split('-');
|
||||||
|
|
||||||
if (semver.rcompare(a[0], b[0]) !== 0) {
|
if (semver.rcompare(a[0], b[0]) !== 0) {
|
||||||
return semver.rcompare(a[0], b[0]);
|
return semver.rcompare(a[0], b[0]);
|
||||||
@ -597,7 +597,7 @@ var path = require('path'),
|
|||||||
|
|
||||||
// Gets tags in master branch, sorts them with semver,
|
// Gets tags in master branch, sorts them with semver,
|
||||||
function getTags(callback) {
|
function getTags(callback) {
|
||||||
git(["show-ref", "--tags"], function (results) {
|
git(['show-ref', '--tags'], function (results) {
|
||||||
results = results
|
results = results
|
||||||
.split(/\n+/)
|
.split(/\n+/)
|
||||||
.filter(function (tag) {
|
.filter(function (tag) {
|
||||||
@ -605,8 +605,8 @@ var path = require('path'),
|
|||||||
})
|
})
|
||||||
.map(function (tag) {
|
.map(function (tag) {
|
||||||
return {
|
return {
|
||||||
"tag": tag.split(/tags\//).pop().trim(),
|
'tag': tag.split(/tags\//).pop().trim(),
|
||||||
"ref": tag.split(/\s+/).shift().trim()
|
'ref': tag.split(/\s+/).shift().trim()
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.sort(sortTags);
|
.sort(sortTags);
|
||||||
@ -620,11 +620,11 @@ var path = require('path'),
|
|||||||
var commits = [],
|
var commits = [],
|
||||||
commitRegex =
|
commitRegex =
|
||||||
new RegExp(
|
new RegExp(
|
||||||
"\\n*[|\\*\\s]*commit\\s+([a-f0-9]+)" +
|
'\\n*[|\\*\\s]*commit\\s+([a-f0-9]+)' +
|
||||||
"\\n[|\\*\\s]*Author:\\s+([^<\\n]+)<([^>\\n]+)>" +
|
'\\n[|\\*\\s]*Author:\\s+([^<\\n]+)<([^>\\n]+)>' +
|
||||||
"\\n[|\\*\\s]*Date:\\s+([^\\n]+)" +
|
'\\n[|\\*\\s]*Date:\\s+([^\\n]+)' +
|
||||||
"\\n+[|\\*\\s]*[ ]{4}([^\\n]+)",
|
'\\n+[|\\*\\s]*[ ]{4}([^\\n]+)',
|
||||||
"ig"
|
'ig'
|
||||||
);
|
);
|
||||||
|
|
||||||
// Using String.prototype.replace as a kind of poor-man's substitute
|
// Using String.prototype.replace as a kind of poor-man's substitute
|
||||||
@ -641,16 +641,16 @@ var path = require('path'),
|
|||||||
date =
|
date =
|
||||||
date.replace(
|
date.replace(
|
||||||
/^(\w+)\s(\w+)\s(\d+)\s([\d\:]+)\s(\d+)\s([\+\-\d]+)$/,
|
/^(\w+)\s(\w+)\s(\d+)\s([\d\:]+)\s(\d+)\s([\+\-\d]+)$/,
|
||||||
"$1, $2 $3 $5 $4 $6"
|
'$1, $2 $3 $5 $4 $6'
|
||||||
);
|
);
|
||||||
|
|
||||||
commits.push({
|
commits.push({
|
||||||
"hash": hash,
|
'hash': hash,
|
||||||
"author": author,
|
'author': author,
|
||||||
"email": email,
|
'email': email,
|
||||||
"date": date,
|
'date': date,
|
||||||
"parsedDate": new Date(Date.parse(date)),
|
'parsedDate': new Date(Date.parse(date)),
|
||||||
"message": message
|
'message': message
|
||||||
});
|
});
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -662,8 +662,8 @@ var path = require('path'),
|
|||||||
|
|
||||||
// Gets git log for specified range.
|
// Gets git log for specified range.
|
||||||
function getLog(to, from, callback) {
|
function getLog(to, from, callback) {
|
||||||
var range = from && to ? from + ".." + to : "",
|
var range = from && to ? from + '..' + to : '',
|
||||||
args = [ "log", "master", "--no-color", "--no-merges", "--graph" ];
|
args = [ 'log', 'master', '--no-color', '--no-merges', '--graph' ];
|
||||||
|
|
||||||
if (range) {
|
if (range) {
|
||||||
args.push(range);
|
args.push(range);
|
||||||
@ -676,12 +676,12 @@ var path = require('path'),
|
|||||||
|
|
||||||
// Run the job
|
// Run the job
|
||||||
getTags(function (tags) {
|
getTags(function (tags) {
|
||||||
var logPath = path.join(__dirname, "CHANGELOG.md"),
|
var logPath = path.join(__dirname, 'CHANGELOG.md'),
|
||||||
log = fs.createWriteStream(logPath),
|
log = fs.createWriteStream(logPath),
|
||||||
commitCache = {};
|
commitCache = {};
|
||||||
|
|
||||||
function processTag(tag, callback) {
|
function processTag(tag, callback) {
|
||||||
var buffer = "",
|
var buffer = '',
|
||||||
peek = tag[1];
|
peek = tag[1];
|
||||||
|
|
||||||
tag = tag[0];
|
tag = tag[0];
|
||||||
@ -699,7 +699,7 @@ var path = require('path'),
|
|||||||
return callback("");
|
return callback("");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer += "## Release " + tag.tag + "\n";
|
buffer += '## Release ' + tag.tag + '\n';
|
||||||
|
|
||||||
commits = commits
|
commits = commits
|
||||||
.filter(function (commit) {
|
.filter(function (commit) {
|
||||||
@ -707,12 +707,12 @@ var path = require('path'),
|
|||||||
// Get rid of jenkins' release tagging commits
|
// Get rid of jenkins' release tagging commits
|
||||||
// Remove commits we've already spat out
|
// Remove commits we've already spat out
|
||||||
return (
|
return (
|
||||||
commit.author !== "TryGhost-Jenkins" &&
|
commit.author !== 'TryGhost-Jenkins' &&
|
||||||
!commitCache[commit.hash]
|
!commitCache[commit.hash]
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
.map(function (commit) {
|
.map(function (commit) {
|
||||||
buffer += "\n* " + commit.message + " (_" + commit.author + "_)";
|
buffer += '\n* ' + commit.message + ' (_' + commit.author + '_)';
|
||||||
commitCache[commit.hash] = true;
|
commitCache[commit.hash] = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -720,12 +720,12 @@ var path = require('path'),
|
|||||||
buffer += "\nNo changes were made in this build.\n";
|
buffer += "\nNo changes were made in this build.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(buffer + "\n");
|
callback(buffer + '\n');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get two weeks' worth of tags
|
// Get two weeks' worth of tags
|
||||||
tags.unshift({"tag": "HEAD"});
|
tags.unshift({'tag': 'HEAD'});
|
||||||
|
|
||||||
tags =
|
tags =
|
||||||
tags
|
tags
|
||||||
@ -737,17 +737,17 @@ var path = require('path'),
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
log.write("# Ghost Changelog\n\n");
|
log.write('# Ghost Changelog\n\n');
|
||||||
log.write("_Showing " + tags.length + " releases._\n");
|
log.write('_Showing ' + tags.length + ' releases._\n');
|
||||||
|
|
||||||
when.reduce(tags,
|
when.reduce(tags,
|
||||||
function (prev, tag, idx) {
|
function (prev, tag, idx) {
|
||||||
return when.promise(function (resolve) {
|
return when.promise(function (resolve) {
|
||||||
processTag(tag, function (releaseData) {
|
processTag(tag, function (releaseData) {
|
||||||
resolve(prev + "\n" + releaseData);
|
resolve(prev + '\n' + releaseData);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}, "")
|
}, '')
|
||||||
.then(function (reducedChangelog) {
|
.then(function (reducedChangelog) {
|
||||||
log.write(reducedChangelog);
|
log.write(reducedChangelog);
|
||||||
log.close();
|
log.close();
|
||||||
@ -765,75 +765,75 @@ var path = require('path'),
|
|||||||
* - Zip files in build folder to dist-folder/#{version} directory
|
* - Zip files in build folder to dist-folder/#{version} directory
|
||||||
*/
|
*/
|
||||||
grunt.registerTask("nightly", [
|
grunt.registerTask("nightly", [
|
||||||
"setCurrentBuildType:Nightly",
|
'setCurrentBuildType:Nightly',
|
||||||
"shell:bourbon",
|
'shell:bourbon',
|
||||||
"sass:admin",
|
'sass:admin',
|
||||||
"handlebars",
|
'handlebars',
|
||||||
"concat",
|
'concat',
|
||||||
"uglify",
|
'uglify',
|
||||||
"bump:build",
|
'bump:build',
|
||||||
"updateCurrentPackageInfo",
|
'updateCurrentPackageInfo',
|
||||||
"changelog",
|
'changelog',
|
||||||
"copy:nightly",
|
'copy:nightly',
|
||||||
"compress:nightly"
|
'compress:nightly'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
grunt.registerTask("weekly", [
|
grunt.registerTask("weekly", [
|
||||||
"setCurrentBuildType:Weekly",
|
'setCurrentBuildType:Weekly',
|
||||||
"shell:bourbon",
|
'shell:bourbon',
|
||||||
"sass:admin",
|
'sass:admin',
|
||||||
"handlebars",
|
'handlebars',
|
||||||
"concat",
|
'concat',
|
||||||
"uglify",
|
'uglify',
|
||||||
"bump:build",
|
'bump:build',
|
||||||
"updateCurrentPackageInfo",
|
'updateCurrentPackageInfo',
|
||||||
"changelog",
|
'changelog',
|
||||||
"copy:weekly",
|
'copy:weekly',
|
||||||
"compress:weekly"
|
'compress:weekly'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
grunt.registerTask("build", [
|
grunt.registerTask('build', [
|
||||||
"shell:bourbon",
|
'shell:bourbon',
|
||||||
"sass:admin",
|
'sass:admin',
|
||||||
"handlebars",
|
'handlebars',
|
||||||
"concat",
|
'concat',
|
||||||
"uglify",
|
'uglify',
|
||||||
"changelog",
|
'changelog',
|
||||||
"clean:build",
|
'clean:build',
|
||||||
"copy:build",
|
'copy:build',
|
||||||
"compress:build"
|
'compress:build'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Dev Mode; watch files and restart server on changes
|
// Dev Mode; watch files and restart server on changes
|
||||||
grunt.registerTask("dev", [
|
grunt.registerTask('dev', [
|
||||||
"default",
|
'default',
|
||||||
"express:dev",
|
'express:dev',
|
||||||
"open",
|
'open',
|
||||||
"watch"
|
'watch'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Prepare the project for development
|
// Prepare the project for development
|
||||||
// TODO: Git submodule init/update (https://github.com/jaubourg/grunt-update-submodules)?
|
// TODO: Git submodule init/update (https://github.com/jaubourg/grunt-update-submodules)?
|
||||||
grunt.registerTask("init", ["shell:bourbon", "default"]);
|
grunt.registerTask('init', ['shell:bourbon', 'default']);
|
||||||
|
|
||||||
// Run unit tests
|
// Run unit tests
|
||||||
grunt.registerTask("test-unit", ['setTestEnv', 'loadConfig', "mochacli:all"]);
|
grunt.registerTask('test-unit', ['setTestEnv', 'loadConfig', 'mochacli:all']);
|
||||||
|
|
||||||
// Run casperjs tests only
|
// Run casperjs tests only
|
||||||
grunt.registerTask('test-functional', ['setTestEnv', 'express:test', 'spawn-casperjs']);
|
grunt.registerTask('test-functional', ['setTestEnv', 'express:test', 'spawn-casperjs']);
|
||||||
|
|
||||||
// Run tests and lint code
|
// Run tests and lint code
|
||||||
grunt.registerTask("validate", ["jslint", "test-unit", "test-functional"]);
|
grunt.registerTask('validate', ['jslint', 'test-unit', 'test-functional']);
|
||||||
|
|
||||||
// Generate Docs
|
// Generate Docs
|
||||||
grunt.registerTask("docs", ["groc"]);
|
grunt.registerTask('docs', ['groc']);
|
||||||
|
|
||||||
// TODO: Production build task that minifies with uglify:prod
|
// TODO: Production build task that minifies with uglify:prod
|
||||||
|
|
||||||
grunt.registerTask("prod", ['sass:admin', 'handlebars', 'concat', "uglify"]);
|
grunt.registerTask('prod', ['sass:admin', 'handlebars', 'concat', 'uglify']);
|
||||||
|
|
||||||
// When you just say "grunt"
|
// When you just say 'grunt'
|
||||||
grunt.registerTask("default", ['sass:admin', 'handlebars', 'concat']);
|
grunt.registerTask('default', ['sass:admin', 'handlebars', 'concat']);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = configureGrunt;
|
module.exports = configureGrunt;
|
||||||
|
@ -34,7 +34,9 @@ config = {
|
|||||||
debug: false
|
debug: false
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
// Host to be passed to node's `net.Server#listen()`
|
||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
|
// Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
|
||||||
port: '2368'
|
port: '2368'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -53,7 +55,9 @@ config = {
|
|||||||
debug: false
|
debug: false
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
|
// Host to be passed to node's `net.Server#listen()`
|
||||||
host: '127.0.0.1',
|
host: '127.0.0.1',
|
||||||
|
// Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
|
||||||
port: '2368'
|
port: '2368'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 2bd73d696a53671afe1de0fd5a59a4c22e86b740
|
Subproject commit c4c276653dc751e50fd927bd8c88a72930f4beff
|
@ -23,8 +23,6 @@
|
|||||||
complete: function (result) {
|
complete: function (result) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
$dropzone.trigger("uploadsuccess", [result, $dropzone.attr('id')]);
|
|
||||||
|
|
||||||
function showImage(width, height) {
|
function showImage(width, height) {
|
||||||
$dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"});
|
$dropzone.find('img.js-upload-target').attr({"width": width, "height": height}).css({"display": "block"});
|
||||||
$dropzone.find('.fileupload-loading').remove();
|
$dropzone.find('.fileupload-loading').remove();
|
||||||
@ -137,7 +135,7 @@
|
|||||||
var self = this;
|
var self = this;
|
||||||
//This is the start point if no image exists
|
//This is the start point if no image exists
|
||||||
$dropzone.find('img.js-upload-target').css({"display": "none"});
|
$dropzone.find('img.js-upload-target').css({"display": "none"});
|
||||||
$dropzone.removeClass('pre-image-uploader').addClass('image-uploader');
|
$dropzone.removeClass('pre-image-uploader image-uploader-url').addClass('image-uploader');
|
||||||
this.removeExtras();
|
this.removeExtras();
|
||||||
this.buildExtras();
|
this.buildExtras();
|
||||||
this.bindFileUpload();
|
this.bindFileUpload();
|
||||||
@ -148,6 +146,7 @@
|
|||||||
initUrl: function () {
|
initUrl: function () {
|
||||||
var self = this, val;
|
var self = this, val;
|
||||||
this.removeExtras();
|
this.removeExtras();
|
||||||
|
$dropzone.addClass('image-uploader-url').removeClass('pre-image-uploader');
|
||||||
$dropzone.find('.js-fileupload').addClass('right');
|
$dropzone.find('.js-fileupload').addClass('right');
|
||||||
$dropzone.append($cancel);
|
$dropzone.append($cancel);
|
||||||
$dropzone.find('.js-cancel').on('click', function () {
|
$dropzone.find('.js-cancel').on('click', function () {
|
||||||
@ -163,6 +162,7 @@
|
|||||||
$dropzone.find('div.description').before($url);
|
$dropzone.find('div.description').before($url);
|
||||||
|
|
||||||
$dropzone.find('.js-button-accept').on('click', function () {
|
$dropzone.find('.js-button-accept').on('click', function () {
|
||||||
|
$dropzone.trigger('uploadstart', [$dropzone.attr('id')]);
|
||||||
$dropzone.find('div.description').hide();
|
$dropzone.find('div.description').hide();
|
||||||
val = $('#uploadurl').val();
|
val = $('#uploadurl').val();
|
||||||
$dropzone.find('.js-fileupload').removeClass('right');
|
$dropzone.find('.js-fileupload').removeClass('right');
|
||||||
@ -175,7 +175,7 @@
|
|||||||
var self = this;
|
var self = this;
|
||||||
// This is the start point if an image already exists
|
// This is the start point if an image already exists
|
||||||
source = $dropzone.find('img.js-upload-target').attr('src');
|
source = $dropzone.find('img.js-upload-target').attr('src');
|
||||||
$dropzone.removeClass('image-uploader').addClass('pre-image-uploader');
|
$dropzone.removeClass('image-uploader image-uploader-url').addClass('pre-image-uploader');
|
||||||
$dropzone.find('div.description').hide();
|
$dropzone.find('div.description').hide();
|
||||||
$dropzone.append($cancel);
|
$dropzone.append($cancel);
|
||||||
$dropzone.find('.js-cancel').on('click', function () {
|
$dropzone.find('.js-cancel').on('click', function () {
|
||||||
|
@ -1277,7 +1277,8 @@ main {
|
|||||||
.centre{
|
.centre{
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 50px;
|
top: 50px;
|
||||||
margin-bottom: -6px;
|
display: block;
|
||||||
|
margin: 0 auto -6px auto;
|
||||||
}
|
}
|
||||||
.media {
|
.media {
|
||||||
@include icon($i-image, 60px, darken($lightbrown, 3%)) {
|
@include icon($i-image, 60px, darken($lightbrown, 3%)) {
|
||||||
@ -1408,6 +1409,7 @@ main {
|
|||||||
color: $brown;
|
color: $brown;
|
||||||
background: rgba(0,0,0,0.1);
|
background: rgba(0,0,0,0.1);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
|
min-height: 46px;
|
||||||
|
|
||||||
input {
|
input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/*globals Handlebars, moment
|
/*globals Handlebars, moment
|
||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
Handlebars.registerHelper('date', function (context, block) {
|
Handlebars.registerHelper('date', function (context, block) {
|
||||||
var f = block.hash.format || "MMM Do, YYYY",
|
var f = block.hash.format || 'MMM Do, YYYY',
|
||||||
timeago = block.hash.timeago,
|
timeago = block.hash.timeago,
|
||||||
date;
|
date;
|
||||||
if (timeago) {
|
if (timeago) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*globals window, $, _, Backbone, Validator */
|
/*globals window, $, _, Backbone, Validator */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
var Ghost = {
|
var Ghost = {
|
||||||
Layout : {},
|
Layout : {},
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/*global $, window, CodeMirror, Showdown, moment */
|
/*global $, window, CodeMirror, Showdown, moment */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
var Markdown = {
|
var Markdown = {
|
||||||
init : function (options, elem) {
|
init : function (options, elem) {
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -17,59 +17,59 @@
|
|||||||
replace: function () {
|
replace: function () {
|
||||||
var text = this.elem.getSelection(), pass = true, md, cursor, line, word, letterCount, converter;
|
var text = this.elem.getSelection(), pass = true, md, cursor, line, word, letterCount, converter;
|
||||||
switch (this.style) {
|
switch (this.style) {
|
||||||
case "h1":
|
case 'h1':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
line = this.elem.getLine(cursor.line);
|
line = this.elem.getLine(cursor.line);
|
||||||
this.elem.setLine(cursor.line, "# " + line);
|
this.elem.setLine(cursor.line, '# ' + line);
|
||||||
this.elem.setCursor(cursor.line, cursor.ch + 2);
|
this.elem.setCursor(cursor.line, cursor.ch + 2);
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "h2":
|
case 'h2':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
line = this.elem.getLine(cursor.line);
|
line = this.elem.getLine(cursor.line);
|
||||||
this.elem.setLine(cursor.line, "## " + line);
|
this.elem.setLine(cursor.line, '## ' + line);
|
||||||
this.elem.setCursor(cursor.line, cursor.ch + 3);
|
this.elem.setCursor(cursor.line, cursor.ch + 3);
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "h3":
|
case 'h3':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
line = this.elem.getLine(cursor.line);
|
line = this.elem.getLine(cursor.line);
|
||||||
this.elem.setLine(cursor.line, "### " + line);
|
this.elem.setLine(cursor.line, '### ' + line);
|
||||||
this.elem.setCursor(cursor.line, cursor.ch + 4);
|
this.elem.setCursor(cursor.line, cursor.ch + 4);
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "h4":
|
case 'h4':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
line = this.elem.getLine(cursor.line);
|
line = this.elem.getLine(cursor.line);
|
||||||
this.elem.setLine(cursor.line, "#### " + line);
|
this.elem.setLine(cursor.line, '#### ' + line);
|
||||||
this.elem.setCursor(cursor.line, cursor.ch + 5);
|
this.elem.setCursor(cursor.line, cursor.ch + 5);
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "h5":
|
case 'h5':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
line = this.elem.getLine(cursor.line);
|
line = this.elem.getLine(cursor.line);
|
||||||
this.elem.setLine(cursor.line, "##### " + line);
|
this.elem.setLine(cursor.line, '##### ' + line);
|
||||||
this.elem.setCursor(cursor.line, cursor.ch + 6);
|
this.elem.setCursor(cursor.line, cursor.ch + 6);
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "h6":
|
case 'h6':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
line = this.elem.getLine(cursor.line);
|
line = this.elem.getLine(cursor.line);
|
||||||
this.elem.setLine(cursor.line, "###### " + line);
|
this.elem.setLine(cursor.line, '###### ' + line);
|
||||||
this.elem.setCursor(cursor.line, cursor.ch + 7);
|
this.elem.setCursor(cursor.line, cursor.ch + 7);
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "link":
|
case 'link':
|
||||||
md = this.options.syntax.link.replace('$1', text);
|
md = this.options.syntax.link.replace('$1', text);
|
||||||
this.elem.replaceSelection(md, "end");
|
this.elem.replaceSelection(md, 'end');
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
this.elem.setSelection({line: cursor.line, ch: cursor.ch - 8}, {line: cursor.line, ch: cursor.ch - 1});
|
this.elem.setSelection({line: cursor.line, ch: cursor.ch - 8}, {line: cursor.line, ch: cursor.ch - 1});
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "image":
|
case 'image':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
md = this.options.syntax.image.replace('$1', text);
|
md = this.options.syntax.image.replace('$1', text);
|
||||||
if (this.elem.getLine(cursor.line) !== "") {
|
if (this.elem.getLine(cursor.line) !== '') {
|
||||||
md = "\n\n" + md;
|
md = "\n\n" + md;
|
||||||
}
|
}
|
||||||
this.elem.replaceSelection(md, "end");
|
this.elem.replaceSelection(md, "end");
|
||||||
@ -77,16 +77,16 @@
|
|||||||
this.elem.setSelection({line: cursor.line, ch: cursor.ch - 8}, {line: cursor.line, ch: cursor.ch - 1});
|
this.elem.setSelection({line: cursor.line, ch: cursor.ch - 8}, {line: cursor.line, ch: cursor.ch - 1});
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "uppercase":
|
case 'uppercase':
|
||||||
md = text.toLocaleUpperCase();
|
md = text.toLocaleUpperCase();
|
||||||
break;
|
break;
|
||||||
case "lowercase":
|
case 'lowercase':
|
||||||
md = text.toLocaleLowerCase();
|
md = text.toLocaleLowerCase();
|
||||||
break;
|
break;
|
||||||
case "titlecase":
|
case 'titlecase':
|
||||||
md = text.toTitleCase();
|
md = text.toTitleCase();
|
||||||
break;
|
break;
|
||||||
case "selectword":
|
case 'selectword':
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
word = this.elem.getTokenAt(cursor);
|
word = this.elem.getTokenAt(cursor);
|
||||||
if (!/\w$/g.test(word.string)) {
|
if (!/\w$/g.test(word.string)) {
|
||||||
@ -95,7 +95,7 @@
|
|||||||
this.elem.setSelection({line: cursor.line, ch: word.start}, {line: cursor.line, ch: word.end});
|
this.elem.setSelection({line: cursor.line, ch: word.start}, {line: cursor.line, ch: word.end});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "copyHTML":
|
case 'copyHTML':
|
||||||
converter = new Showdown.converter();
|
converter = new Showdown.converter();
|
||||||
if (text) {
|
if (text) {
|
||||||
md = converter.makeHtml(text);
|
md = converter.makeHtml(text);
|
||||||
@ -106,13 +106,15 @@
|
|||||||
$(".modal-copyToHTML-content").text(md).selectText();
|
$(".modal-copyToHTML-content").text(md).selectText();
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "list":
|
case 'list':
|
||||||
md = text.replace(/^(\s*)(\w\W*)/gm, "$1* $2");
|
md = text.replace(/^(\s*)(\w\W*)/gm, '$1* $2');
|
||||||
this.elem.replaceSelection(md, "end");
|
this.elem.replaceSelection(md, 'end');
|
||||||
pass = false;
|
pass = false;
|
||||||
break;
|
break;
|
||||||
case "currentDate":
|
case 'currentDate':
|
||||||
md = moment(new Date()).format("D MMMM YYYY");
|
md = moment(new Date()).format('D MMMM YYYY');
|
||||||
|
this.elem.replaceSelection(md, 'end');
|
||||||
|
pass = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (this.options.syntax[this.style]) {
|
if (this.options.syntax[this.style]) {
|
||||||
@ -120,7 +122,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pass && md) {
|
if (pass && md) {
|
||||||
this.elem.replaceSelection(md, "end");
|
this.elem.replaceSelection(md, 'end');
|
||||||
if (!text) {
|
if (!text) {
|
||||||
letterCount = md.length;
|
letterCount = md.length;
|
||||||
cursor = this.elem.getCursor();
|
cursor = this.elem.getCursor();
|
||||||
|
@ -3,49 +3,49 @@
|
|||||||
/*global window, document, $, FastClick */
|
/*global window, document, $, FastClick */
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
FastClick.attach(document.body);
|
FastClick.attach(document.body);
|
||||||
|
|
||||||
// ### Show content preview when swiping left on content list
|
// ### Show content preview when swiping left on content list
|
||||||
$(".manage").on("click", ".content-list ol li", function (event) {
|
$('.manage').on('click', '.content-list ol li', function (event) {
|
||||||
if (window.matchMedia('(max-width: 800px)').matches) {
|
if (window.matchMedia('(max-width: 800px)').matches) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
$(".content-list").animate({right: "100%", left: "-100%", 'margin-right': "15px"}, 300);
|
$('.content-list').animate({right: '100%', left: '-100%', 'margin-right': '15px'}, 300);
|
||||||
$(".content-preview").animate({right: "0", left: "0", 'margin-left': "0"}, 300);
|
$('.content-preview').animate({right: '0', left: '0', 'margin-left': '0'}, 300);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ### Hide content preview
|
// ### Hide content preview
|
||||||
$(".manage").on("click", ".content-preview .button-back", function (event) {
|
$('.manage').on('click', '.content-preview .button-back', function (event) {
|
||||||
if (window.matchMedia('(max-width: 800px)').matches) {
|
if (window.matchMedia('(max-width: 800px)').matches) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
$(".content-list").animate({right: "0", left: "0", 'margin-right': "0"}, 300);
|
$('.content-list').animate({right: '0', left: '0', 'margin-right': '0'}, 300);
|
||||||
$(".content-preview").animate({right: "-100%", left: "100%", 'margin-left': "15px"}, 300);
|
$('.content-preview').animate({right: '-100%', left: '100%', 'margin-left': '15px'}, 300);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ### Show settings options page when swiping left on settings menu link
|
// ### Show settings options page when swiping left on settings menu link
|
||||||
$(".settings").on("click", ".settings-menu li", function (event) {
|
$('.settings').on('click', '.settings-menu li', function (event) {
|
||||||
if (window.matchMedia('(max-width: 800px)').matches) {
|
if (window.matchMedia('(max-width: 800px)').matches) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
$(".settings-sidebar").animate({right: "100%", left: "-102%", 'margin-right': "15px"}, 300);
|
$('.settings-sidebar').animate({right: '100%', left: '-102%', 'margin-right': '15px'}, 300);
|
||||||
$(".settings-content").animate({right: "0", left: "0", 'margin-left': "0"}, 300);
|
$('.settings-content').animate({right: '0', left: '0', 'margin-left': '0'}, 300);
|
||||||
$(".settings-content .button-back, .settings-content .button-save").css("display", "inline-block");
|
$('.settings-content .button-back, .settings-content .button-save').css('display', 'inline-block');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// ### Hide settings options page
|
// ### Hide settings options page
|
||||||
$(".settings").on("click", ".settings-content .button-back", function (event) {
|
$('.settings').on('click', '.settings-content .button-back', function (event) {
|
||||||
if (window.matchMedia('(max-width: 800px)').matches) {
|
if (window.matchMedia('(max-width: 800px)').matches) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
$(".settings-sidebar").animate({right: "0", left: "0", 'margin-right': "0"}, 300);
|
$('.settings-sidebar').animate({right: '0', left: '0', 'margin-right': '0'}, 300);
|
||||||
$(".settings-content").animate({right: "-100%", left: "100%", 'margin-left': "15"}, 300);
|
$('.settings-content').animate({right: '-100%', left: '100%', 'margin-left': '15'}, 300);
|
||||||
$(".settings-content .button-back, .settings-content .button-save").css("display", "none");
|
$('.settings-content .button-back, .settings-content .button-save').css('display', 'none');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*global window, document, Ghost, $, _, Backbone */
|
/*global window, document, Ghost, $, _, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
Ghost.Models.Post = Backbone.Model.extend({
|
Ghost.Models.Post = Backbone.Model.extend({
|
||||||
|
|
||||||
@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
parse: function (resp) {
|
parse: function (resp) {
|
||||||
if (resp.status) {
|
if (resp.status) {
|
||||||
resp.published = !!(resp.status === "published");
|
resp.published = !!(resp.status === 'published');
|
||||||
resp.draft = !!(resp.status === "draft");
|
resp.draft = !!(resp.status === 'draft');
|
||||||
}
|
}
|
||||||
if (resp.tags) {
|
if (resp.tags) {
|
||||||
// TODO: parse tags into it's own collection on the model (this.tags)
|
// TODO: parse tags into it's own collection on the model (this.tags)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*global window, document, Ghost, $, _, Backbone */
|
/*global window, document, Ghost, $, _, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
//id:0 is used to issue PUT requests
|
//id:0 is used to issue PUT requests
|
||||||
Ghost.Models.Settings = Backbone.Model.extend({
|
Ghost.Models.Settings = Backbone.Model.extend({
|
||||||
url: Ghost.settings.apiRoot + '/settings/?type=blog,theme',
|
url: Ghost.settings.apiRoot + '/settings/?type=blog,theme',
|
||||||
id: "0"
|
id: '0'
|
||||||
});
|
});
|
||||||
|
|
||||||
}());
|
}());
|
@ -1,6 +1,6 @@
|
|||||||
/*global window, document, Ghost, $, _, Backbone */
|
/*global window, document, Ghost, $, _, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
Ghost.Collections.Tags = Backbone.Collection.extend({
|
Ghost.Collections.Tags = Backbone.Collection.extend({
|
||||||
url: Ghost.settings.apiRoot + '/tags/'
|
url: Ghost.settings.apiRoot + '/tags/'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*global window, document, Ghost, $, _, Backbone */
|
/*global window, document, Ghost, $, _, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
Ghost.Models.Themes = Backbone.Model.extend({
|
Ghost.Models.Themes = Backbone.Model.extend({
|
||||||
url: Ghost.settings.apiRoot + '/themes'
|
url: Ghost.settings.apiRoot + '/themes'
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/*global Ghost, Backbone */
|
/*global Ghost, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
Ghost.Models.uploadModal = Backbone.Model.extend({
|
Ghost.Models.uploadModal = Backbone.Model.extend({
|
||||||
|
|
||||||
options: {
|
options: {
|
||||||
close: true,
|
close: true,
|
||||||
type: "action",
|
type: 'action',
|
||||||
style: ["wide"],
|
style: ["wide"],
|
||||||
animation: 'fade',
|
animation: 'fade',
|
||||||
afterRender: function () {
|
afterRender: function () {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*global window, document, Ghost, $, _, Backbone */
|
/*global window, document, Ghost, $, _, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
Ghost.Models.User = Backbone.Model.extend({
|
Ghost.Models.User = Backbone.Model.extend({
|
||||||
url: Ghost.settings.apiRoot + '/users/me/'
|
url: Ghost.settings.apiRoot + '/users/me/'
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
/*global window, document, Ghost, $, _, Backbone */
|
/*global window, document, Ghost, $, _, Backbone */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
Ghost.Models.Widget = Backbone.Model.extend({
|
Ghost.Models.Widget = Backbone.Model.extend({
|
||||||
|
|
||||||
defaults: {
|
defaults: {
|
||||||
title: "",
|
title: '',
|
||||||
name: "",
|
name: '',
|
||||||
author: "",
|
author: '',
|
||||||
applicationID: "",
|
applicationID: '',
|
||||||
size: "",
|
size: '',
|
||||||
content: {
|
content: {
|
||||||
template: '',
|
template: '',
|
||||||
data: {
|
data: {
|
||||||
@ -17,9 +17,9 @@
|
|||||||
count: 0,
|
count: 0,
|
||||||
sub: {
|
sub: {
|
||||||
value: 0,
|
value: 0,
|
||||||
dir: "", // "up" or "down"
|
dir: '', // "up" or "down"
|
||||||
item: "",
|
item: '',
|
||||||
period: ""
|
period: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -28,8 +28,8 @@
|
|||||||
settingsPane: false,
|
settingsPane: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
options: [{
|
options: [{
|
||||||
title: "ERROR",
|
title: 'ERROR',
|
||||||
value: "Widget options not set"
|
value: 'Widget options not set'
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
/*global document, $, Ghost */
|
/*global document, $, Ghost */
|
||||||
(function () {
|
(function () {
|
||||||
"use strict";
|
'use strict';
|
||||||
|
|
||||||
Ghost.temporary.hideToggles = function () {
|
Ghost.temporary.hideToggles = function () {
|
||||||
$('[data-toggle]').each(function () {
|
$('[data-toggle]').each(function () {
|
||||||
@ -11,7 +11,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Toggle active classes on menu headers
|
// Toggle active classes on menu headers
|
||||||
$("[data-toggle].active").removeClass("active");
|
$('[data-toggle].active').removeClass('active');
|
||||||
};
|
};
|
||||||
|
|
||||||
Ghost.temporary.initToggles = function ($el) {
|
Ghost.temporary.initToggles = function ($el) {
|
||||||
|
@ -281,7 +281,7 @@
|
|||||||
this.addSubview(new PublishBar({el: "#publish-bar", model: this.model})).render();
|
this.addSubview(new PublishBar({el: "#publish-bar", model: this.model})).render();
|
||||||
|
|
||||||
this.$('#entry-title').val(this.model.get('title')).focus();
|
this.$('#entry-title').val(this.model.get('title')).focus();
|
||||||
this.$('#entry-markdown').html(this.model.get('markdown'));
|
this.$('#entry-markdown').text(this.model.get('markdown'));
|
||||||
|
|
||||||
this.initMarkdown();
|
this.initMarkdown();
|
||||||
this.renderPreview();
|
this.renderPreview();
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
when = require('when');
|
url = require('url'),
|
||||||
|
when = require('when'),
|
||||||
|
errors = require('./server/errorHandling');
|
||||||
|
|
||||||
function writeConfigFile() {
|
function writeConfigFile() {
|
||||||
var written = when.defer();
|
var written = when.defer();
|
||||||
@ -11,19 +13,19 @@ function writeConfigFile() {
|
|||||||
write;
|
write;
|
||||||
|
|
||||||
if (!templateExists) {
|
if (!templateExists) {
|
||||||
throw new Error('Could not locate a configuration file. Please check your deployment for config.js or config.example.js.');
|
return errors.logError(new Error('Could not locate a configuration file.'), process.cwd(), 'Please check your deployment for config.js or config.example.js.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy config.example.js => config.js
|
// Copy config.example.js => config.js
|
||||||
read = fs.createReadStream('config.example.js');
|
read = fs.createReadStream('config.example.js');
|
||||||
read.on('error', function (err) {
|
read.on('error', function (err) {
|
||||||
throw new Error('Could not open config.example.js for read.');
|
return errors.logError(new Error('Could not open config.example.js for read.'), process.cwd(), 'Please check your deployment for config.js or config.example.js.');
|
||||||
});
|
});
|
||||||
read.on('end', written.resolve);
|
read.on('end', written.resolve);
|
||||||
|
|
||||||
write = fs.createWriteStream('config.js');
|
write = fs.createWriteStream('config.js');
|
||||||
write.on('error', function (err) {
|
write.on('error', function (err) {
|
||||||
throw new Error('Could not open config.js for write.');
|
return errors.logError(new Error('Could not open config.js for write.'), process.cwd(), 'Please check your deployment for config.js or config.example.js.');
|
||||||
});
|
});
|
||||||
|
|
||||||
read.pipe(write);
|
read.pipe(write);
|
||||||
@ -32,15 +34,54 @@ function writeConfigFile() {
|
|||||||
return written.promise;
|
return written.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateConfigEnvironment() {
|
||||||
|
var envVal = process.env.NODE_ENV || 'undefined',
|
||||||
|
config,
|
||||||
|
parsedUrl;
|
||||||
|
|
||||||
|
try {
|
||||||
|
config = require('../config')[envVal];
|
||||||
|
} catch (ignore) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we don't even have a config
|
||||||
|
if (!config) {
|
||||||
|
errors.logError(new Error('Cannot find the configuration for the current NODE_ENV'), "NODE_ENV=" + envVal, 'Ensure your config.js has a section for the current NODE_ENV value');
|
||||||
|
return when.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that our url is valid
|
||||||
|
parsedUrl = url.parse(config.url || 'invalid');
|
||||||
|
if (!parsedUrl.protocol || !parsedUrl.host) {
|
||||||
|
errors.logError(new Error('Your site url in config.js is invalid.'), config.url, 'Please make sure this is a valid url before restarting');
|
||||||
|
return when.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that we have database values
|
||||||
|
if (!config.database) {
|
||||||
|
errors.logError(new Error('Your database configuration in config.js is invalid.'), JSON.stringify(config.database), 'Please make sure this is a valid Bookshelf database configuration');
|
||||||
|
return when.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for valid server host and port values
|
||||||
|
if (!config.server || !config.server.host || !config.server.port) {
|
||||||
|
errors.logError(new Error('Your server values (host and port) in config.js are invalid.'), JSON.stringify(config.server), 'Please provide them before restarting.');
|
||||||
|
return when.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return when.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
exports.loadConfig = function () {
|
exports.loadConfig = function () {
|
||||||
var loaded = when.defer();
|
var loaded = when.defer();
|
||||||
/* Check for config file and copy from config.example.js
|
/* Check for config file and copy from config.example.js
|
||||||
if one doesn't exist. After that, start the server. */
|
if one doesn't exist. After that, start the server. */
|
||||||
fs.exists('config.js', function checkConfig(configExists) {
|
fs.exists('config.js', function checkConfig(configExists) {
|
||||||
if (configExists) {
|
if (configExists) {
|
||||||
loaded.resolve();
|
validateConfigEnvironment().then(loaded.resolve).otherwise(loaded.reject);
|
||||||
} else {
|
} else {
|
||||||
writeConfigFile().then(loaded.resolve).otherwise(loaded.reject);
|
writeConfigFile().then(validateConfigEnvironment).then(loaded.resolve).otherwise(loaded.reject);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return loaded.promise;
|
return loaded.promise;
|
||||||
|
@ -2,28 +2,28 @@
|
|||||||
// Defines core methods required to build the application
|
// Defines core methods required to build the application
|
||||||
|
|
||||||
// Module dependencies
|
// Module dependencies
|
||||||
var config = require('../config'),
|
var config = require('../config'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
express = require('express'),
|
express = require('express'),
|
||||||
errors = require('./server/errorHandling'),
|
errors = require('./server/errorHandling'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
hbs = require('express-hbs'),
|
hbs = require('express-hbs'),
|
||||||
nodefn = require('when/node/function'),
|
nodefn = require('when/node/function'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
Polyglot = require('node-polyglot'),
|
Polyglot = require('node-polyglot'),
|
||||||
Mailer = require('./server/mail'),
|
Mailer = require('./server/mail'),
|
||||||
models = require('./server/models'),
|
models = require('./server/models'),
|
||||||
plugins = require('./server/plugins'),
|
plugins = require('./server/plugins'),
|
||||||
requireTree = require('./server/require-tree'),
|
requireTree = require('./server/require-tree'),
|
||||||
permissions = require('./server/permissions'),
|
permissions = require('./server/permissions'),
|
||||||
uuid = require('node-uuid'),
|
uuid = require('node-uuid'),
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
appRoot = path.resolve(__dirname, '../'),
|
appRoot = path.resolve(__dirname, '../'),
|
||||||
themePath = path.resolve(appRoot + '/content/themes'),
|
themePath = path.resolve(appRoot + '/content/themes'),
|
||||||
pluginPath = path.resolve(appRoot + '/content/plugins'),
|
pluginPath = path.resolve(appRoot + '/content/plugins'),
|
||||||
themeDirectories = requireTree(themePath),
|
themeDirectories = requireTree(themePath),
|
||||||
pluginDirectories = requireTree(pluginPath),
|
pluginDirectories = requireTree(pluginPath),
|
||||||
|
|
||||||
Ghost,
|
Ghost,
|
||||||
@ -111,7 +111,7 @@ Ghost = function () {
|
|||||||
'appRoot': appRoot,
|
'appRoot': appRoot,
|
||||||
'themePath': themePath,
|
'themePath': themePath,
|
||||||
'pluginPath': pluginPath,
|
'pluginPath': pluginPath,
|
||||||
'activeTheme': path.join(themePath, !instance.settingsCache ? "" : instance.settingsCache.activeTheme.value),
|
'activeTheme': path.join(themePath, !instance.settingsCache ? '' : instance.settingsCache.activeTheme.value),
|
||||||
'adminViews': path.join(appRoot, '/core/server/views/'),
|
'adminViews': path.join(appRoot, '/core/server/views/'),
|
||||||
'helperTemplates': path.join(appRoot, '/core/server/helpers/tpl/'),
|
'helperTemplates': path.join(appRoot, '/core/server/helpers/tpl/'),
|
||||||
'lang': path.join(appRoot, '/core/shared/lang/'),
|
'lang': path.join(appRoot, '/core/shared/lang/'),
|
||||||
@ -130,14 +130,14 @@ Ghost.prototype.init = function () {
|
|||||||
|
|
||||||
function doFirstRun() {
|
function doFirstRun() {
|
||||||
var firstRunMessage = [
|
var firstRunMessage = [
|
||||||
"Welcome to Ghost.",
|
'Welcome to Ghost.',
|
||||||
"You're running under the <strong>",
|
'You\'re running under the <strong>',
|
||||||
process.env.NODE_ENV,
|
process.env.NODE_ENV,
|
||||||
"</strong>environment.",
|
'</strong>environment.',
|
||||||
|
|
||||||
"Your URL is set to",
|
'Your URL is set to',
|
||||||
"<strong>" + self.config().url + "</strong>.",
|
'<strong>' + self.config().url + '</strong>.',
|
||||||
"See <a href=\"http://docs.ghost.org/\">http://docs.ghost.org</a> for instructions."
|
'See <a href="http://docs.ghost.org/">http://docs.ghost.org</a> for instructions.'
|
||||||
];
|
];
|
||||||
|
|
||||||
self.notifications.push({
|
self.notifications.push({
|
||||||
@ -165,14 +165,13 @@ Ghost.prototype.init = function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ### Initialisation
|
// ### Initialisation
|
||||||
// make sure things are done in order
|
|
||||||
return when.join(
|
return when.join(
|
||||||
// Initialise the models
|
// Initialise the models
|
||||||
instance.dataProvider.init(),
|
self.dataProvider.init(),
|
||||||
// Calculate paths
|
// Calculate paths
|
||||||
instance.getPaths(),
|
self.getPaths(),
|
||||||
// Initialise mail after first run
|
// Initialise mail after first run
|
||||||
instance.mail.init(self)
|
self.mail.init(self)
|
||||||
).then(function () {
|
).then(function () {
|
||||||
// Populate any missing default settings
|
// Populate any missing default settings
|
||||||
return models.Settings.populateDefaults();
|
return models.Settings.populateDefaults();
|
||||||
@ -183,7 +182,7 @@ Ghost.prototype.init = function () {
|
|||||||
return when.join(
|
return when.join(
|
||||||
// Check for or initialise a dbHash.
|
// Check for or initialise a dbHash.
|
||||||
initDbHashAndFirstRun(),
|
initDbHashAndFirstRun(),
|
||||||
// Initialize plugins
|
// Initialize plugins
|
||||||
self.initPlugins(),
|
self.initPlugins(),
|
||||||
// Initialize the permissions actions and objects
|
// Initialize the permissions actions and objects
|
||||||
permissions.init()
|
permissions.init()
|
||||||
@ -261,7 +260,7 @@ Ghost.prototype.loadTemplate = function (name) {
|
|||||||
var self = this,
|
var self = this,
|
||||||
templateFileName = name + '.hbs',
|
templateFileName = name + '.hbs',
|
||||||
// Check for theme specific version first
|
// Check for theme specific version first
|
||||||
templatePath = path.join(this.paths().activeTheme, "partials", templateFileName),
|
templatePath = path.join(this.paths().activeTheme, 'partials', templateFileName),
|
||||||
deferred = when.defer();
|
deferred = when.defer();
|
||||||
|
|
||||||
// Can't use nodefn here because exists just returns one parameter, true or false
|
// Can't use nodefn here because exists just returns one parameter, true or false
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
// Module dependencies
|
// Module dependencies
|
||||||
var express = require('express'),
|
var express = require('express'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
colors = require("colors"),
|
colors = require('colors'),
|
||||||
semver = require("semver"),
|
semver = require('semver'),
|
||||||
slashes = require("connect-slashes"),
|
slashes = require('connect-slashes'),
|
||||||
errors = require('./server/errorHandling'),
|
errors = require('./server/errorHandling'),
|
||||||
admin = require('./server/controllers/admin'),
|
admin = require('./server/controllers/admin'),
|
||||||
frontend = require('./server/controllers/frontend'),
|
frontend = require('./server/controllers/frontend'),
|
||||||
api = require('./server/api'),
|
api = require('./server/api'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
hbs = require('express-hbs'),
|
hbs = require('express-hbs'),
|
||||||
Ghost = require('./ghost'),
|
Ghost = require('./ghost'),
|
||||||
helpers = require('./server/helpers'),
|
helpers = require('./server/helpers'),
|
||||||
packageInfo = require('../package.json'),
|
packageInfo = require('../package.json'),
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
@ -112,7 +112,8 @@ function ghostLocals(req, res, next) {
|
|||||||
_.extend(res.locals, {
|
_.extend(res.locals, {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
name: currentUser.attributes.name,
|
name: currentUser.attributes.name,
|
||||||
profile: currentUser.attributes.image
|
email: currentUser.attributes.email,
|
||||||
|
image: currentUser.attributes.image
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
next();
|
next();
|
||||||
@ -128,8 +129,8 @@ function ghostLocals(req, res, next) {
|
|||||||
// Disable any caching until it can be done properly
|
// Disable any caching until it can be done properly
|
||||||
function disableCachedResult(req, res, next) {
|
function disableCachedResult(req, res, next) {
|
||||||
res.set({
|
res.set({
|
||||||
"Cache-Control": "no-cache, must-revalidate",
|
'Cache-Control': 'no-cache, must-revalidate',
|
||||||
"Expires": "Sat, 26 Jul 1997 05:00:00 GMT"
|
'Expires': 'Sat, 26 Jul 1997 05:00:00 GMT'
|
||||||
});
|
});
|
||||||
|
|
||||||
next();
|
next();
|
||||||
@ -222,13 +223,15 @@ function manageAdminAndTheme(req, res, next) {
|
|||||||
// Expose the promise we will resolve after our pre-loading
|
// Expose the promise we will resolve after our pre-loading
|
||||||
ghost.loaded = loading.promise;
|
ghost.loaded = loading.promise;
|
||||||
|
|
||||||
when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () {
|
when(ghost.init()).then(function () {
|
||||||
|
return helpers.loadCoreHelpers(ghost);
|
||||||
|
}).then(function () {
|
||||||
|
|
||||||
// ##Configuration
|
// ##Configuration
|
||||||
var oneYear = 31536000000;
|
var oneYear = 31536000000;
|
||||||
|
|
||||||
// Logging configuration
|
// Logging configuration
|
||||||
if (server.get('env') !== "development") {
|
if (server.get('env') !== 'development') {
|
||||||
server.use(express.logger());
|
server.use(express.logger());
|
||||||
} else {
|
} else {
|
||||||
server.use(express.logger('dev'));
|
server.use(express.logger('dev'));
|
||||||
@ -243,7 +246,7 @@ when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () {
|
|||||||
server.use('/shared', express['static'](path.join(__dirname, '/shared')));
|
server.use('/shared', express['static'](path.join(__dirname, '/shared')));
|
||||||
server.use('/content/images', express['static'](path.join(__dirname, '/../content/images')));
|
server.use('/content/images', express['static'](path.join(__dirname, '/../content/images')));
|
||||||
// Serve our built scripts; can't use /scripts here because themes already are
|
// Serve our built scripts; can't use /scripts here because themes already are
|
||||||
server.use("/built/scripts", express['static'](path.join(__dirname, '/built/scripts'), {
|
server.use('/built/scripts', express['static'](path.join(__dirname, '/built/scripts'), {
|
||||||
// Put a maxAge of one year on built scripts
|
// Put a maxAge of one year on built scripts
|
||||||
maxAge: oneYear
|
maxAge: oneYear
|
||||||
}));
|
}));
|
||||||
@ -264,6 +267,7 @@ when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () {
|
|||||||
server.use(express.urlencoded());
|
server.use(express.urlencoded());
|
||||||
server.use('/ghost/upload/', express.multipart());
|
server.use('/ghost/upload/', express.multipart());
|
||||||
server.use('/ghost/upload/', express.multipart({uploadDir: __dirname + '/content/images'}));
|
server.use('/ghost/upload/', express.multipart({uploadDir: __dirname + '/content/images'}));
|
||||||
|
server.use('/ghost/debug/db/import/', express.multipart());
|
||||||
server.use(express.cookieParser(ghost.dbHash));
|
server.use(express.cookieParser(ghost.dbHash));
|
||||||
server.use(express.cookieSession({ cookie: { maxAge: 60000000 }}));
|
server.use(express.cookieSession({ cookie: { maxAge: 60000000 }}));
|
||||||
|
|
||||||
@ -339,7 +343,11 @@ when.all([ghost.init(), helpers.loadCoreHelpers(ghost)]).then(function () {
|
|||||||
server.get('/ghost/debug/db/reset/', auth, admin.debug.reset);
|
server.get('/ghost/debug/db/reset/', auth, admin.debug.reset);
|
||||||
// We don't want to register bodyParser globally b/c of security concerns, so use multipart only here
|
// We don't want to register bodyParser globally b/c of security concerns, so use multipart only here
|
||||||
server.post('/ghost/upload/', admin.uploader);
|
server.post('/ghost/upload/', admin.uploader);
|
||||||
server.get(/^\/(ghost$|(ghost-admin|admin|wp-admin|dashboard|signin)\/?)/, auth, function (req, res) {
|
// redirect to /ghost and let that do the authentication to prevent redirects to /ghost//admin etc.
|
||||||
|
server.get(/^\/((ghost-admin|admin|wp-admin|dashboard|signin)\/?)/, function (req, res) {
|
||||||
|
res.redirect('/ghost/');
|
||||||
|
});
|
||||||
|
server.get(/^\/(ghost$\/?)/, auth, function (req, res) {
|
||||||
res.redirect('/ghost/');
|
res.redirect('/ghost/');
|
||||||
});
|
});
|
||||||
server.get('/ghost/', redirectToSignup, auth, admin.index);
|
server.get('/ghost/', redirectToSignup, auth, admin.index);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
// # Ghost Data API
|
// # Ghost Data API
|
||||||
// Provides access to the data model
|
// Provides access to the data model
|
||||||
|
|
||||||
var Ghost = require('../ghost'),
|
var Ghost = require('../ghost'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
errors = require('./errorHandling'),
|
errors = require('./errorHandling'),
|
||||||
permissions = require('./permissions'),
|
permissions = require('./permissions'),
|
||||||
canThis = permissions.canThis,
|
canThis = permissions.canThis,
|
||||||
|
|
||||||
ghost = new Ghost(),
|
ghost = new Ghost(),
|
||||||
dataProvider = ghost.dataProvider,
|
dataProvider = ghost.dataProvider,
|
||||||
posts,
|
posts,
|
||||||
users,
|
users,
|
||||||
@ -228,7 +228,7 @@ settingsCollection = function (settings) {
|
|||||||
settingsFilter = function (settings, filter) {
|
settingsFilter = function (settings, filter) {
|
||||||
return _.object(_.filter(_.pairs(settings), function (setting) {
|
return _.object(_.filter(_.pairs(settings), function (setting) {
|
||||||
if (filter) {
|
if (filter) {
|
||||||
return _.some(filter.split(","), function (f) {
|
return _.some(filter.split(','), function (f) {
|
||||||
return setting[1].type === f;
|
return setting[1].type === f;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
var Ghost = require('../../ghost'),
|
var Ghost = require('../../ghost'),
|
||||||
dataExport = require('../data/export'),
|
dataExport = require('../data/export'),
|
||||||
dataImport = require('../data/import'),
|
dataImport = require('../data/import'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
fs = require('fs-extra'),
|
fs = require('fs-extra'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
nodefn = require('when/node/function'),
|
nodefn = require('when/node/function'),
|
||||||
api = require('../api'),
|
api = require('../api'),
|
||||||
moment = require('moment'),
|
moment = require('moment'),
|
||||||
errors = require('../errorHandling'),
|
errors = require('../errorHandling'),
|
||||||
|
|
||||||
ghost = new Ghost(),
|
ghost = new Ghost(),
|
||||||
dataProvider = ghost.dataProvider,
|
dataProvider = ghost.dataProvider,
|
||||||
adminNavbar,
|
adminNavbar,
|
||||||
adminControllers,
|
adminControllers,
|
||||||
loginSecurity = [];
|
loginSecurity = [];
|
||||||
@ -269,8 +269,8 @@ adminControllers = {
|
|||||||
|
|
||||||
// TODO: Centralise list/enumeration of settings panes, so we don't
|
// TODO: Centralise list/enumeration of settings panes, so we don't
|
||||||
// run into trouble in future.
|
// run into trouble in future.
|
||||||
var allowedSections = ["", "general", "user"],
|
var allowedSections = ['', 'general', 'user'],
|
||||||
section = req.url.replace(/(^\/ghost\/settings[\/]*|\/$)/ig, "");
|
section = req.url.replace(/(^\/ghost\/settings[\/]*|\/$)/ig, '');
|
||||||
|
|
||||||
if (allowedSections.indexOf(section) < 0) {
|
if (allowedSections.indexOf(section) < 0) {
|
||||||
return next();
|
return next();
|
||||||
@ -312,7 +312,7 @@ adminControllers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return api.notifications.add(notification).then(function () {
|
return api.notifications.add(notification).then(function () {
|
||||||
res.redirect("/ghost/debug/");
|
res.redirect('/ghost/debug/');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -327,16 +327,16 @@ adminControllers = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return api.notifications.add(notification).then(function () {
|
return api.notifications.add(notification).then(function () {
|
||||||
res.redirect("/ghost/debug/");
|
res.redirect('/ghost/debug/');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the current version for importing
|
// Get the current version for importing
|
||||||
api.settings.read({ key: "databaseVersion" })
|
api.settings.read({ key: 'databaseVersion' })
|
||||||
.then(function (setting) {
|
.then(function (setting) {
|
||||||
return when(setting.value);
|
return when(setting.value);
|
||||||
}, function () {
|
}, function () {
|
||||||
return when("001");
|
return when('001');
|
||||||
})
|
})
|
||||||
.then(function (databaseVersion) {
|
.then(function (databaseVersion) {
|
||||||
// Read the file contents
|
// Read the file contents
|
||||||
|
@ -4,14 +4,16 @@
|
|||||||
|
|
||||||
/*global require, module */
|
/*global require, module */
|
||||||
|
|
||||||
var Ghost = require('../../ghost'),
|
var Ghost = require('../../ghost'),
|
||||||
api = require('../api'),
|
api = require('../api'),
|
||||||
RSS = require('rss'),
|
RSS = require('rss'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
errors = require('../errorHandling'),
|
errors = require('../errorHandling'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
|
url = require('url'),
|
||||||
|
|
||||||
ghost = new Ghost(),
|
|
||||||
|
ghost = new Ghost(),
|
||||||
frontendControllers;
|
frontendControllers;
|
||||||
|
|
||||||
frontendControllers = {
|
frontendControllers = {
|
||||||
@ -24,7 +26,7 @@ frontendControllers = {
|
|||||||
// No negative pages
|
// No negative pages
|
||||||
if (isNaN(pageParam) || pageParam < 1) {
|
if (isNaN(pageParam) || pageParam < 1) {
|
||||||
//redirect to 404 page?
|
//redirect to 404 page?
|
||||||
return res.redirect("/");
|
return res.redirect('/');
|
||||||
}
|
}
|
||||||
options.page = pageParam;
|
options.page = pageParam;
|
||||||
|
|
||||||
@ -87,14 +89,14 @@ frontendControllers = {
|
|||||||
description: ghost.settings('description'),
|
description: ghost.settings('description'),
|
||||||
generator: 'Ghost v' + res.locals.version,
|
generator: 'Ghost v' + res.locals.version,
|
||||||
author: user ? user.attributes.name : null,
|
author: user ? user.attributes.name : null,
|
||||||
feed_url: siteUrl + '/rss/',
|
feed_url: url.resolve(siteUrl, '/rss/'),
|
||||||
site_url: siteUrl,
|
site_url: siteUrl,
|
||||||
ttl: '60'
|
ttl: '60'
|
||||||
});
|
});
|
||||||
|
|
||||||
// No negative pages
|
// No negative pages
|
||||||
if (isNaN(pageParam) || pageParam < 1) {
|
if (isNaN(pageParam) || pageParam < 1) {
|
||||||
return res.redirect("/rss/");
|
return res.redirect('/rss/');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageParam === 1 && req.route.path === '/rss/:page/') {
|
if (pageParam === 1 && req.route.path === '/rss/:page/') {
|
||||||
@ -112,22 +114,30 @@ frontendControllers = {
|
|||||||
|
|
||||||
// If page is greater than number of pages we have, redirect to last page
|
// If page is greater than number of pages we have, redirect to last page
|
||||||
if (pageParam > maxPage) {
|
if (pageParam > maxPage) {
|
||||||
return res.redirect("/rss/" + maxPage + "/");
|
return res.redirect('/rss/' + maxPage + '/');
|
||||||
}
|
}
|
||||||
|
|
||||||
ghost.doFilter('prePostsRender', page.posts, function (posts) {
|
ghost.doFilter('prePostsRender', page.posts, function (posts) {
|
||||||
posts.forEach(function (post) {
|
posts.forEach(function (post) {
|
||||||
var item = {
|
var item = {
|
||||||
title: _.escape(post.title),
|
title: _.escape(post.title),
|
||||||
guid: post.uuid,
|
guid: post.uuid,
|
||||||
url: siteUrl + '/' + post.slug + '/',
|
url: siteUrl + '/' + post.slug + '/',
|
||||||
date: post.published_at
|
date: post.published_at,
|
||||||
};
|
},
|
||||||
|
content = post.html;
|
||||||
if (post.meta_description !== null) {
|
|
||||||
item.push({ description: post.meta_description });
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//set img src to absolute url
|
||||||
|
content = content.replace(/src=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
|
||||||
|
p1 = url.resolve(siteUrl, p1);
|
||||||
|
return "src='" + p1 + "' ";
|
||||||
|
});
|
||||||
|
//set a href to absolute url
|
||||||
|
content = content.replace(/href=["|'|\s]?([\w\/\?\$\.\+\-;%:@&=,_]+)["|'|\s]?/gi, function (match, p1) {
|
||||||
|
p1 = url.resolve(siteUrl, p1);
|
||||||
|
return "href='" + p1 + "' ";
|
||||||
|
});
|
||||||
|
item.description = content;
|
||||||
feed.item(item);
|
feed.item(item);
|
||||||
});
|
});
|
||||||
res.set('Content-Type', 'text/xml');
|
res.set('Content-Type', 'text/xml');
|
||||||
@ -138,6 +148,7 @@ frontendControllers = {
|
|||||||
return next(new Error(err));
|
return next(new Error(err));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = frontendControllers;
|
module.exports = frontendControllers;
|
@ -1,8 +1,8 @@
|
|||||||
var when = require('when'),
|
var when = require('when'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
migration = require('../migration'),
|
migration = require('../migration'),
|
||||||
client = require('../../models/base').client,
|
client = require('../../models/base').client,
|
||||||
knex = require('../../models/base').Knex,
|
knex = require('../../models/base').Knex,
|
||||||
|
|
||||||
exporter;
|
exporter;
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ function getTablesFromSqlite3() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTablesFromMySQL() {
|
function getTablesFromMySQL() {
|
||||||
knex.Raw("show tables").then(function (response) {
|
return knex.Raw('show tables').then(function (response) {
|
||||||
return _.flatten(_.map(response, function (entry) {
|
return _.flatten(_.map(response, function (entry) {
|
||||||
return _.values(entry);
|
return _.values(entry);
|
||||||
}));
|
}));
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
var sequence = require('when/sequence'),
|
var sequence = require('when/sequence'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
Post = require('../../models/post').Post,
|
Post = require('../../models/post').Post,
|
||||||
Tag = require('../../models/tag').Tag,
|
Tag = require('../../models/tag').Tag,
|
||||||
Role = require('../../models/role').Role,
|
Role = require('../../models/role').Role,
|
||||||
Permission = require('../../models/permission').Permission,
|
Permission = require('../../models/permission').Permission,
|
||||||
uuid = require('node-uuid');
|
uuid = require('node-uuid');
|
||||||
|
|
||||||
var fixtures = {
|
var fixtures = {
|
||||||
posts: [
|
posts: [
|
||||||
@ -12,7 +12,7 @@ var fixtures = {
|
|||||||
"title": "Welcome to Ghost",
|
"title": "Welcome to Ghost",
|
||||||
"slug": "welcome-to-ghost",
|
"slug": "welcome-to-ghost",
|
||||||
"markdown": "You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!\n\n## Getting Started\n\nWriting in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use *formatting* shortcuts to style your content. For example, a list:\n\n* Item number one\n* Item number two\n * A nested item\n* A final item\n\nor with numbers!\n\n1. Remember to buy some milk\n2. Drink the milk\n3. Tweet that I remembered to buy the milk, and drank it\n\n### Links\n\nWant to link to a source? No problem. If you paste in url, like http://ghost.org - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to [the Ghost website](http://ghost.org). Neat.\n\n### What about Images?\n\nImages work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:\n\n![The Ghost Logo](http://tryghost.org/ghost.png)\n\nNot sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:\n\n![A bowl of bananas]\n\n\n### Quoting\n\nSometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.\n\n> Wisdomous - it's definitely a word.\n\n### Working with Code\n\nGot a streak of geek? We've got you covered there, too. You can write inline `<code>` blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.\n\n .awesome-thing {\n display: block;\n width: 100%;\n }\n\n### Ready for a Break? \n\nThrow 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.\n\n---\n\n### Advanced Usage\n\nThere's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.\n\n<input type=\"text\" placeholder=\"I'm an input field!\" />\n\nThat should be enough to get you started. Have fun - and let us know what you think :)",
|
"markdown": "You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!\n\n## Getting Started\n\nWriting in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use *formatting* shortcuts to style your content. For example, a list:\n\n* Item number one\n* Item number two\n * A nested item\n* A final item\n\nor with numbers!\n\n1. Remember to buy some milk\n2. Drink the milk\n3. Tweet that I remembered to buy the milk, and drank it\n\n### Links\n\nWant to link to a source? No problem. If you paste in url, like http://ghost.org - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to [the Ghost website](http://ghost.org). Neat.\n\n### What about Images?\n\nImages work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:\n\n![The Ghost Logo](http://tryghost.org/ghost.png)\n\nNot sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:\n\n![A bowl of bananas]\n\n\n### Quoting\n\nSometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.\n\n> Wisdomous - it's definitely a word.\n\n### Working with Code\n\nGot a streak of geek? We've got you covered there, too. You can write inline `<code>` blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.\n\n .awesome-thing {\n display: block;\n width: 100%;\n }\n\n### Ready for a Break? \n\nThrow 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.\n\n---\n\n### Advanced Usage\n\nThere's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.\n\n<input type=\"text\" placeholder=\"I'm an input field!\" />\n\nThat should be enough to get you started. Have fun - and let us know what you think :)",
|
||||||
"html": "<p>You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!</p>\n\n<h2 id=\"gettingstarted\">Getting Started</h2>\n\n<p>Writing in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use <em>formatting</em> shortcuts to style your content. For example, a list:</p>\n\n<ul>\n<li>Item number one</li>\n<li>Item number two\n<ul><li>A nested item</li></ul></li>\n<li>A final item</li>\n</ul>\n\n<p>or with numbers!</p>\n\n<ol>\n<li>Remember to buy some milk </li>\n<li>Drink the milk </li>\n<li>Tweet that I remembered to buy the milk, and drank it</li>\n</ol>\n\n<h3 id=\"links\">Links</h3>\n\n<p>Want to link to a source? No problem. If you paste in url, like <a href='http://ghost.org'>http://ghost.org</a> - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to <a href=\"http://ghost.org\">the Ghost website</a>. Neat.</p>\n\n<h3 id=\"whataboutimages\">What about Images?</h3>\n\n<p>Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:</p>\n\n<p><img src=\"http://tryghost.org/ghost.png\" alt=\"The Ghost Logo\" /></p>\n\n<p>Not sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:</p>\n\n<p><img src=\"undefined\" alt=\"A bowl of bananas\" /></p>\n\n<h3 id=\"quoting\">Quoting</h3>\n\n<p>Sometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.</p>\n\n<blockquote>\n <p>Wisdomous - it's definitely a word.</p>\n</blockquote>\n\n<h3 id=\"workingwithcode\">Working with Code</h3>\n\n<p>Got a streak of geek? We've got you covered there, too. You can write inline <code><code></code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.</p>\n\n<pre><code>.awesome-thing {\n display: block;\n width: 100%;\n}\n</code></pre>\n\n<h3 id=\"readyforabreak\">Ready for a Break?</h3>\n\n<p>Throw 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.</p>\n\n<hr />\n\n<h3 id=\"advancedusage\">Advanced Usage</h3>\n\n<p>There's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.</p>\n\n<p><input type=\"text\" placeholder=\"I'm an input field!\" /></p>\n\n<p>That should be enough to get you started. Have fun - and let us know what you think :)</p>",
|
"html": "<p>You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!</p>\n\n<h2 id=\"gettingstarted\">Getting Started</h2>\n\n<p>Writing in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use <em>formatting</em> shortcuts to style your content. For example, a list:</p>\n\n<ul>\n<li>Item number one</li>\n<li>Item number two\n<ul><li>A nested item</li></ul></li>\n<li>A final item</li>\n</ul>\n\n<p>or with numbers!</p>\n\n<ol>\n<li>Remember to buy some milk </li>\n<li>Drink the milk </li>\n<li>Tweet that I remembered to buy the milk, and drank it</li>\n</ol>\n\n<h3 id=\"links\">Links</h3>\n\n<p>Want to link to a source? No problem. If you paste in url, like <a href='http://ghost.org'>http://ghost.org</a> - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to <a href=\"http://ghost.org\">the Ghost website</a>. Neat.</p>\n\n<h3 id=\"whataboutimages\">What about Images?</h3>\n\n<p>Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:</p>\n\n<p><img src=\"http://tryghost.org/ghost.png\" alt=\"The Ghost Logo\" /></p>\n\n<p>Not sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:</p>\n\n<h3 id=\"quoting\">Quoting</h3>\n\n<p>Sometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.</p>\n\n<blockquote>\n <p>Wisdomous - it's definitely a word.</p>\n</blockquote>\n\n<h3 id=\"workingwithcode\">Working with Code</h3>\n\n<p>Got a streak of geek? We've got you covered there, too. You can write inline <code><code></code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.</p>\n\n<pre><code>.awesome-thing {\n display: block;\n width: 100%;\n}\n</code></pre>\n\n<h3 id=\"readyforabreak\">Ready for a Break?</h3>\n\n<p>Throw 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.</p>\n\n<hr />\n\n<h3 id=\"advancedusage\">Advanced Usage</h3>\n\n<p>There's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.</p>\n\n<p><input type=\"text\" placeholder=\"I'm an input field!\" /></p>\n\n<p>That should be enough to get you started. Have fun - and let us know what you think :)</p>",
|
||||||
"image": null,
|
"image": null,
|
||||||
"featured": false,
|
"featured": false,
|
||||||
"page": false,
|
"page": false,
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
var when = require("when"),
|
var when = require('when'),
|
||||||
_ = require("underscore"),
|
_ = require('underscore'),
|
||||||
models = require('../../models'),
|
models = require('../../models'),
|
||||||
errors = require('../../errorHandling'),
|
errors = require('../../errorHandling'),
|
||||||
Importer000;
|
Importer000;
|
||||||
|
|
||||||
|
|
||||||
Importer000 = function () {
|
Importer000 = function () {
|
||||||
_.bindAll(this, "basicImport");
|
_.bindAll(this, 'basicImport');
|
||||||
|
|
||||||
this.version = "000";
|
this.version = '000';
|
||||||
|
|
||||||
this.importFrom = {
|
this.importFrom = {
|
||||||
"000": this.basicImport,
|
'000': this.basicImport,
|
||||||
"001": this.tempImport,
|
'001': this.tempImport,
|
||||||
"002": this.tempImport
|
'002': this.tempImport
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,7 +81,12 @@ function preProcessPostTags(tableData) {
|
|||||||
function importTags(ops, tableData) {
|
function importTags(ops, tableData) {
|
||||||
tableData = stripProperties(['id'], tableData);
|
tableData = stripProperties(['id'], tableData);
|
||||||
_.each(tableData, function (tag) {
|
_.each(tableData, function (tag) {
|
||||||
ops.push(models.Tag.add(tag));
|
ops.push(models.Tag.read({name: tag.name}).then(function (_tag) {
|
||||||
|
if (!_tag) {
|
||||||
|
return models.Tag.add(tag);
|
||||||
|
}
|
||||||
|
return when.resolve(_tag);
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ module.exports = function (version, data) {
|
|||||||
var importer;
|
var importer;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
importer = require("./" + version);
|
importer = require('./' + version);
|
||||||
} catch (ignore) {
|
} catch (ignore) {
|
||||||
// Zero effs given
|
// Zero effs given
|
||||||
}
|
}
|
||||||
|
@ -131,22 +131,22 @@ up = function () {
|
|||||||
|
|
||||||
down = function () {
|
down = function () {
|
||||||
return when.all([
|
return when.all([
|
||||||
knex.Schema.dropTableIfExists("posts"),
|
knex.Schema.dropTableIfExists('posts_tags'),
|
||||||
knex.Schema.dropTableIfExists("users"),
|
knex.Schema.dropTableIfExists('roles_users'),
|
||||||
knex.Schema.dropTableIfExists("roles"),
|
knex.Schema.dropTableIfExists('permissions_users'),
|
||||||
knex.Schema.dropTableIfExists("settings"),
|
knex.Schema.dropTableIfExists('permissions_roles'),
|
||||||
knex.Schema.dropTableIfExists("permissions"),
|
knex.Schema.dropTableIfExists('users')
|
||||||
knex.Schema.dropTableIfExists("tags")
|
|
||||||
]).then(function () {
|
]).then(function () {
|
||||||
// Drop the relation tables after the model tables
|
|
||||||
return when.all([
|
return when.all([
|
||||||
knex.Schema.dropTableIfExists("roles_users"),
|
knex.Schema.dropTableIfExists('roles'),
|
||||||
knex.Schema.dropTableIfExists("permissions_users"),
|
knex.Schema.dropTableIfExists('settings'),
|
||||||
knex.Schema.dropTableIfExists("permissions_roles"),
|
knex.Schema.dropTableIfExists('permissions'),
|
||||||
knex.Schema.dropTableIfExists("posts_tags")
|
knex.Schema.dropTableIfExists('tags'),
|
||||||
|
knex.Schema.dropTableIfExists('posts')
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.up = up;
|
exports.up = up;
|
||||||
exports.down = down;
|
exports.down = down;
|
@ -1,15 +1,15 @@
|
|||||||
|
|
||||||
var _ = require('underscore'),
|
var _ = require('underscore'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
series = require('when/sequence'),
|
series = require('when/sequence'),
|
||||||
errors = require('../../errorHandling'),
|
errors = require('../../errorHandling'),
|
||||||
knex = require('../../models/base').Knex,
|
knex = require('../../models/base').Knex,
|
||||||
|
|
||||||
defaultSettings = require('../default-settings'),
|
defaultSettings = require('../default-settings'),
|
||||||
Settings = require('../../models/settings').Settings,
|
Settings = require('../../models/settings').Settings,
|
||||||
fixtures = require('../fixtures'),
|
fixtures = require('../fixtures'),
|
||||||
|
|
||||||
initialVersion = '000',
|
initialVersion = '000',
|
||||||
defaultDatabaseVersion;
|
defaultDatabaseVersion;
|
||||||
|
|
||||||
// Default Database Version
|
// Default Database Version
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
/*jslint regexp: true */
|
/*jslint regexp: true */
|
||||||
var _ = require('underscore'),
|
var _ = require('underscore'),
|
||||||
colors = require("colors"),
|
colors = require('colors'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
errors,
|
errors,
|
||||||
|
|
||||||
// Paths for views
|
// Paths for views
|
||||||
appRoot = path.resolve(__dirname, '../'),
|
appRoot = path.resolve(__dirname, '../'),
|
||||||
themePath = path.resolve(appRoot + '/content/themes'),
|
themePath = path.resolve(appRoot + '/content/themes'),
|
||||||
adminTemplatePath = path.resolve(appRoot + '/server/views/'),
|
adminTemplatePath = path.resolve(appRoot + '/server/views/'),
|
||||||
defaultErrorTemplatePath = path.resolve(adminTemplatePath + '/user-error.hbs'),
|
defaultErrorTemplatePath = path.resolve(adminTemplatePath + '/user-error.hbs'),
|
||||||
userErrorTemplatePath = path.resolve(themePath + '/error.hbs'),
|
userErrorTemplatePath = path.resolve(themePath + '/error.hbs'),
|
||||||
userErrorTemplateExists;
|
userErrorTemplateExists;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,14 +31,14 @@ errors = {
|
|||||||
|
|
||||||
logError: function (err, context, help) {
|
logError: function (err, context, help) {
|
||||||
var stack = err ? err.stack : null;
|
var stack = err ? err.stack : null;
|
||||||
err = err.message || err || "Unknown";
|
err = err.message || err || 'Unknown';
|
||||||
// TODO: Logging framework hookup
|
// TODO: Logging framework hookup
|
||||||
// Eventually we'll have better logging which will know about envs
|
// Eventually we'll have better logging which will know about envs
|
||||||
if ((process.env.NODE_ENV === 'development' ||
|
if ((process.env.NODE_ENV === 'development' ||
|
||||||
process.env.NODE_ENV === 'staging' ||
|
process.env.NODE_ENV === 'staging' ||
|
||||||
process.env.NODE_ENV === 'production')) {
|
process.env.NODE_ENV === 'production')) {
|
||||||
|
|
||||||
console.error("\nERROR:".red, err.red);
|
console.error('\nERROR:'.red, err.red);
|
||||||
|
|
||||||
if (context) {
|
if (context) {
|
||||||
console.error(context);
|
console.error(context);
|
||||||
@ -49,10 +49,10 @@ errors = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add a new line
|
// add a new line
|
||||||
console.error("");
|
console.error('');
|
||||||
|
|
||||||
if (stack) {
|
if (stack) {
|
||||||
console.error(stack, "\n");
|
console.error(stack, '\n');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -84,7 +84,7 @@ errors = {
|
|||||||
renderErrorPage: function (code, err, req, res, next) {
|
renderErrorPage: function (code, err, req, res, next) {
|
||||||
|
|
||||||
function parseStack(stack) {
|
function parseStack(stack) {
|
||||||
if (typeof stack !== "string") {
|
if (typeof stack !== 'string') {
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,8 +102,8 @@ errors = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"function": parts[1],
|
'function': parts[1],
|
||||||
"at": parts[2]
|
'at': parts[2]
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.filter(function (line) {
|
.filter(function (line) {
|
||||||
@ -116,12 +116,12 @@ errors = {
|
|||||||
function renderErrorInt(errorView) {
|
function renderErrorInt(errorView) {
|
||||||
var stack = null;
|
var stack = null;
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== "production" && err.stack) {
|
if (process.env.NODE_ENV !== 'production' && err.stack) {
|
||||||
stack = parseStack(err.stack);
|
stack = parseStack(err.stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Attach node-polyglot
|
// TODO: Attach node-polyglot
|
||||||
res.render((errorView || "error"), {
|
res.render((errorView || 'error'), {
|
||||||
message: err.message || err,
|
message: err.message || err,
|
||||||
code: code,
|
code: code,
|
||||||
stack: stack
|
stack: stack
|
||||||
@ -177,13 +177,13 @@ errors = {
|
|||||||
// Ensure our 'this' context in the functions
|
// Ensure our 'this' context in the functions
|
||||||
_.bindAll(
|
_.bindAll(
|
||||||
errors,
|
errors,
|
||||||
"throwError",
|
'throwError',
|
||||||
"logError",
|
'logError',
|
||||||
"logAndThrowError",
|
'logAndThrowError',
|
||||||
"logErrorWithRedirect",
|
'logErrorWithRedirect',
|
||||||
"renderErrorPage",
|
'renderErrorPage',
|
||||||
"render404Page",
|
'render404Page',
|
||||||
"render500Page"
|
'render500Page'
|
||||||
);
|
);
|
||||||
|
|
||||||
module.exports = errors;
|
module.exports = errors;
|
@ -1,18 +1,18 @@
|
|||||||
var _ = require('underscore'),
|
var _ = require('underscore'),
|
||||||
moment = require('moment'),
|
moment = require('moment'),
|
||||||
downsize = require('downsize'),
|
downsize = require('downsize'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
hbs = require('express-hbs'),
|
hbs = require('express-hbs'),
|
||||||
packageInfo = require('../../../package.json'),
|
packageInfo = require('../../../package.json'),
|
||||||
errors = require('../errorHandling'),
|
errors = require('../errorHandling'),
|
||||||
models = require('../models'),
|
models = require('../models'),
|
||||||
coreHelpers;
|
coreHelpers;
|
||||||
|
|
||||||
|
|
||||||
coreHelpers = function (ghost) {
|
coreHelpers = function (ghost) {
|
||||||
var paginationHelper,
|
var paginationHelper,
|
||||||
scriptTemplate = _.template("<script src='/built/scripts/<%= name %>?v=<%= version %>'></script>"),
|
scriptTemplate = _.template("<script src='/built/scripts/<%= name %>?v=<%= version %>'></script>"),
|
||||||
isProduction = process.env.NODE_ENV === "production",
|
isProduction = process.env.NODE_ENV === 'production',
|
||||||
version = encodeURIComponent(packageInfo.version);
|
version = encodeURIComponent(packageInfo.version);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,7 +34,7 @@ coreHelpers = function (ghost) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var f = options.hash.format || "MMM Do, YYYY",
|
var f = options.hash.format || 'MMM Do, YYYY',
|
||||||
timeago = options.hash.timeago,
|
timeago = options.hash.timeago,
|
||||||
date;
|
date;
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ coreHelpers = function (ghost) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (models.isPost(this)) {
|
if (models.isPost(this)) {
|
||||||
output += "/" + this.slug + '/';
|
output += '/' + this.slug + '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
@ -91,7 +91,7 @@ coreHelpers = function (ghost) {
|
|||||||
// if the author could not be determined.
|
// if the author could not be determined.
|
||||||
//
|
//
|
||||||
ghost.registerThemeHelper('author', function (context, options) {
|
ghost.registerThemeHelper('author', function (context, options) {
|
||||||
return this.author ? this.author.name : "";
|
return this.author ? this.author.name : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
// ### Tags Helper
|
// ### Tags Helper
|
||||||
@ -106,10 +106,10 @@ coreHelpers = function (ghost) {
|
|||||||
// Note that the standard {{#each tags}} implementation is unaffected by this helper
|
// Note that the standard {{#each tags}} implementation is unaffected by this helper
|
||||||
// and can be used for more complex templates.
|
// and can be used for more complex templates.
|
||||||
ghost.registerThemeHelper('tags', function (options) {
|
ghost.registerThemeHelper('tags', function (options) {
|
||||||
var separator = ", ",
|
var separator = ', ',
|
||||||
tagNames;
|
tagNames;
|
||||||
|
|
||||||
if (typeof options.hash.separator === "string") {
|
if (typeof options.hash.separator === 'string') {
|
||||||
separator = options.hash.separator;
|
separator = options.hash.separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ coreHelpers = function (ghost) {
|
|||||||
//
|
//
|
||||||
ghost.registerThemeHelper('content', function (options) {
|
ghost.registerThemeHelper('content', function (options) {
|
||||||
var truncateOptions = (options || {}).hash || {};
|
var truncateOptions = (options || {}).hash || {};
|
||||||
truncateOptions = _.pick(truncateOptions, ["words", "characters"]);
|
truncateOptions = _.pick(truncateOptions, ['words', 'characters']);
|
||||||
|
|
||||||
if (truncateOptions.words || truncateOptions.characters) {
|
if (truncateOptions.words || truncateOptions.characters) {
|
||||||
return new hbs.handlebars.SafeString(
|
return new hbs.handlebars.SafeString(
|
||||||
@ -162,10 +162,10 @@ coreHelpers = function (ghost) {
|
|||||||
var truncateOptions = (options || {}).hash || {},
|
var truncateOptions = (options || {}).hash || {},
|
||||||
excerpt;
|
excerpt;
|
||||||
|
|
||||||
truncateOptions = _.pick(truncateOptions, ["words", "characters"]);
|
truncateOptions = _.pick(truncateOptions, ['words', 'characters']);
|
||||||
|
|
||||||
/*jslint regexp:true */
|
/*jslint regexp:true */
|
||||||
excerpt = String(this.html).replace(/<\/?[^>]+>/gi, "");
|
excerpt = String(this.html).replace(/<\/?[^>]+>/gi, '');
|
||||||
/*jslint regexp:false */
|
/*jslint regexp:false */
|
||||||
|
|
||||||
if (!truncateOptions.words && !truncateOptions.characters) {
|
if (!truncateOptions.words && !truncateOptions.characters) {
|
||||||
@ -198,7 +198,7 @@ coreHelpers = function (ghost) {
|
|||||||
var classes = ['post'];
|
var classes = ['post'];
|
||||||
|
|
||||||
if (this.tags) {
|
if (this.tags) {
|
||||||
classes = classes.concat(this.tags.map(function (tag) { return "tag-" + tag.name; }));
|
classes = classes.concat(this.tags.map(function (tag) { return 'tag-' + tag.name; }));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghost.doFilter('post_class', classes, function (classes) {
|
return ghost.doFilter('post_class', classes, function (classes) {
|
||||||
@ -208,12 +208,15 @@ coreHelpers = function (ghost) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
ghost.registerThemeHelper('ghost_head', function (options) {
|
ghost.registerThemeHelper('ghost_head', function (options) {
|
||||||
var head = [];
|
var head = [],
|
||||||
head.push('<meta name="generator" content="Ghost ' + this.version + '" />');
|
majorMinor = /^(\d+\.)?(\d+)/,
|
||||||
|
trimmedVersion = this.version.match(majorMinor)[0];
|
||||||
|
|
||||||
|
head.push('<meta name="generator" content="Ghost ' + trimmedVersion + '" />');
|
||||||
head.push('<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
head.push('<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
||||||
|
|
||||||
return ghost.doFilter('ghost_head', head, function (head) {
|
return ghost.doFilter('ghost_head', head, function (head) {
|
||||||
var headString = _.reduce(head, function (memo, item) { return memo + "\n" + item; }, '');
|
var headString = _.reduce(head, function (memo, item) { return memo + '\n' + item; }, '');
|
||||||
return new hbs.handlebars.SafeString(headString.trim());
|
return new hbs.handlebars.SafeString(headString.trim());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -292,7 +295,7 @@ coreHelpers = function (ghost) {
|
|||||||
j = 0,
|
j = 0,
|
||||||
columns = options.hash.columns,
|
columns = options.hash.columns,
|
||||||
key,
|
key,
|
||||||
ret = "",
|
ret = '',
|
||||||
data;
|
data;
|
||||||
|
|
||||||
if (options.data) {
|
if (options.data) {
|
||||||
@ -356,18 +359,18 @@ coreHelpers = function (ghost) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// A helper for inserting the javascript tags with version hashes
|
// A helper for inserting the javascript tags with version hashes
|
||||||
ghost.registerThemeHelper("ghostScriptTags", function () {
|
ghost.registerThemeHelper('ghostScriptTags', function () {
|
||||||
var scriptFiles = [];
|
var scriptFiles = [];
|
||||||
|
|
||||||
if (isProduction) {
|
if (isProduction) {
|
||||||
scriptFiles.push("ghost.min.js");
|
scriptFiles.push("ghost.min.js");
|
||||||
} else {
|
} else {
|
||||||
scriptFiles = [
|
scriptFiles = [
|
||||||
"vendor.js",
|
'vendor.js',
|
||||||
"helpers.js",
|
'helpers.js',
|
||||||
"templates.js",
|
'templates.js',
|
||||||
"models.js",
|
'models.js',
|
||||||
"views.js"
|
'views.js'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +381,7 @@ coreHelpers = function (ghost) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return scriptFiles.join("");
|
return scriptFiles.join('');
|
||||||
});
|
});
|
||||||
|
|
||||||
// ## Template driven helpers
|
// ## Template driven helpers
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
var cp = require('child_process'),
|
var cp = require('child_process'),
|
||||||
url = require('url'),
|
url = require('url'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
nodefn = require('when/node/function'),
|
nodefn = require('when/node/function'),
|
||||||
nodemailer = require('nodemailer');
|
nodemailer = require('nodemailer');
|
||||||
|
|
||||||
function GhostMailer(opts) {
|
function GhostMailer(opts) {
|
||||||
@ -51,7 +51,7 @@ GhostMailer.prototype.detectSendmail = function () {
|
|||||||
if (err && !/bin\/sendmail/.test(stdout)) {
|
if (err && !/bin\/sendmail/.test(stdout)) {
|
||||||
return reject();
|
return reject();
|
||||||
}
|
}
|
||||||
resolve(stdout.toString());
|
resolve(stdout.toString().replace(/(\n|\r|\r\n)$/, ''));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
var GhostBookshelf,
|
var GhostBookshelf,
|
||||||
Bookshelf = require('bookshelf'),
|
Bookshelf = require('bookshelf'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
moment = require('moment'),
|
moment = require('moment'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
uuid = require('node-uuid'),
|
uuid = require('node-uuid'),
|
||||||
config = require('../../../config'),
|
config = require('../../../config'),
|
||||||
Validator = require('validator').Validator;
|
Validator = require('validator').Validator;
|
||||||
|
|
||||||
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up
|
// Initializes Bookshelf as its own instance, so we can modify the Models and not mess up
|
||||||
@ -70,7 +70,7 @@ GhostBookshelf.Model = GhostBookshelf.Model.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_.each(relations, function (relation, key) {
|
_.each(relations, function (relation, key) {
|
||||||
if (key.substring(0, 7) !== "_pivot_") {
|
if (key.substring(0, 7) !== '_pivot_') {
|
||||||
attrs[key] = relation.toJSON ? relation.toJSON() : relation;
|
attrs[key] = relation.toJSON ? relation.toJSON() : relation;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -126,7 +126,7 @@ GhostBookshelf.Model = GhostBookshelf.Model.extend({
|
|||||||
|
|
||||||
//if slug is empty after trimming use "post"
|
//if slug is empty after trimming use "post"
|
||||||
if (!slug) {
|
if (!slug) {
|
||||||
slug = "post";
|
slug = 'post';
|
||||||
}
|
}
|
||||||
// Test for duplicate slugs.
|
// Test for duplicate slugs.
|
||||||
return checkIfSlugExists(slug);
|
return checkIfSlugExists(slug);
|
||||||
|
@ -16,7 +16,7 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
isPost: function (jsonData) {
|
isPost: function (jsonData) {
|
||||||
return jsonData.hasOwnProperty("html") && jsonData.hasOwnProperty("markdown")
|
return jsonData.hasOwnProperty('html') && jsonData.hasOwnProperty('markdown')
|
||||||
&& jsonData.hasOwnProperty("title") && jsonData.hasOwnProperty("slug");
|
&& jsonData.hasOwnProperty('title') && jsonData.hasOwnProperty('slug');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var GhostBookshelf = require('./base'),
|
var GhostBookshelf = require('./base'),
|
||||||
User = require('./user').User,
|
User = require('./user').User,
|
||||||
Role = require('./role').Role,
|
Role = require('./role').Role,
|
||||||
Permission,
|
Permission,
|
||||||
Permissions;
|
Permissions;
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ Post = GhostBookshelf.Model.extend({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (tagsToAttach) {
|
if (!_.isEmpty(tagsToAttach)) {
|
||||||
return Tags.forge().query('whereIn', 'name', _.pluck(tagsToAttach, 'name')).fetch().then(function (matchingTags) {
|
return Tags.forge().query('whereIn', 'name', _.pluck(tagsToAttach, 'name')).fetch().then(function (matchingTags) {
|
||||||
_.each(matchingTags.toJSON(), function (matchingTag) {
|
_.each(matchingTags.toJSON(), function (matchingTag) {
|
||||||
tagOperations.push(self.tags().attach(matchingTag.id));
|
tagOperations.push(self.tags().attach(matchingTag.id));
|
||||||
@ -173,7 +173,7 @@ Post = GhostBookshelf.Model.extend({
|
|||||||
// Extends base model findAll to eager-fetch author and user relationships.
|
// Extends base model findAll to eager-fetch author and user relationships.
|
||||||
findAll: function (options) {
|
findAll: function (options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.withRelated = [ "author", "user", "tags" ];
|
options.withRelated = [ 'author', 'user', 'tags' ];
|
||||||
return GhostBookshelf.Model.findAll.call(this, options);
|
return GhostBookshelf.Model.findAll.call(this, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -181,7 +181,7 @@ Post = GhostBookshelf.Model.extend({
|
|||||||
// Extends base model findOne to eager-fetch author and user relationships.
|
// Extends base model findOne to eager-fetch author and user relationships.
|
||||||
findOne: function (args, options) {
|
findOne: function (args, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
options.withRelated = [ "author", "user", "tags" ];
|
options.withRelated = [ 'author', 'user', 'tags' ];
|
||||||
return GhostBookshelf.Model.findOne.call(this, args, options);
|
return GhostBookshelf.Model.findOne.call(this, args, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -235,7 +235,7 @@ Post = GhostBookshelf.Model.extend({
|
|||||||
postCollection.query('where', opts.where);
|
postCollection.query('where', opts.where);
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.withRelated = [ "author", "user", "tags" ];
|
opts.withRelated = [ 'author', 'user', 'tags' ];
|
||||||
|
|
||||||
// Set the limit & offset for the query, fetching
|
// Set the limit & offset for the query, fetching
|
||||||
// with the opts (to specify any eager relations, etc.)
|
// with the opts (to specify any eager relations, etc.)
|
||||||
@ -332,6 +332,19 @@ Post = GhostBookshelf.Model.extend({
|
|||||||
// associated models can't be created until the post has an ID, so run this after
|
// associated models can't be created until the post has an ID, so run this after
|
||||||
return post.updateTags(newPostData.tags);
|
return post.updateTags(newPostData.tags);
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
destroy: function (_identifier, options) {
|
||||||
|
options = options || {};
|
||||||
|
return this.forge({id: _identifier}).fetch({withRelated: ['tags']}).then(function destroyTags(post) {
|
||||||
|
var tagIds = _.pluck(post.related('tags').toJSON(), 'id');
|
||||||
|
if (tagIds) {
|
||||||
|
return post.tags().detach(tagIds).then(function destroyPost() {
|
||||||
|
return post.destroy(options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return post.destroy(options);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
var User = require('./user').User,
|
var User = require('./user').User,
|
||||||
Permission = require('./permission').Permission,
|
Permission = require('./permission').Permission,
|
||||||
GhostBookshelf = require('./base'),
|
GhostBookshelf = require('./base'),
|
||||||
Role,
|
Role,
|
||||||
Roles;
|
Roles;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
var Settings,
|
var Settings,
|
||||||
GhostBookshelf = require('./base'),
|
GhostBookshelf = require('./base'),
|
||||||
validator = GhostBookshelf.validator,
|
validator = GhostBookshelf.validator,
|
||||||
uuid = require('node-uuid'),
|
uuid = require('node-uuid'),
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
errors = require('../errorHandling'),
|
errors = require('../errorHandling'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
defaultSettings;
|
defaultSettings;
|
||||||
|
|
||||||
// For neatness, the defaults file is split into categories.
|
// For neatness, the defaults file is split into categories.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
var Tag,
|
var Tag,
|
||||||
Tags,
|
Tags,
|
||||||
Posts = require('./post').Posts,
|
Posts = require('./post').Posts,
|
||||||
GhostBookshelf = require('./base');
|
GhostBookshelf = require('./base');
|
||||||
|
|
||||||
Tag = GhostBookshelf.Model.extend({
|
Tag = GhostBookshelf.Model.extend({
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
var User,
|
var User,
|
||||||
Users,
|
Users,
|
||||||
_ = require('underscore'),
|
_ = require('underscore'),
|
||||||
uuid = require('node-uuid'),
|
uuid = require('node-uuid'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
errors = require('../errorHandling'),
|
errors = require('../errorHandling'),
|
||||||
nodefn = require('when/node/function'),
|
nodefn = require('when/node/function'),
|
||||||
bcrypt = require('bcrypt-nodejs'),
|
bcrypt = require('bcrypt-nodejs'),
|
||||||
Posts = require('./post').Posts,
|
Posts = require('./post').Posts,
|
||||||
GhostBookshelf = require('./base'),
|
GhostBookshelf = require('./base'),
|
||||||
Role = require('./role').Role,
|
Role = require('./role').Role,
|
||||||
Permission = require('./permission').Permission;
|
Permission = require('./permission').Permission;
|
||||||
|
|
||||||
|
|
||||||
function validatePasswordLength(password) {
|
function validatePasswordLength(password) {
|
||||||
try {
|
try {
|
||||||
GhostBookshelf.validator.check(password, "Your password is not long enough. It must be at least 8 characters long.").len(8);
|
GhostBookshelf.validator.check(password, "Your must be at least 8 characters long.").len(8);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return when.reject(error);
|
return when.reject(error);
|
||||||
}
|
}
|
||||||
@ -33,10 +33,10 @@ User = GhostBookshelf.Model.extend({
|
|||||||
],
|
],
|
||||||
|
|
||||||
validate: function () {
|
validate: function () {
|
||||||
GhostBookshelf.validator.check(this.get('email'), "Please check your email address. It does not seem to be valid.").isEmail();
|
GhostBookshelf.validator.check(this.get('email'), "Please enter a valid email address. That one looks a bit dodgy.").isEmail();
|
||||||
GhostBookshelf.validator.check(this.get('bio'), "Your bio is too long. Please keep it to 200 chars.").len(0, 200);
|
GhostBookshelf.validator.check(this.get('bio'), "We're not writing a novel here! I'm afraid your bio has to stay under 200 characters.").len(0, 200);
|
||||||
if (this.get('website') && this.get('website').length > 0) {
|
if (this.get('website') && this.get('website').length > 0) {
|
||||||
GhostBookshelf.validator.check(this.get('website'), "Your website is not a valid URL.").isUrl();
|
GhostBookshelf.validator.check(this.get('website'), "Looks like your website is not actually a website. Try again?").isUrl();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
// canThis(someUser).edit.posts([id]|[[ids]])
|
// canThis(someUser).edit.posts([id]|[[ids]])
|
||||||
// canThis(someUser).edit.post(somePost|somePostId)
|
// canThis(someUser).edit.post(somePost|somePostId)
|
||||||
|
|
||||||
var _ = require('underscore'),
|
var _ = require('underscore'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
Models = require('../models'),
|
Models = require('../models'),
|
||||||
objectTypeModelMap = require('./objectTypeModelMap'),
|
objectTypeModelMap = require('./objectTypeModelMap'),
|
||||||
UserProvider = Models.User,
|
UserProvider = Models.User,
|
||||||
PermissionsProvider = Models.Permission,
|
PermissionsProvider = Models.Permission,
|
||||||
init,
|
init,
|
||||||
refresh,
|
refresh,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
'post': require('../models/post').Post,
|
'post': require('../models/post').Post,
|
||||||
'role': require('../models/role').Role,
|
'role': require('../models/role').Role,
|
||||||
'user': require('../models/user').User,
|
'user': require('../models/user').User,
|
||||||
'permission': require('../models/permission').Permission,
|
'permission': require('../models/permission').Permission,
|
||||||
'setting': require('../models/settings').Settings
|
'setting': require('../models/settings').Settings
|
||||||
};
|
};
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
var _ = require("underscore"),
|
var _ = require('underscore'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
ghostApi,
|
ghostApi,
|
||||||
loader = require("./loader"),
|
loader = require('./loader'),
|
||||||
GhostPlugin = require("./GhostPlugin");
|
GhostPlugin = require('./GhostPlugin');
|
||||||
|
|
||||||
function getInstalledPlugins() {
|
function getInstalledPlugins() {
|
||||||
if (!ghostApi) {
|
if (!ghostApi) {
|
||||||
ghostApi = require('../api');
|
ghostApi = require('../api');
|
||||||
}
|
}
|
||||||
|
|
||||||
return ghostApi.settings.read("installedPlugins").then(function (installed) {
|
return ghostApi.settings.read('installedPlugins').then(function (installed) {
|
||||||
installed.value = installed.value || "[]";
|
installed.value = installed.value || '[]';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
installed = JSON.parse(installed.value);
|
installed = JSON.parse(installed.value);
|
||||||
@ -27,7 +27,7 @@ function saveInstalledPlugins(installedPlugins) {
|
|||||||
return getInstalledPlugins().then(function (currentInstalledPlugins) {
|
return getInstalledPlugins().then(function (currentInstalledPlugins) {
|
||||||
var updatedPluginsInstalled = _.uniq(installedPlugins.concat(currentInstalledPlugins));
|
var updatedPluginsInstalled = _.uniq(installedPlugins.concat(currentInstalledPlugins));
|
||||||
|
|
||||||
return ghostApi.settings.edit("installedPlugins", updatedPluginsInstalled);
|
return ghostApi.settings.edit('installedPlugins', updatedPluginsInstalled);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
var path = require("path"),
|
var path = require('path'),
|
||||||
_ = require("underscore"),
|
_ = require('underscore'),
|
||||||
when = require("when"),
|
when = require('when'),
|
||||||
ghostInstance,
|
ghostInstance,
|
||||||
loader;
|
loader;
|
||||||
|
|
||||||
@ -10,7 +10,7 @@ function getGhostInstance() {
|
|||||||
return ghostInstance;
|
return ghostInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
var Ghost = require("../../ghost");
|
var Ghost = require('../../ghost');
|
||||||
|
|
||||||
ghostInstance = new Ghost();
|
ghostInstance = new Ghost();
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
var when = require('when'),
|
var when = require('when'),
|
||||||
keys = require('when/keys'),
|
keys = require('when/keys'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
path = require('path'),
|
path = require('path'),
|
||||||
extend = function (obj, source) {
|
extend = function (obj, source) {
|
||||||
var key;
|
var key;
|
||||||
for (key in source) {
|
for (key in source) {
|
||||||
|
@ -34,15 +34,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</form>
|
</form>
|
||||||
<form id="settings-resetdb">
|
|
||||||
<fieldset>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>Reset Database</label>
|
|
||||||
<a href="/ghost/debug/db/reset/" class="button-delete">Reset</a>
|
|
||||||
<p>Delete the entire database so you can start again with empty tables</p>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</form>
|
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
<li id="usermenu" class="subnav">
|
<li id="usermenu" class="subnav">
|
||||||
<a href="#" data-toggle="ul" class="dropdown">
|
<a href="#" data-toggle="ul" class="dropdown">
|
||||||
<img class="avatar" src="{{#if currentUser.profile}}{{currentUser.profile}}{{else}}/shared/img/user-image.png{{/if}}" alt="Avatar" />
|
<img class="avatar" src="{{#if currentUser.image}}{{currentUser.image}}{{else}}/shared/img/user-image.png{{/if}}" alt="Avatar" />
|
||||||
<span class="name">{{#if currentUser.name}}{{currentUser.name}}{{else}}Ghost{{/if}}</span>
|
<span class="name">{{#if currentUser.name}}{{currentUser.name}}{{else}}{{currentUser.email}}{{/if}}</span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="overlay">
|
<ul class="overlay">
|
||||||
<li class="usermenu-profile"><a href="/ghost/settings/user/">Your Profile</a></li>
|
<li class="usermenu-profile"><a href="/ghost/settings/user/">Your Profile</a></li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li class="usermenu-help"><a href="http://forum.tryghost.org">Help / Support</a></li>
|
<li class="usermenu-help"><a href="http://ghost.org/forum/">Help / Support</a></li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li class="usermenu-signout"><a href="/signout/">Sign Out</a></li>
|
<li class="usermenu-signout"><a href="/signout/">Sign Out</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
47
core/shared/vendor/showdown/extensions/github.js
vendored
47
core/shared/vendor/showdown/extensions/github.js
vendored
@ -16,10 +16,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// GFM newline and underscore modifications
|
// GFM newline and underscore modifications, happen BEFORE showdown
|
||||||
type : 'lang',
|
type : 'lang',
|
||||||
filter : function (text) {
|
filter : function (text) {
|
||||||
var extractions = {},
|
var preExtractions = {},
|
||||||
imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim,
|
imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim,
|
||||||
hashID = 0;
|
hashID = 0;
|
||||||
|
|
||||||
@ -30,15 +30,10 @@
|
|||||||
// Extract pre blocks
|
// Extract pre blocks
|
||||||
text = text.replace(/<pre>[\s\S]*?<\/pre>/gim, function (x) {
|
text = text.replace(/<pre>[\s\S]*?<\/pre>/gim, function (x) {
|
||||||
var hash = hashId();
|
var hash = hashId();
|
||||||
extractions[hash] = x;
|
preExtractions[hash] = x;
|
||||||
return "{gfm-js-extract-pre-" + hash + "}";
|
return "{gfm-js-extract-pre-" + hash + "}";
|
||||||
}, 'm');
|
}, 'm');
|
||||||
|
|
||||||
// better URL support, but no title support
|
|
||||||
text = text.replace(imageMarkdownRegex, function (match, key, alt, src) {
|
|
||||||
return '<img src="' + src + '" alt="' + alt + '" />';
|
|
||||||
});
|
|
||||||
|
|
||||||
//prevent foo_bar and foo_bar_baz from ending up with an italic word in the middle
|
//prevent foo_bar and foo_bar_baz from ending up with an italic word in the middle
|
||||||
text = text.replace(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/gm, function (x) {
|
text = text.replace(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/gm, function (x) {
|
||||||
return x.replace(/_/gm, '\\_');
|
return x.replace(/_/gm, '\\_');
|
||||||
@ -49,8 +44,17 @@
|
|||||||
return x.match(/\n{2}/) ? x : x.trim() + " \n";
|
return x.match(/\n{2}/) ? x : x.trim() + " \n";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// better URL support, but no title support
|
||||||
|
text = text.replace(imageMarkdownRegex, function (match, key, alt, src) {
|
||||||
|
if (src) {
|
||||||
|
return '<img src="' + src + '" alt="' + alt + '" />';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
|
||||||
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
|
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
|
||||||
return "\n\n" + extractions[y];
|
return "\n\n" + preExtractions[y];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -58,22 +62,30 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Auto-link URLs and emails
|
// GFM autolinking & custom image handling, happens AFTER showdown
|
||||||
type : 'lang',
|
type : 'html',
|
||||||
filter : function (text) {
|
filter : function (text) {
|
||||||
var extractions = {},
|
var refExtractions = {},
|
||||||
|
preExtractions = {},
|
||||||
hashID = 0;
|
hashID = 0;
|
||||||
|
|
||||||
function hashId() {
|
function hashId() {
|
||||||
return hashID++;
|
return hashID++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Extract pre blocks
|
||||||
|
text = text.replace(/<(pre|code)>[\s\S]*?<\/(\1)>/gim, function (x) {
|
||||||
|
var hash = hashId();
|
||||||
|
preExtractions[hash] = x;
|
||||||
|
return "{gfm-js-extract-pre-" + hash + "}";
|
||||||
|
}, 'm');
|
||||||
|
|
||||||
// filter out def urls
|
// filter out def urls
|
||||||
// from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24
|
// from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24
|
||||||
text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi,
|
text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi,
|
||||||
function (x) {
|
function (x) {
|
||||||
var hash = hashId();
|
var hash = hashId();
|
||||||
extractions[hash] = x;
|
refExtractions[hash] = x;
|
||||||
return "{gfm-js-extract-ref-url-" + hash + "}";
|
return "{gfm-js-extract-ref-url-" + hash + "}";
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -91,13 +103,18 @@
|
|||||||
return lookBehind ? wholeMatch : "<a href='" + wholeMatch + "'>" + wholeMatch + "</a>";
|
return lookBehind ? wholeMatch : "<a href='" + wholeMatch + "'>" + wholeMatch + "</a>";
|
||||||
});
|
});
|
||||||
|
|
||||||
// match emil
|
// match email
|
||||||
text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) {
|
text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) {
|
||||||
return "<a href='mailto:" + wholeMatch + "'>" + wholeMatch + "</a>";
|
return "<a href='mailto:" + wholeMatch + "'>" + wholeMatch + "</a>";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// replace extractions
|
||||||
|
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
|
||||||
|
return preExtractions[y];
|
||||||
|
});
|
||||||
|
|
||||||
text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) {
|
text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) {
|
||||||
return "\n\n" + extractions[y];
|
return "\n\n" + refExtractions[y];
|
||||||
});
|
});
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
@ -146,6 +146,11 @@ describe('Admin Controller', function() {
|
|||||||
fs.exists.withArgs('content/images/2013/Sep/IMAGE.jpg').yields(true);
|
fs.exists.withArgs('content/images/2013/Sep/IMAGE.jpg').yields(true);
|
||||||
fs.exists.withArgs('content/images/2013/Sep/IMAGE-1.jpg').yields(false);
|
fs.exists.withArgs('content/images/2013/Sep/IMAGE-1.jpg').yields(false);
|
||||||
|
|
||||||
|
// if on windows need to setup with back slashes
|
||||||
|
// doesn't hurt for the test to cope with both
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE.jpg').yields(true);
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE-1.jpg').yields(false);
|
||||||
|
|
||||||
sinon.stub(res, 'send', function(data) {
|
sinon.stub(res, 'send', function(data) {
|
||||||
data.should.equal('/content/images/2013/Sep/IMAGE-1.jpg');
|
data.should.equal('/content/images/2013/Sep/IMAGE-1.jpg');
|
||||||
return done();
|
return done();
|
||||||
@ -163,6 +168,13 @@ describe('Admin Controller', function() {
|
|||||||
fs.exists.withArgs('content/images/2013/Sep/IMAGE-3.jpg').yields(true);
|
fs.exists.withArgs('content/images/2013/Sep/IMAGE-3.jpg').yields(true);
|
||||||
fs.exists.withArgs('content/images/2013/Sep/IMAGE-4.jpg').yields(false);
|
fs.exists.withArgs('content/images/2013/Sep/IMAGE-4.jpg').yields(false);
|
||||||
|
|
||||||
|
// windows setup
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE.jpg').yields(true);
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE-1.jpg').yields(true);
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE-2.jpg').yields(true);
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE-3.jpg').yields(true);
|
||||||
|
fs.exists.withArgs('content\\images\\2013\\Sep\\IMAGE-4.jpg').yields(false);
|
||||||
|
|
||||||
sinon.stub(res, 'send', function(data) {
|
sinon.stub(res, 'send', function(data) {
|
||||||
data.should.equal('/content/images/2013/Sep/IMAGE-4.jpg');
|
data.should.equal('/content/images/2013/Sep/IMAGE-4.jpg');
|
||||||
return done();
|
return done();
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*globals describe, before, beforeEach, afterEach, it */
|
/*globals describe, before, beforeEach, afterEach, it */
|
||||||
var testUtils = require('./testUtils'),
|
var testUtils = require('./testUtils'),
|
||||||
should = require('should'),
|
should = require('should'),
|
||||||
_ = require("underscore"),
|
_ = require('underscore'),
|
||||||
when = require('when'),
|
when = require('when'),
|
||||||
sequence = require('when/sequence'),
|
sequence = require('when/sequence'),
|
||||||
|
|
||||||
@ -14,8 +14,8 @@ describe('Post Model', function () {
|
|||||||
UserModel = Models.User,
|
UserModel = Models.User,
|
||||||
userData = {
|
userData = {
|
||||||
password: 'testpass1',
|
password: 'testpass1',
|
||||||
email: "test@test1.com",
|
email: 'test@test1.com',
|
||||||
name: "Mr Biscuits"
|
name: 'Mr Biscuits'
|
||||||
};
|
};
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
@ -79,10 +79,10 @@ describe('Post Model', function () {
|
|||||||
results.length.should.be.above(0);
|
results.length.should.be.above(0);
|
||||||
firstPost = results.models[0].toJSON();
|
firstPost = results.models[0].toJSON();
|
||||||
|
|
||||||
firstPost.author.should.be.a("object");
|
firstPost.author.should.be.a('object');
|
||||||
firstPost.user.should.be.a("object");
|
firstPost.user.should.be.a('object');
|
||||||
firstPost.author.name.should.equal("Mr Biscuits");
|
firstPost.author.name.should.equal('Mr Biscuits');
|
||||||
firstPost.user.name.should.equal("Mr Biscuits");
|
firstPost.user.name.should.equal('Mr Biscuits');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}, done);
|
}, done);
|
||||||
@ -95,10 +95,10 @@ describe('Post Model', function () {
|
|||||||
should.exist(result);
|
should.exist(result);
|
||||||
firstPost = result.toJSON();
|
firstPost = result.toJSON();
|
||||||
|
|
||||||
firstPost.author.should.be.a("object");
|
firstPost.author.should.be.a('object');
|
||||||
firstPost.user.should.be.a("object");
|
firstPost.user.should.be.a('object');
|
||||||
firstPost.author.name.should.equal("Mr Biscuits");
|
firstPost.author.name.should.equal('Mr Biscuits');
|
||||||
firstPost.user.name.should.equal("Mr Biscuits");
|
firstPost.user.name.should.equal('Mr Biscuits');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}, done);
|
}, done);
|
||||||
@ -112,7 +112,7 @@ describe('Post Model', function () {
|
|||||||
results.length.should.be.above(0);
|
results.length.should.be.above(0);
|
||||||
firstPost = results.models[0];
|
firstPost = results.models[0];
|
||||||
|
|
||||||
return PostModel.edit({id: firstPost.id, title: "new title"});
|
return PostModel.edit({id: firstPost.id, title: 'new title'});
|
||||||
}).then(function (edited) {
|
}).then(function (edited) {
|
||||||
should.exist(edited);
|
should.exist(edited);
|
||||||
edited.attributes.title.should.equal('new title');
|
edited.attributes.title.should.equal('new title');
|
||||||
@ -134,16 +134,16 @@ describe('Post Model', function () {
|
|||||||
should.exist(createdPost);
|
should.exist(createdPost);
|
||||||
createdPost.has('uuid').should.equal(true);
|
createdPost.has('uuid').should.equal(true);
|
||||||
createdPost.get('status').should.equal('draft');
|
createdPost.get('status').should.equal('draft');
|
||||||
createdPost.get('title').should.equal(newPost.title, "title is correct");
|
createdPost.get('title').should.equal(newPost.title, 'title is correct');
|
||||||
createdPost.get('markdown').should.equal(newPost.markdown, "markdown is correct");
|
createdPost.get('markdown').should.equal(newPost.markdown, 'markdown is correct');
|
||||||
createdPost.has('html').should.equal(true);
|
createdPost.has('html').should.equal(true);
|
||||||
createdPost.get('html').should.equal('<p>' + newPost.markdown + '</p>');
|
createdPost.get('html').should.equal('<p>' + newPost.markdown + '</p>');
|
||||||
createdPost.get('slug').should.equal('test-title-1');
|
createdPost.get('slug').should.equal('test-title-1');
|
||||||
createdPost.get('created_at').should.be.below(new Date().getTime()).and.be.above(new Date(0).getTime());
|
createdPost.get('created_at').should.be.above(new Date(0).getTime());
|
||||||
createdPost.get('created_by').should.equal(1);
|
createdPost.get('created_by').should.equal(1);
|
||||||
createdPost.get('author_id').should.equal(1);
|
createdPost.get('author_id').should.equal(1);
|
||||||
createdPost.get('created_by').should.equal(createdPost.get('author_id'));
|
createdPost.get('created_by').should.equal(createdPost.get('author_id'));
|
||||||
createdPost.get('updated_at').should.be.below(new Date().getTime()).and.be.above(new Date(0).getTime());
|
createdPost.get('updated_at').should.be.above(new Date(0).getTime());
|
||||||
createdPost.get('updated_by').should.equal(1);
|
createdPost.get('updated_by').should.equal(1);
|
||||||
should.equal(createdPost.get('published_at'), null);
|
should.equal(createdPost.get('published_at'), null);
|
||||||
should.equal(createdPost.get('published_by'), null);
|
should.equal(createdPost.get('published_by'), null);
|
||||||
@ -198,8 +198,8 @@ describe('Post Model', function () {
|
|||||||
sequence(_.times(12, function (i) {
|
sequence(_.times(12, function (i) {
|
||||||
return function () {
|
return function () {
|
||||||
return PostModel.add({
|
return PostModel.add({
|
||||||
title: "Test Title",
|
title: 'Test Title',
|
||||||
markdown: "Test Content " + (i+1)
|
markdown: 'Test Content ' + (i+1)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
})).then(function (createdPosts) {
|
})).then(function (createdPosts) {
|
||||||
@ -224,7 +224,6 @@ describe('Post Model', function () {
|
|||||||
}).otherwise(done);
|
}).otherwise(done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('can generate slugs without duplicate hyphens', function (done) {
|
it('can generate slugs without duplicate hyphens', function (done) {
|
||||||
var newPost = {
|
var newPost = {
|
||||||
title: 'apprehensive titles have too many spaces ',
|
title: 'apprehensive titles have too many spaces ',
|
||||||
@ -239,6 +238,53 @@ describe('Post Model', function () {
|
|||||||
}).then(null, done);
|
}).then(null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('detects duplicate slugs before saving', function (done) {
|
||||||
|
var firstPost = {
|
||||||
|
title: 'First post',
|
||||||
|
markdown: 'First content 1'
|
||||||
|
},
|
||||||
|
secondPost = {
|
||||||
|
title: 'Second post',
|
||||||
|
markdown: 'Second content 1'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create the first post
|
||||||
|
PostModel.add(firstPost)
|
||||||
|
.then(function (createdFirstPost) {
|
||||||
|
// Store the slug for later
|
||||||
|
firstPost.slug = createdFirstPost.get('slug');
|
||||||
|
|
||||||
|
// Create the second post
|
||||||
|
return PostModel.add(secondPost);
|
||||||
|
}).then(function (createdSecondPost) {
|
||||||
|
// Store the slug for comparison later
|
||||||
|
secondPost.slug = createdSecondPost.get('slug');
|
||||||
|
|
||||||
|
// Update with a conflicting slug from the first post
|
||||||
|
return createdSecondPost.save({
|
||||||
|
slug: firstPost.slug
|
||||||
|
});
|
||||||
|
}).then(function (updatedSecondPost) {
|
||||||
|
|
||||||
|
// Should have updated from original
|
||||||
|
updatedSecondPost.get('slug').should.not.equal(secondPost.slug);
|
||||||
|
// Should not have a conflicted slug from the first
|
||||||
|
updatedSecondPost.get('slug').should.not.equal(firstPost.slug);
|
||||||
|
|
||||||
|
return PostModel.read({
|
||||||
|
id: updatedSecondPost.id
|
||||||
|
});
|
||||||
|
}).then(function (foundPost) {
|
||||||
|
|
||||||
|
// Should have updated from original
|
||||||
|
foundPost.get('slug').should.not.equal(secondPost.slug);
|
||||||
|
// Should not have a conflicted slug from the first
|
||||||
|
foundPost.get('slug').should.not.equal(firstPost.slug);
|
||||||
|
|
||||||
|
done();
|
||||||
|
}).otherwise(done);
|
||||||
|
});
|
||||||
|
|
||||||
it('can delete', function (done) {
|
it('can delete', function (done) {
|
||||||
var firstPostId;
|
var firstPostId;
|
||||||
PostModel.browse().then(function (results) {
|
PostModel.browse().then(function (results) {
|
||||||
@ -252,7 +298,7 @@ describe('Post Model', function () {
|
|||||||
}).then(function (newResults) {
|
}).then(function (newResults) {
|
||||||
var ids, hasDeletedId;
|
var ids, hasDeletedId;
|
||||||
|
|
||||||
ids = _.pluck(newResults.models, "id");
|
ids = _.pluck(newResults.models, 'id');
|
||||||
hasDeletedId = _.any(ids, function (id) {
|
hasDeletedId = _.any(ids, function (id) {
|
||||||
return id === firstPostId;
|
return id === firstPostId;
|
||||||
});
|
});
|
||||||
@ -262,6 +308,25 @@ describe('Post Model', function () {
|
|||||||
}).then(null, done);
|
}).then(null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('can create a new Post with a previous published_at date', function (done) {
|
||||||
|
var previousPublishedAtDate = new Date(2013, 8, 21, 12);
|
||||||
|
|
||||||
|
PostModel.add({
|
||||||
|
status: 'published',
|
||||||
|
published_at: previousPublishedAtDate,
|
||||||
|
title: 'published_at test',
|
||||||
|
markdown: 'This is some content'
|
||||||
|
}).then(function (newPost) {
|
||||||
|
|
||||||
|
should.exist(newPost);
|
||||||
|
|
||||||
|
newPost.get('published_at').should.equal(previousPublishedAtDate);
|
||||||
|
|
||||||
|
done();
|
||||||
|
|
||||||
|
}).otherwise(done);
|
||||||
|
});
|
||||||
|
|
||||||
it('can fetch a paginated set, with various options', function (done) {
|
it('can fetch a paginated set, with various options', function (done) {
|
||||||
this.timeout(10000); // this is a patch to ensure it doesn't timeout.
|
this.timeout(10000); // this is a patch to ensure it doesn't timeout.
|
||||||
|
|
||||||
|
@ -76,13 +76,7 @@ describe('Settings Model', function () {
|
|||||||
|
|
||||||
results.length.should.be.above(0);
|
results.length.should.be.above(0);
|
||||||
|
|
||||||
firstSetting = results.models[1];
|
return SettingsModel.edit({key: "description", value: "new value"});
|
||||||
|
|
||||||
// The edit method has been modified to take an object of
|
|
||||||
// key/value pairs
|
|
||||||
firstSetting.set('value', 'new value');
|
|
||||||
|
|
||||||
return SettingsModel.edit(firstSetting);
|
|
||||||
|
|
||||||
}).then(function (edited) {
|
}).then(function (edited) {
|
||||||
|
|
||||||
@ -92,7 +86,7 @@ describe('Settings Model', function () {
|
|||||||
|
|
||||||
edited = edited[0];
|
edited = edited[0];
|
||||||
|
|
||||||
edited.attributes.key.should.equal(firstSetting.attributes.key);
|
edited.attributes.key.should.equal('description');
|
||||||
edited.attributes.value.should.equal('new value');
|
edited.attributes.value.should.equal('new value');
|
||||||
|
|
||||||
done();
|
done();
|
||||||
@ -111,13 +105,8 @@ describe('Settings Model', function () {
|
|||||||
|
|
||||||
results.length.should.be.above(0);
|
results.length.should.be.above(0);
|
||||||
|
|
||||||
model1 = results.models[1];
|
model1 = {key: "description", value: "another new value"};
|
||||||
model2 = results.models[2];
|
model2 = {key: "title", value: "new title"};
|
||||||
|
|
||||||
// The edit method has been modified to take an object of
|
|
||||||
// key/value pairs
|
|
||||||
model1.set('value', 'new value1');
|
|
||||||
model2.set('value', 'new value2');
|
|
||||||
|
|
||||||
return SettingsModel.edit([model1, model2]);
|
return SettingsModel.edit([model1, model2]);
|
||||||
|
|
||||||
@ -129,13 +118,13 @@ describe('Settings Model', function () {
|
|||||||
|
|
||||||
editedModel = edited[0];
|
editedModel = edited[0];
|
||||||
|
|
||||||
editedModel.attributes.key.should.equal(model1.attributes.key);
|
editedModel.attributes.key.should.equal(model1.key);
|
||||||
editedModel.attributes.value.should.equal('new value1');
|
editedModel.attributes.value.should.equal(model1.value);
|
||||||
|
|
||||||
editedModel = edited[1];
|
editedModel = edited[1];
|
||||||
|
|
||||||
editedModel.attributes.key.should.equal(model2.attributes.key);
|
editedModel.attributes.key.should.equal(model2.key);
|
||||||
editedModel.attributes.value.should.equal('new value2');
|
editedModel.attributes.value.should.equal(model2.value);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
|
|
||||||
@ -205,7 +194,6 @@ describe('Settings Model', function () {
|
|||||||
|
|
||||||
it('populates any unset settings from the JSON defaults', function (done) {
|
it('populates any unset settings from the JSON defaults', function (done) {
|
||||||
SettingsModel.findAll().then(function (allSettings) {
|
SettingsModel.findAll().then(function (allSettings) {
|
||||||
console.log(allSettings.models)
|
|
||||||
allSettings.length.should.equal(0);
|
allSettings.length.should.equal(0);
|
||||||
return SettingsModel.populateDefaults();
|
return SettingsModel.populateDefaults();
|
||||||
}).then(function () {
|
}).then(function () {
|
||||||
|
@ -130,7 +130,7 @@ describe('Tag Model', function () {
|
|||||||
return postModel.save();
|
return postModel.save();
|
||||||
}).then(function (postModel) {
|
}).then(function (postModel) {
|
||||||
var tagNames = postModel.related('tags').models.map(function (t) { return t.attributes.name; });
|
var tagNames = postModel.related('tags').models.map(function (t) { return t.attributes.name; });
|
||||||
tagNames.should.eql(seededTagNames);
|
tagNames.sort().should.eql(seededTagNames);
|
||||||
|
|
||||||
return TagModel.findAll();
|
return TagModel.findAll();
|
||||||
}).then(function (tagsFromDB) {
|
}).then(function (tagsFromDB) {
|
||||||
@ -155,7 +155,7 @@ describe('Tag Model', function () {
|
|||||||
return PostModel.read({id: postModel.id}, { withRelated: ['tags']});
|
return PostModel.read({id: postModel.id}, { withRelated: ['tags']});
|
||||||
}).then(function (reloadedPost) {
|
}).then(function (reloadedPost) {
|
||||||
var tagNames = reloadedPost.related('tags').models.map(function (t) { return t.attributes.name; });
|
var tagNames = reloadedPost.related('tags').models.map(function (t) { return t.attributes.name; });
|
||||||
tagNames.should.eql(['tag1', 'tag3']);
|
tagNames.sort().should.eql(['tag1', 'tag3']);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).then(null, done);
|
}).then(null, done);
|
||||||
@ -180,7 +180,7 @@ describe('Tag Model', function () {
|
|||||||
}).then(function (reloadedPost) {
|
}).then(function (reloadedPost) {
|
||||||
var tagModels = reloadedPost.related('tags').models,
|
var tagModels = reloadedPost.related('tags').models,
|
||||||
tagNames = tagModels.map(function (t) { return t.attributes.name; });
|
tagNames = tagModels.map(function (t) { return t.attributes.name; });
|
||||||
tagNames.should.eql(['tag1', 'tag2', 'tag3']);
|
tagNames.sort().should.eql(['tag1', 'tag2', 'tag3']);
|
||||||
tagModels[2].id.should.eql(4); // make sure it hasn't just added a new tag with the same name
|
tagModels[2].id.should.eql(4); // make sure it hasn't just added a new tag with the same name
|
||||||
|
|
||||||
done();
|
done();
|
||||||
@ -201,7 +201,7 @@ describe('Tag Model', function () {
|
|||||||
return PostModel.read({id: postModel.id}, { withRelated: ['tags']});
|
return PostModel.read({id: postModel.id}, { withRelated: ['tags']});
|
||||||
}).then(function (reloadedPost) {
|
}).then(function (reloadedPost) {
|
||||||
var tagNames = reloadedPost.related('tags').models.map(function (t) { return t.attributes.name; });
|
var tagNames = reloadedPost.related('tags').models.map(function (t) { return t.attributes.name; });
|
||||||
tagNames.should.eql(['tag1', 'tag2', 'tag3']);
|
tagNames.sort().should.eql(['tag1', 'tag2', 'tag3']);
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).then(null, done);
|
}).then(null, done);
|
||||||
|
@ -178,7 +178,7 @@ describe("Showdown client side converter", function () {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "# http://google.co.uk",
|
input: "# http://google.co.uk",
|
||||||
output: /^<h1 id="ahrefhttpgooglecoukhttpgooglecouka"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/
|
output: /^<h1 id="httpgooglecouk"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "* http://google.co.uk",
|
input: "* http://google.co.uk",
|
||||||
@ -279,6 +279,30 @@ describe("Showdown client side converter", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should NOT auto-link URLS inside of code/pre blocks", function () {
|
||||||
|
var testPhrases = [
|
||||||
|
{
|
||||||
|
input: "```\nurl: http://google.co.uk\n```",
|
||||||
|
output: /^<pre><code>url: http:\/\/google.co.uk \n<\/code><\/pre>$/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "`url: http://google.co.uk`",
|
||||||
|
output: /^<p><code>url: http:\/\/google.co.uk<\/code><\/p>$/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
input: "Hello type some `url: http://google.co.uk` stuff",
|
||||||
|
output: /^<p>Hello type some <code>url: http:\/\/google.co.uk<\/code> stuff<\/p>$/
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
processedMarkup;
|
||||||
|
|
||||||
|
testPhrases.forEach(function (testPhrase) {
|
||||||
|
processedMarkup = converter.makeHtml(testPhrase.input);
|
||||||
|
processedMarkup.should.match(testPhrase.output);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should not display anything for reference URL", function () {
|
it("should not display anything for reference URL", function () {
|
||||||
var testPhrases = [
|
var testPhrases = [
|
||||||
{
|
{
|
||||||
|
@ -12,6 +12,7 @@ var testUtils = require('./testUtils'),
|
|||||||
describe("Ghost API", function () {
|
describe("Ghost API", function () {
|
||||||
var testTemplatePath = 'core/test/unit/fixtures/',
|
var testTemplatePath = 'core/test/unit/fixtures/',
|
||||||
themeTemplatePath = 'core/test/unit/fixtures/theme',
|
themeTemplatePath = 'core/test/unit/fixtures/theme',
|
||||||
|
sandbox,
|
||||||
ghost;
|
ghost;
|
||||||
|
|
||||||
before(function (done) {
|
before(function (done) {
|
||||||
@ -21,23 +22,26 @@ describe("Ghost API", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
|
||||||
testUtils.initData().then(function () {
|
testUtils.initData().then(function () {
|
||||||
ghost = new Ghost();
|
ghost = new Ghost();
|
||||||
done();
|
done();
|
||||||
}, done);
|
}, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("is a singleton", function () {
|
afterEach(function () {
|
||||||
var logStub = sinon.stub(console, "log"),
|
sandbox.restore();
|
||||||
ghost1 = new Ghost(),
|
});
|
||||||
ghost2 = new Ghost();
|
|
||||||
|
|
||||||
should.strictEqual(ghost1, ghost2);
|
it("is a singleton", function () {
|
||||||
logStub.restore();
|
var ghost2 = new Ghost();
|
||||||
|
|
||||||
|
should.strictEqual(ghost, ghost2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses init() to initialize", function (done) {
|
it("uses init() to initialize", function (done) {
|
||||||
var dataProviderInitMock = sinon.stub(ghost.dataProvider, "init", function () {
|
var dataProviderInitMock = sandbox.stub(ghost.dataProvider, "init", function () {
|
||||||
return when.resolve();
|
return when.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -49,8 +53,6 @@ describe("Ghost API", function () {
|
|||||||
|
|
||||||
dataProviderInitMock.called.should.equal(true);
|
dataProviderInitMock.called.should.equal(true);
|
||||||
|
|
||||||
dataProviderInitMock.restore();
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}, done);
|
}, done);
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ describe("Ghost API", function () {
|
|||||||
it("can register filters with specific priority", function () {
|
it("can register filters with specific priority", function () {
|
||||||
var filterName = 'test',
|
var filterName = 'test',
|
||||||
filterPriority = 9,
|
filterPriority = 9,
|
||||||
testFilterHandler = sinon.spy();
|
testFilterHandler = sandbox.spy();
|
||||||
|
|
||||||
ghost.registerFilter(filterName, filterPriority, testFilterHandler);
|
ghost.registerFilter(filterName, filterPriority, testFilterHandler);
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ describe("Ghost API", function () {
|
|||||||
it("can register filters with default priority", function () {
|
it("can register filters with default priority", function () {
|
||||||
var filterName = 'test',
|
var filterName = 'test',
|
||||||
defaultPriority = 5,
|
defaultPriority = 5,
|
||||||
testFilterHandler = sinon.spy();
|
testFilterHandler = sandbox.spy();
|
||||||
|
|
||||||
ghost.registerFilter(filterName, testFilterHandler);
|
ghost.registerFilter(filterName, testFilterHandler);
|
||||||
|
|
||||||
@ -84,9 +86,9 @@ describe("Ghost API", function () {
|
|||||||
|
|
||||||
it("executes filters in priority order", function (done) {
|
it("executes filters in priority order", function (done) {
|
||||||
var filterName = 'testpriority',
|
var filterName = 'testpriority',
|
||||||
testFilterHandler1 = sinon.spy(),
|
testFilterHandler1 = sandbox.spy(),
|
||||||
testFilterHandler2 = sinon.spy(),
|
testFilterHandler2 = sandbox.spy(),
|
||||||
testFilterHandler3 = sinon.spy();
|
testFilterHandler3 = sandbox.spy();
|
||||||
|
|
||||||
ghost.registerFilter(filterName, 0, testFilterHandler1);
|
ghost.registerFilter(filterName, 0, testFilterHandler1);
|
||||||
ghost.registerFilter(filterName, 2, testFilterHandler2);
|
ghost.registerFilter(filterName, 2, testFilterHandler2);
|
||||||
@ -118,13 +120,13 @@ describe("Ghost API", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("loads templates for helpers", function (done) {
|
it("loads templates for helpers", function (done) {
|
||||||
var compileSpy = sinon.spy(ghost, 'compileTemplate'),
|
var compileSpy = sandbox.spy(ghost, 'compileTemplate'),
|
||||||
pathsStub;
|
pathsStub;
|
||||||
|
|
||||||
should.exist(ghost.loadTemplate, 'load template function exists');
|
should.exist(ghost.loadTemplate, 'load template function exists');
|
||||||
|
|
||||||
// In order for the test to work, need to replace the path to the template
|
// In order for the test to work, need to replace the path to the template
|
||||||
pathsStub = sinon.stub(ghost, "paths", function () {
|
pathsStub = sandbox.stub(ghost, "paths", function () {
|
||||||
return {
|
return {
|
||||||
// Forcing the theme path to be the same
|
// Forcing the theme path to be the same
|
||||||
activeTheme: path.join(process.cwd(), testTemplatePath),
|
activeTheme: path.join(process.cwd(), testTemplatePath),
|
||||||
@ -145,20 +147,18 @@ describe("Ghost API", function () {
|
|||||||
|
|
||||||
templateFn().should.equal('<h1>HelloWorld</h1>');
|
templateFn().should.equal('<h1>HelloWorld</h1>');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
done();
|
done();
|
||||||
}).then(null, done);
|
}).then(null, done);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("loads templates from themes first", function (done) {
|
it("loads templates from themes first", function (done) {
|
||||||
var compileSpy = sinon.spy(ghost, 'compileTemplate'),
|
var compileSpy = sandbox.spy(ghost, 'compileTemplate'),
|
||||||
pathsStub;
|
pathsStub;
|
||||||
|
|
||||||
should.exist(ghost.loadTemplate, 'load template function exists');
|
should.exist(ghost.loadTemplate, 'load template function exists');
|
||||||
|
|
||||||
// In order for the test to work, need to replace the path to the template
|
// In order for the test to work, need to replace the path to the template
|
||||||
pathsStub = sinon.stub(ghost, "paths", function () {
|
pathsStub = sandbox.stub(ghost, "paths", function () {
|
||||||
return {
|
return {
|
||||||
activeTheme: path.join(process.cwd(), themeTemplatePath),
|
activeTheme: path.join(process.cwd(), themeTemplatePath),
|
||||||
helperTemplates: path.join(process.cwd(), testTemplatePath)
|
helperTemplates: path.join(process.cwd(), testTemplatePath)
|
||||||
|
@ -1,202 +1,98 @@
|
|||||||
///*globals describe, beforeEach, it*/
|
/*globals describe, beforeEach, it*/
|
||||||
//var testUtils = require('./testUtils'),
|
var testUtils = require('./testUtils'),
|
||||||
// should = require('should'),
|
should = require('should'),
|
||||||
// sinon = require('sinon'),
|
sinon = require('sinon'),
|
||||||
// when = require('when'),
|
when = require('when'),
|
||||||
// _ = require("underscore"),
|
_ = require("underscore"),
|
||||||
// errors = require('../../server/errorHandling'),
|
errors = require('../../server/errorHandling'),
|
||||||
//
|
|
||||||
// // Stuff we are testing
|
// Stuff we are testing
|
||||||
// knex = require("../../server/models/base").Knex,
|
knex = require("../../server/models/base").Knex,
|
||||||
// migration = require('../../server/data/migration'),
|
migration = require('../../server/data/migration'),
|
||||||
// exporter = require('../../server/data/export'),
|
exporter = require('../../server/data/export'),
|
||||||
// importer = require('../../server/data/import'),
|
importer = require('../../server/data/import'),
|
||||||
// Importer001 = require('../../server/data/import/001'),
|
Importer000 = require('../../server/data/import/000'),
|
||||||
// Importer002 = require('../../server/data/import/002'),
|
fixtures = require('../../server/data/fixtures'),
|
||||||
// Settings = require('../../server/models/settings').Settings;
|
Settings = require('../../server/models/settings').Settings;
|
||||||
//
|
|
||||||
//describe("Import", function () {
|
describe("Import", function () {
|
||||||
//
|
|
||||||
// should.exist(exporter);
|
should.exist(exporter);
|
||||||
// should.exist(importer);
|
should.exist(importer);
|
||||||
//
|
|
||||||
// beforeEach(function (done) {
|
beforeEach(function (done) {
|
||||||
// // clear database... we need to initialise it manually for each test
|
// clear database... we need to initialise it manually for each test
|
||||||
// testUtils.clearData().then(function () {
|
testUtils.clearData().then(function () {
|
||||||
// done();
|
done();
|
||||||
// }, done);
|
}, done);
|
||||||
// });
|
});
|
||||||
//
|
|
||||||
// it("resolves 001", function (done) {
|
it("resolves 000", function (done) {
|
||||||
// var importStub = sinon.stub(Importer001, "importData", function () {
|
var importStub = sinon.stub(Importer000, "importData", function () {
|
||||||
// return when.resolve();
|
return when.resolve();
|
||||||
// }),
|
}),
|
||||||
// fakeData = { test: true };
|
fakeData = { test: true };
|
||||||
//
|
|
||||||
// importer("001", fakeData).then(function () {
|
importer("000", fakeData).then(function () {
|
||||||
// importStub.calledWith(fakeData).should.equal(true);
|
importStub.calledWith(fakeData).should.equal(true);
|
||||||
//
|
|
||||||
// importStub.restore();
|
importStub.restore();
|
||||||
//
|
|
||||||
// done();
|
done();
|
||||||
// }).then(null, done);
|
}).then(null, done);
|
||||||
// });
|
});
|
||||||
//
|
|
||||||
// describe("001", function () {
|
describe("000", function () {
|
||||||
// this.timeout(4000);
|
this.timeout(4000);
|
||||||
//
|
|
||||||
// should.exist(Importer001);
|
should.exist(Importer000);
|
||||||
//
|
|
||||||
// it("imports data from 001", function (done) {
|
it("imports data from 000", function (done) {
|
||||||
// var exportData;
|
var exportData;
|
||||||
//
|
|
||||||
// // initialise database to version 001 - confusingly we have to set the max version to be one higher
|
// initialise database to version 000 - confusingly we have to set the max version to be one higher
|
||||||
// // than the migration version we want
|
// than the migration version we want. Could just use migrate from fresh here... but this is more explicit
|
||||||
// migration.migrateUpFromVersion('001', '002').then(function () {
|
migration.migrateUpFromVersion('000', '001').then(function () {
|
||||||
// return Settings.populateDefaults();
|
// Load the fixtures
|
||||||
// }).then(function () {
|
return fixtures.populateFixtures();
|
||||||
// // export the version 001 data ready to import
|
}).then(function () {
|
||||||
// // TODO: Should have static test data here?
|
// Initialise the default settings
|
||||||
// return exporter("001");
|
return Settings.populateDefaults();
|
||||||
// }).then(function (exported) {
|
}).then(function () {
|
||||||
// exportData = exported;
|
// export the version 000 data ready to import
|
||||||
//
|
// TODO: Should have static test data here?
|
||||||
// // Version 001 exporter required the database be empty...
|
return exporter();
|
||||||
// var tables = [
|
}).then(function (exported) {
|
||||||
// 'posts', 'users', 'roles', 'roles_users', 'permissions', 'permissions_roles',
|
exportData = exported;
|
||||||
// 'settings'
|
|
||||||
// ],
|
return importer("000", exportData);
|
||||||
// truncateOps = _.map(tables, function (name) {
|
}).then(function () {
|
||||||
// return knex(name).truncate();
|
// Grab the data from tables
|
||||||
// });
|
return when.all([
|
||||||
//
|
knex("users").select(),
|
||||||
// return when.all(truncateOps);
|
knex("posts").select(),
|
||||||
// }).then(function () {
|
knex("settings").select(),
|
||||||
// return importer("001", exportData);
|
knex("tags").select()
|
||||||
// }).then(function () {
|
]);
|
||||||
// // Grab the data from tables
|
}).then(function (importedData) {
|
||||||
// return when.all([
|
|
||||||
// knex("users").select(),
|
should.exist(importedData);
|
||||||
// knex("posts").select(),
|
importedData.length.should.equal(4, 'Did not get data successfully');
|
||||||
// knex("settings").select()
|
|
||||||
// ]);
|
// we always have 0 users as there isn't one in fixtures
|
||||||
// }).then(function (importedData) {
|
importedData[0].length.should.equal(0, 'There should not be a user');
|
||||||
//
|
// import no longer requires all data to be dropped, and adds posts
|
||||||
// should.exist(importedData);
|
importedData[1].length.should.equal(exportData.data.posts.length + 1, 'Wrong number of posts');
|
||||||
// importedData.length.should.equal(3);
|
|
||||||
//
|
// test settings
|
||||||
// // we always have 0 users as there isn't one in fixtures
|
importedData[2].length.should.be.above(0, 'Wrong number of settings');
|
||||||
// importedData[0].length.should.equal(0);
|
_.findWhere(importedData[2], {key: "databaseVersion"}).value.should.equal("000", 'Wrong database version');
|
||||||
// importedData[1].length.should.equal(exportData.data.posts.length);
|
|
||||||
// importedData[2].length.should.be.above(0);
|
// test tags
|
||||||
//
|
importedData[3].length.should.equal(exportData.data.tags.length, 'no new tags');
|
||||||
// _.findWhere(exportData.data.settings, {key: "databaseVersion"}).value.should.equal("001");
|
|
||||||
//
|
done();
|
||||||
// done();
|
}).then(null, done);
|
||||||
// }).then(null, done);
|
});
|
||||||
// });
|
});
|
||||||
// });
|
});
|
||||||
//
|
|
||||||
// it("resolves 002", function (done) {
|
|
||||||
// var importStub = sinon.stub(Importer002, "importData", function () {
|
|
||||||
// return when.resolve();
|
|
||||||
// }),
|
|
||||||
// fakeData = { test: true };
|
|
||||||
//
|
|
||||||
// importer("002", fakeData).then(function () {
|
|
||||||
// importStub.calledWith(fakeData).should.equal(true);
|
|
||||||
//
|
|
||||||
// importStub.restore();
|
|
||||||
//
|
|
||||||
// done();
|
|
||||||
// }).then(null, done);
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// describe("002", function () {
|
|
||||||
// this.timeout(4000);
|
|
||||||
//
|
|
||||||
// should.exist(Importer002);
|
|
||||||
//
|
|
||||||
// it("imports data from 001", function (done) {
|
|
||||||
// var exportData;
|
|
||||||
//
|
|
||||||
// // initialise database to version 001 - confusingly we have to set the max version to be one higher
|
|
||||||
// // than the migration version we want
|
|
||||||
// migration.migrateUpFromVersion('001', '002').then(function () {
|
|
||||||
// return Settings.populateDefaults();
|
|
||||||
// }).then(function () {
|
|
||||||
// // export the version 001 data ready to import
|
|
||||||
// // TODO: Should have static test data here?
|
|
||||||
// return exporter("001");
|
|
||||||
// }).then(function (exported) {
|
|
||||||
// exportData = exported;
|
|
||||||
//
|
|
||||||
// // now migrate up to the proper version ready for importing - confusingly we have to set the max version
|
|
||||||
// // to be one higher than the migration version we want
|
|
||||||
// return migration.migrateUpFromVersion('002', '003');
|
|
||||||
// }).then(function () {
|
|
||||||
// return importer("002", exportData);
|
|
||||||
// }).then(function () {
|
|
||||||
// // Grab the data from tables
|
|
||||||
// return when.all([
|
|
||||||
// knex("users").select(),
|
|
||||||
// knex("posts").select(),
|
|
||||||
// knex("settings").select()
|
|
||||||
// ]);
|
|
||||||
// }).then(function (importedData) {
|
|
||||||
//
|
|
||||||
// should.exist(importedData);
|
|
||||||
// importedData.length.should.equal(3);
|
|
||||||
//
|
|
||||||
// // we always have 0 users as there isn't one in fixtures
|
|
||||||
// importedData[0].length.should.equal(0);
|
|
||||||
// // import no longer requires all data to be dropped, and adds posts
|
|
||||||
// importedData[1].length.should.equal(exportData.data.posts.length + 1);
|
|
||||||
// importedData[2].length.should.be.above(0);
|
|
||||||
//
|
|
||||||
// _.findWhere(importedData[2], {key: "databaseVersion"}).value.should.equal("002");
|
|
||||||
//
|
|
||||||
// done();
|
|
||||||
// }).then(null, done);
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// it("imports data from 002", function (done) {
|
|
||||||
// var exportData;
|
|
||||||
//
|
|
||||||
// // initialise database to version 001 - confusingly we have to set the max version to be one higher
|
|
||||||
// // than the migration version we want
|
|
||||||
// migration.migrateUpFromVersion('001', '003').then(function () {
|
|
||||||
// return Settings.populateDefaults();
|
|
||||||
// }).then(function () {
|
|
||||||
// // export the version 002 data ready to import
|
|
||||||
// // TODO: Should have static test data here?
|
|
||||||
// return exporter("002");
|
|
||||||
// }).then(function (exported) {
|
|
||||||
// exportData = exported;
|
|
||||||
//
|
|
||||||
// return importer("002", exportData);
|
|
||||||
// }).then(function () {
|
|
||||||
// // Grab the data from tables
|
|
||||||
// return when.all([
|
|
||||||
// knex("users").select(),
|
|
||||||
// knex("posts").select(),
|
|
||||||
// knex("settings").select()
|
|
||||||
// ]);
|
|
||||||
// }).then(function (importedData) {
|
|
||||||
//
|
|
||||||
// should.exist(importedData);
|
|
||||||
// importedData.length.should.equal(3);
|
|
||||||
//
|
|
||||||
// // we always have 0 users as there isn't one in fixtures
|
|
||||||
// importedData[0].length.should.equal(0);
|
|
||||||
// // import no longer requires all data to be dropped, and adds posts
|
|
||||||
// importedData[1].length.should.equal(exportData.data.posts.length + 1);
|
|
||||||
// importedData[2].length.should.be.above(0);
|
|
||||||
//
|
|
||||||
// _.findWhere(importedData[2], {key: "databaseVersion"}).value.should.equal("002");
|
|
||||||
//
|
|
||||||
// done();
|
|
||||||
// }).then(null, done);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
//});
|
|
||||||
|
@ -94,7 +94,7 @@ describe('permissions', function () {
|
|||||||
.then(function (actionsMap) {
|
.then(function (actionsMap) {
|
||||||
should.exist(actionsMap);
|
should.exist(actionsMap);
|
||||||
|
|
||||||
actionsMap.edit.should.eql(['post', 'tag', 'user', 'page']);
|
actionsMap.edit.sort().should.eql(['post', 'tag', 'user', 'page'].sort());
|
||||||
|
|
||||||
actionsMap.should.equal(permissions.actionsMap);
|
actionsMap.should.equal(permissions.actionsMap);
|
||||||
|
|
||||||
|
@ -189,10 +189,16 @@ describe('Core Helpers', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns meta tag string', function () {
|
it('returns meta tag string', function () {
|
||||||
var rendered = handlebars.helpers.ghost_head.call({version: "0.3"});
|
var rendered = handlebars.helpers.ghost_head.call({version: "0.3.0"});
|
||||||
should.exist(rendered);
|
should.exist(rendered);
|
||||||
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
rendered.string.should.equal('<meta name="generator" content="Ghost 0.3" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('returns meta tag string even if version is invalid', function () {
|
||||||
|
var rendered = handlebars.helpers.ghost_head.call({version: "0.9"});
|
||||||
|
should.exist(rendered);
|
||||||
|
rendered.string.should.equal('<meta name="generator" content="Ghost 0.9" />\n<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss/">');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('ghost_foot Helper', function () {
|
describe('ghost_foot Helper', function () {
|
||||||
|
@ -252,4 +252,19 @@ describe("Github showdown extensions", function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not output image if there is no src", function () {
|
||||||
|
var testPhrases = [
|
||||||
|
{
|
||||||
|
input: "![anything here]()",
|
||||||
|
output: /^$/
|
||||||
|
}
|
||||||
|
],
|
||||||
|
processedMarkup;
|
||||||
|
|
||||||
|
testPhrases.forEach(function (testPhrase) {
|
||||||
|
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||||
|
processedMarkup.should.match(testPhrase.output);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
@ -37,7 +37,7 @@ sampleUser = function (i) {
|
|||||||
email: "joe_" + i + "@bloggs.com",
|
email: "joe_" + i + "@bloggs.com",
|
||||||
password: "$2a$10$c5G9RS5.dXRt3UqvZ5wNgOLQLc7ZFc2DJo01du0oLT1YYOM67KJMe",
|
password: "$2a$10$c5G9RS5.dXRt3UqvZ5wNgOLQLc7ZFc2DJo01du0oLT1YYOM67KJMe",
|
||||||
created_by: 1,
|
created_by: 1,
|
||||||
created_at: 1234567890
|
created_at: new Date()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
2
index.js
2
index.js
@ -2,7 +2,7 @@
|
|||||||
// Orchestrates the loading of Ghost
|
// Orchestrates the loading of Ghost
|
||||||
|
|
||||||
var configLoader = require('./core/config-loader.js'),
|
var configLoader = require('./core/config-loader.js'),
|
||||||
error = require('./core/server/errorHandling');
|
error = require('./core/server/errorHandling');
|
||||||
|
|
||||||
// If no env is set, default to development
|
// If no env is set, default to development
|
||||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "ghost",
|
"name": "ghost",
|
||||||
"version": "0.3.0",
|
"version": "0.3.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node index",
|
"start": "node index",
|
||||||
|
Loading…
Reference in New Issue
Block a user