mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 10:53:34 +03:00
Switch to bower for client assets.
fixes #2272 - Remove libraries from shared/vendor - Remove libraries from client/assets/vendor - Add bower to package.json and postinstall - Add bower.json with dependencies - Add scripts from bower_components to concat/uglify - Fix tests - Serve jquery from /ghost/built/theme/
This commit is contained in:
parent
c3865dbb9c
commit
cd74b0e232
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@ results
|
||||
|
||||
npm-debug.log
|
||||
node_modules
|
||||
bower_components
|
||||
|
||||
.idea/*
|
||||
*.iml
|
||||
|
119
Gruntfile.js
119
Gruntfile.js
@ -235,7 +235,8 @@ var path = require('path'),
|
||||
src: [
|
||||
'core/shared/**/*.js',
|
||||
// Ignore files
|
||||
'!core/shared/vendor/**/*.js'
|
||||
'!core/shared/vendor/**/*.js',
|
||||
'!core/shared/lib/**/*.js'
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -397,11 +398,32 @@ var path = require('path'),
|
||||
// ### Config for grunt-contrib-copy
|
||||
// Prepare files for builds / releases
|
||||
copy: {
|
||||
dev: {
|
||||
files: [{
|
||||
cwd: 'bower_components/jquery/dist/',
|
||||
src: 'jquery.js',
|
||||
dest: 'core/built/public/',
|
||||
expand: true
|
||||
}]
|
||||
},
|
||||
prod: {
|
||||
files: [{
|
||||
cwd: 'bower_components/jquery/dist/',
|
||||
src: 'jquery.js',
|
||||
dest: 'core/built/public/',
|
||||
expand: true
|
||||
}]
|
||||
},
|
||||
release: {
|
||||
files: [{
|
||||
expand: true,
|
||||
src: buildGlob,
|
||||
dest: '<%= paths.releaseBuild %>/'
|
||||
}, {
|
||||
cwd: 'bower_components/jquery/dist/',
|
||||
src: 'jquery.js',
|
||||
dest: 'core/built/public/',
|
||||
expand: true
|
||||
}]
|
||||
}
|
||||
},
|
||||
@ -425,34 +447,34 @@ var path = require('path'),
|
||||
dev: {
|
||||
files: {
|
||||
'core/built/scripts/vendor.js': [
|
||||
'core/shared/vendor/jquery/jquery.js',
|
||||
'core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js',
|
||||
'bower_components/jquery/dist/jquery.js',
|
||||
'bower_components/jquery-ui/ui/jquery-ui.js',
|
||||
'core/client/assets/lib/jquery-utils.js',
|
||||
'core/client/assets/lib/uploader.js',
|
||||
'core/shared/vendor/lodash.underscore.js',
|
||||
'core/shared/vendor/backbone/backbone.js',
|
||||
'core/shared/vendor/handlebars/handlebars-runtime.js',
|
||||
'core/shared/vendor/moment.js',
|
||||
|
||||
'core/shared/vendor/jquery/jquery.ui.widget.js',
|
||||
'core/shared/vendor/jquery/jquery.iframe-transport.js',
|
||||
'core/shared/vendor/jquery/jquery.fileupload.js',
|
||||
'bower_components/lodash/dist/lodash.underscore.js',
|
||||
'bower_components/backbone/backbone.js',
|
||||
'bower_components/handlebars.js/dist/handlebars.runtime.js',
|
||||
'bower_components/moment/moment.js',
|
||||
'bower_components/jquery-file-upload/js/jquery.fileupload.js',
|
||||
'bower_components/codemirror/lib/codemirror.js',
|
||||
'bower_components/codemirror/lib/addon/mode/overlay.js',
|
||||
'bower_components/codemirror/lib/mode/markdown/markdown.js',
|
||||
'bower_components/codemirror/lib/mode/gfm/gfm.js',
|
||||
'bower_components/showdown/src/showdown.js',
|
||||
'bower_components/validator-js/validator.js',
|
||||
|
||||
'core/client/assets/vendor/codemirror/codemirror.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/gfm/gfm.js',
|
||||
'core/client/assets/vendor/showdown/showdown.js',
|
||||
'core/client/assets/vendor/showdown/extensions/ghostdown.js',
|
||||
'core/shared/vendor/showdown/extensions/typography.js',
|
||||
'core/shared/vendor/showdown/extensions/github.js',
|
||||
'core/client/assets/lib/showdown/extensions/ghostdown.js',
|
||||
'core/shared/lib/showdown/extensions/typography.js',
|
||||
'core/shared/lib/showdown/extensions/github.js',
|
||||
|
||||
// ToDo: Remove or replace
|
||||
'core/client/assets/vendor/shortcuts.js',
|
||||
'core/client/assets/vendor/validator-client.js',
|
||||
'core/client/assets/vendor/countable.js',
|
||||
'core/client/assets/vendor/to-title-case.js',
|
||||
'core/client/assets/vendor/packery.pkgd.min.js',
|
||||
'core/client/assets/vendor/fastclick.js',
|
||||
'core/client/assets/vendor/nprogress.js'
|
||||
|
||||
'bower_components/Countable/Countable.js',
|
||||
'bower_components/fastclick/lib/fastclick.js',
|
||||
'bower_components/nprogress/nprogress.js'
|
||||
],
|
||||
|
||||
'core/built/scripts/helpers.js': [
|
||||
@ -481,34 +503,34 @@ var path = require('path'),
|
||||
prod: {
|
||||
files: {
|
||||
'core/built/scripts/ghost.js': [
|
||||
'core/shared/vendor/jquery/jquery.js',
|
||||
'core/shared/vendor/jquery/jquery-ui-1.10.3.custom.min.js',
|
||||
'bower_components/jquery/dist/jquery.js',
|
||||
'bower_components/jquery-ui/ui/jquery-ui.js',
|
||||
'core/client/assets/lib/jquery-utils.js',
|
||||
'core/client/assets/lib/uploader.js',
|
||||
'core/shared/vendor/lodash.underscore.js',
|
||||
'core/shared/vendor/backbone/backbone.js',
|
||||
'core/shared/vendor/handlebars/handlebars-runtime.js',
|
||||
'core/shared/vendor/moment.js',
|
||||
|
||||
'core/shared/vendor/jquery/jquery.ui.widget.js',
|
||||
'core/shared/vendor/jquery/jquery.iframe-transport.js',
|
||||
'core/shared/vendor/jquery/jquery.fileupload.js',
|
||||
'bower_components/lodash/dist/lodash.underscore.js',
|
||||
'bower_components/backbone/backbone.js',
|
||||
'bower_components/handlebars.js/dist/handlebars.runtime.js',
|
||||
'bower_components/moment/moment.js',
|
||||
'bower_components/jquery-file-upload/js/jquery.fileupload.js',
|
||||
'bower_components/codemirror/lib/codemirror.js',
|
||||
'bower_components/codemirror/lib/addon/mode/overlay.js',
|
||||
'bower_components/codemirror/lib/mode/markdown/markdown.js',
|
||||
'bower_components/codemirror/lib/mode/gfm/gfm.js',
|
||||
'bower_components/showdown/src/showdown.js',
|
||||
'bower_components/validator-js/validator.js',
|
||||
|
||||
'core/client/assets/vendor/codemirror/codemirror.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/gfm/gfm.js',
|
||||
'core/client/assets/vendor/showdown/showdown.js',
|
||||
'core/client/assets/vendor/showdown/extensions/ghostdown.js',
|
||||
'core/shared/vendor/showdown/extensions/typography.js',
|
||||
'core/shared/vendor/showdown/extensions/github.js',
|
||||
'core/client/assets/lib/showdown/extensions/ghostdown.js',
|
||||
'core/shared/lib/showdown/extensions/typography.js',
|
||||
'core/shared/lib/showdown/extensions/github.js',
|
||||
|
||||
// ToDo: Remove or replace
|
||||
'core/client/assets/vendor/shortcuts.js',
|
||||
'core/client/assets/vendor/validator-client.js',
|
||||
'core/client/assets/vendor/countable.js',
|
||||
'core/client/assets/vendor/to-title-case.js',
|
||||
'core/client/assets/vendor/packery.pkgd.min.js',
|
||||
'core/client/assets/vendor/fastclick.js',
|
||||
'core/client/assets/vendor/nprogress.js',
|
||||
|
||||
'bower_components/Countable/Countable.js',
|
||||
'bower_components/fastclick/lib/fastclick.js',
|
||||
'bower_components/nprogress/nprogress.js',
|
||||
|
||||
'core/client/init.js',
|
||||
|
||||
@ -858,6 +880,7 @@ var path = require('path'),
|
||||
'sass:admin',
|
||||
'handlebars',
|
||||
'concat',
|
||||
'copy:dev',
|
||||
'express:dev',
|
||||
'watch'
|
||||
]);
|
||||
@ -877,7 +900,7 @@ var path = require('path'),
|
||||
|
||||
grunt.registerTask('test-integration', 'Run integration tests (mocha + db access)', ['clean:test', 'setTestEnv', 'loadConfig', 'mochacli:integration']);
|
||||
|
||||
grunt.registerTask('test-functional', 'Run functional interface tests (CasperJS)', ['clean:test', 'setTestEnv', 'loadConfig', 'express:test', 'spawn-casperjs', 'express:test:stop']);
|
||||
grunt.registerTask('test-functional', 'Run functional interface tests (CasperJS)', ['clean:test', 'setTestEnv', 'loadConfig', 'copy:dev', 'express:test', 'spawn-casperjs', 'express:test:stop']);
|
||||
|
||||
grunt.registerTask('test-api', 'Run functional api tests (mocha)', ['clean:test', 'setTestEnv', 'loadConfig', 'express:test', 'mochacli:api', 'express:test:stop']);
|
||||
|
||||
@ -901,10 +924,10 @@ var path = require('path'),
|
||||
grunt.registerTask('init', 'Prepare the project for development', ['shell:bundle', 'shell:bourbon', 'default']);
|
||||
|
||||
// Before running in production mode
|
||||
grunt.registerTask('prod', 'Build CSS, JS & templates for production', ['sass:compress', 'handlebars', 'concat', 'uglify']);
|
||||
grunt.registerTask('prod', 'Build CSS, JS & templates for production', ['sass:compress', 'handlebars', 'concat', 'uglify', 'copy:prod']);
|
||||
|
||||
// When you just say 'grunt'
|
||||
grunt.registerTask('default', 'Build CSS, JS & templates for development', ['update_submodules', 'sass:compress', 'handlebars', 'concat']);
|
||||
grunt.registerTask('default', 'Build CSS, JS & templates for development', ['update_submodules', 'sass:compress', 'handlebars', 'concat', 'copy:dev']);
|
||||
};
|
||||
|
||||
module.exports = configureGrunt;
|
||||
|
20
bower.json
Normal file
20
bower.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "ghost",
|
||||
"dependencies": {
|
||||
"jquery": "1.11.0",
|
||||
"jquery-file-upload": "9.5.6",
|
||||
"jquery-hammerjs": "1.0.1",
|
||||
"jquery-ui": "1.10.4",
|
||||
"showdown": "0.3.1",
|
||||
"codemirror": "3.15.0",
|
||||
"backbone": "1.0.0",
|
||||
"handlebars.js": "1.0.0",
|
||||
"lodash": "2.4.1",
|
||||
"moment": "2.4.0",
|
||||
"iCheck": "1.0.1",
|
||||
"nprogress": "0.1.2",
|
||||
"fastclick": "1.0.0",
|
||||
"Countable": "2.0.2",
|
||||
"validator-js": "1.5.1"
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
/* jshint node:true, browser:true */
|
||||
(function () {
|
||||
var ghostdown = function () {
|
||||
return [
|
||||
@ -41,5 +42,7 @@
|
||||
window.Showdown.extensions.ghostdown = ghostdown;
|
||||
}
|
||||
// Server-side export
|
||||
if (typeof module !== 'undefined') module.exports = ghostdown;
|
||||
if (typeof module !== 'undefined') {
|
||||
module.exports = ghostdown;
|
||||
}
|
||||
}());
|
@ -1,59 +0,0 @@
|
||||
// Utility function that allows modes to be combined. The mode given
|
||||
// as the base argument takes care of most of the normal mode
|
||||
// functionality, but a second (typically simple) mode is used, which
|
||||
// can override the style of text. Both modes get to parse all of the
|
||||
// text, but when both assign a non-null style to a piece of code, the
|
||||
// overlay wins, unless the combine argument was true, in which case
|
||||
// the styles are combined.
|
||||
|
||||
// overlayParser is the old, deprecated name
|
||||
CodeMirror.overlayMode = CodeMirror.overlayParser = function(base, overlay, combine) {
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
base: CodeMirror.startState(base),
|
||||
overlay: CodeMirror.startState(overlay),
|
||||
basePos: 0, baseCur: null,
|
||||
overlayPos: 0, overlayCur: null
|
||||
};
|
||||
},
|
||||
copyState: function(state) {
|
||||
return {
|
||||
base: CodeMirror.copyState(base, state.base),
|
||||
overlay: CodeMirror.copyState(overlay, state.overlay),
|
||||
basePos: state.basePos, baseCur: null,
|
||||
overlayPos: state.overlayPos, overlayCur: null
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.start == state.basePos) {
|
||||
state.baseCur = base.token(stream, state.base);
|
||||
state.basePos = stream.pos;
|
||||
}
|
||||
if (stream.start == state.overlayPos) {
|
||||
stream.pos = stream.start;
|
||||
state.overlayCur = overlay.token(stream, state.overlay);
|
||||
state.overlayPos = stream.pos;
|
||||
}
|
||||
stream.pos = Math.min(state.basePos, state.overlayPos);
|
||||
if (stream.eol()) state.basePos = state.overlayPos = 0;
|
||||
|
||||
if (state.overlayCur == null) return state.baseCur;
|
||||
if (state.baseCur != null && combine) return state.baseCur + " " + state.overlayCur;
|
||||
else return state.overlayCur;
|
||||
},
|
||||
|
||||
indent: base.indent && function(state, textAfter) {
|
||||
return base.indent(state.base, textAfter);
|
||||
},
|
||||
electricChars: base.electricChars,
|
||||
|
||||
innerMode: function(state) { return {state: state.base, mode: base}; },
|
||||
|
||||
blankLine: function(state) {
|
||||
if (base.blankLine) base.blankLine(state.base);
|
||||
if (overlay.blankLine) overlay.blankLine(state.overlay);
|
||||
}
|
||||
};
|
||||
};
|
5799
core/client/assets/vendor/codemirror/codemirror.js
vendored
5799
core/client/assets/vendor/codemirror/codemirror.js
vendored
File diff suppressed because it is too large
Load Diff
@ -1,96 +0,0 @@
|
||||
CodeMirror.defineMode("gfm", function(config) {
|
||||
var codeDepth = 0;
|
||||
function blankLine(state) {
|
||||
state.code = false;
|
||||
return null;
|
||||
}
|
||||
var gfmOverlay = {
|
||||
startState: function() {
|
||||
return {
|
||||
code: false,
|
||||
codeBlock: false,
|
||||
ateSpace: false
|
||||
};
|
||||
},
|
||||
copyState: function(s) {
|
||||
return {
|
||||
code: s.code,
|
||||
codeBlock: s.codeBlock,
|
||||
ateSpace: s.ateSpace
|
||||
};
|
||||
},
|
||||
token: function(stream, state) {
|
||||
// Hack to prevent formatting override inside code blocks (block and inline)
|
||||
if (state.codeBlock) {
|
||||
if (stream.match(/^```/)) {
|
||||
state.codeBlock = false;
|
||||
return null;
|
||||
}
|
||||
stream.skipToEnd();
|
||||
return null;
|
||||
}
|
||||
if (stream.sol()) {
|
||||
state.code = false;
|
||||
}
|
||||
if (stream.sol() && stream.match(/^```/)) {
|
||||
stream.skipToEnd();
|
||||
state.codeBlock = true;
|
||||
return null;
|
||||
}
|
||||
// If this block is changed, it may need to be updated in Markdown mode
|
||||
if (stream.peek() === '`') {
|
||||
stream.next();
|
||||
var before = stream.pos;
|
||||
stream.eatWhile('`');
|
||||
var difference = 1 + stream.pos - before;
|
||||
if (!state.code) {
|
||||
codeDepth = difference;
|
||||
state.code = true;
|
||||
} else {
|
||||
if (difference === codeDepth) { // Must be exact
|
||||
state.code = false;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else if (state.code) {
|
||||
stream.next();
|
||||
return null;
|
||||
}
|
||||
// Check if space. If so, links can be formatted later on
|
||||
if (stream.eatSpace()) {
|
||||
state.ateSpace = true;
|
||||
return null;
|
||||
}
|
||||
if (stream.sol() || state.ateSpace) {
|
||||
state.ateSpace = false;
|
||||
if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) {
|
||||
// User/Project@SHA
|
||||
// User@SHA
|
||||
// SHA
|
||||
return "link";
|
||||
} else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) {
|
||||
// User/Project#Num
|
||||
// User#Num
|
||||
// #Num
|
||||
return "link";
|
||||
}
|
||||
}
|
||||
if (stream.match(/^((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]+|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))/i)) {
|
||||
// URLs
|
||||
// Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
||||
// And then (issue #1160) simplified to make it not crash the Chrome Regexp engine
|
||||
return "link";
|
||||
}
|
||||
stream.next();
|
||||
return null;
|
||||
},
|
||||
blankLine: blankLine
|
||||
};
|
||||
CodeMirror.defineMIME("gfmBase", {
|
||||
name: "markdown",
|
||||
underscoresBreakWords: false,
|
||||
taskLists: true,
|
||||
fencedCodeBlocks: true
|
||||
});
|
||||
return CodeMirror.overlayMode(CodeMirror.getMode(config, "gfmBase"), gfmOverlay);
|
||||
}, "markdown");
|
@ -1,74 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CodeMirror: GFM mode</title>
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/mode/overlay.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="../markdown/markdown.js"></script>
|
||||
<script src="gfm.js"></script>
|
||||
|
||||
<!-- Code block highlighting modes -->
|
||||
<script src="../javascript/javascript.js"></script>
|
||||
<script src="../css/css.js"></script>
|
||||
<script src="../htmlmixed/htmlmixed.js"></script>
|
||||
<script src="../clike/clike.js"></script>
|
||||
|
||||
<style type="text/css">.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}</style>
|
||||
<link rel="stylesheet" href="../../doc/docs.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>CodeMirror: GFM mode</h1>
|
||||
|
||||
<form><textarea id="code" name="code">
|
||||
GitHub Flavored Markdown
|
||||
========================
|
||||
|
||||
Everything from markdown plus GFM features:
|
||||
|
||||
## URL autolinking
|
||||
|
||||
Underscores_are_allowed_between_words.
|
||||
|
||||
## Fenced code blocks (and syntax highlighting)
|
||||
|
||||
```javascript
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
console.log(items[i], i); // log them
|
||||
}
|
||||
```
|
||||
|
||||
## Task Lists
|
||||
|
||||
- [ ] Incomplete task list item
|
||||
- [x] **Completed** task list item
|
||||
|
||||
## A bit of GitHub spice
|
||||
|
||||
* SHA: be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||
* User@SHA ref: mojombo@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||
* User/Project@SHA: mojombo/god@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2
|
||||
* \#Num: #1
|
||||
* User/#Num: mojombo#1
|
||||
* User/Project#Num: mojombo/god#1
|
||||
|
||||
See http://github.github.com/github-flavored-markdown/.
|
||||
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: 'gfm',
|
||||
lineNumbers: true,
|
||||
theme: "default"
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Optionally depends on other modes for properly highlighted code blocks.</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#gfm_*">normal</a>, <a href="../../test/index.html#verbose,gfm_*">verbose</a>.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,112 +0,0 @@
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({tabSize: 4}, "gfm");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MT("emInWordAsterisk",
|
||||
"foo[em *bar*]hello");
|
||||
|
||||
MT("emInWordUnderscore",
|
||||
"foo_bar_hello");
|
||||
|
||||
MT("emStrongUnderscore",
|
||||
"[strong __][em&strong _foo__][em _] bar");
|
||||
|
||||
MT("fencedCodeBlocks",
|
||||
"[comment ```]",
|
||||
"[comment foo]",
|
||||
"",
|
||||
"[comment ```]",
|
||||
"bar");
|
||||
|
||||
MT("fencedCodeBlockModeSwitching",
|
||||
"[comment ```javascript]",
|
||||
"[variable foo]",
|
||||
"",
|
||||
"[comment ```]",
|
||||
"bar");
|
||||
|
||||
MT("taskListAsterisk",
|
||||
"[variable-2 * []] foo]", // Invalid; must have space or x between []
|
||||
"[variable-2 * [ ]]bar]", // Invalid; must have space after ]
|
||||
"[variable-2 * [x]]hello]", // Invalid; must have space after ]
|
||||
"[variable-2 * ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links
|
||||
" [variable-3 * ][property [x]]][variable-3 foo]"); // Valid; can be nested
|
||||
|
||||
MT("taskListPlus",
|
||||
"[variable-2 + []] foo]", // Invalid; must have space or x between []
|
||||
"[variable-2 + [ ]]bar]", // Invalid; must have space after ]
|
||||
"[variable-2 + [x]]hello]", // Invalid; must have space after ]
|
||||
"[variable-2 + ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links
|
||||
" [variable-3 + ][property [x]]][variable-3 foo]"); // Valid; can be nested
|
||||
|
||||
MT("taskListDash",
|
||||
"[variable-2 - []] foo]", // Invalid; must have space or x between []
|
||||
"[variable-2 - [ ]]bar]", // Invalid; must have space after ]
|
||||
"[variable-2 - [x]]hello]", // Invalid; must have space after ]
|
||||
"[variable-2 - ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links
|
||||
" [variable-3 - ][property [x]]][variable-3 foo]"); // Valid; can be nested
|
||||
|
||||
MT("taskListNumber",
|
||||
"[variable-2 1. []] foo]", // Invalid; must have space or x between []
|
||||
"[variable-2 2. [ ]]bar]", // Invalid; must have space after ]
|
||||
"[variable-2 3. [x]]hello]", // Invalid; must have space after ]
|
||||
"[variable-2 4. ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links
|
||||
" [variable-3 1. ][property [x]]][variable-3 foo]"); // Valid; can be nested
|
||||
|
||||
MT("SHA",
|
||||
"foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar");
|
||||
|
||||
MT("shortSHA",
|
||||
"foo [link be6a8cc] bar");
|
||||
|
||||
MT("tooShortSHA",
|
||||
"foo be6a8c bar");
|
||||
|
||||
MT("longSHA",
|
||||
"foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar");
|
||||
|
||||
MT("badSHA",
|
||||
"foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar");
|
||||
|
||||
MT("userSHA",
|
||||
"foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello");
|
||||
|
||||
MT("userProjectSHA",
|
||||
"foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world");
|
||||
|
||||
MT("num",
|
||||
"foo [link #1] bar");
|
||||
|
||||
MT("badNum",
|
||||
"foo #1bar hello");
|
||||
|
||||
MT("userNum",
|
||||
"foo [link bar#1] hello");
|
||||
|
||||
MT("userProjectNum",
|
||||
"foo [link bar/hello#1] world");
|
||||
|
||||
MT("vanillaLink",
|
||||
"foo [link http://www.example.com/] bar");
|
||||
|
||||
MT("vanillaLinkPunctuation",
|
||||
"foo [link http://www.example.com/]. bar");
|
||||
|
||||
MT("vanillaLinkExtension",
|
||||
"foo [link http://www.example.com/index.html] bar");
|
||||
|
||||
MT("notALink",
|
||||
"[comment ```css]",
|
||||
"[tag foo] {[property color][operator :][keyword black];}",
|
||||
"[comment ```][link http://www.example.com/]");
|
||||
|
||||
MT("notALink",
|
||||
"[comment ``foo `bar` http://www.example.com/``] hello");
|
||||
|
||||
MT("notALink",
|
||||
"[comment `foo]",
|
||||
"[link http://www.example.com/]",
|
||||
"[comment `foo]",
|
||||
"",
|
||||
"[link http://www.example.com/]");
|
||||
})();
|
@ -1,349 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CodeMirror: Markdown mode</title>
|
||||
<link rel="stylesheet" href="../../lib/codemirror.css">
|
||||
<script src="../../lib/codemirror.js"></script>
|
||||
<script src="../../addon/edit/continuelist.js"></script>
|
||||
<script src="../xml/xml.js"></script>
|
||||
<script src="markdown.js"></script>
|
||||
<style type="text/css">
|
||||
.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
|
||||
.cm-s-default .cm-trailing-space-a:before,
|
||||
.cm-s-default .cm-trailing-space-b:before {position: absolute; content: "\00B7"; color: #777;}
|
||||
.cm-s-default .cm-trailing-space-new-line:before {position: absolute; content: "\21B5"; color: #777;}
|
||||
</style>
|
||||
<link rel="stylesheet" href="../../doc/docs.css">
|
||||
</head>
|
||||
<body>
|
||||
<h1>CodeMirror: Markdown mode</h1>
|
||||
|
||||
<!-- source: http://daringfireball.net/projects/markdown/basics.text -->
|
||||
<form><textarea id="code" name="code">
|
||||
Markdown: Basics
|
||||
================
|
||||
|
||||
<ul id="ProjectSubmenu">
|
||||
<li><a href="/projects/markdown/" title="Markdown Project Page">Main</a></li>
|
||||
<li><a class="selected" title="Markdown Basics">Basics</a></li>
|
||||
<li><a href="/projects/markdown/syntax" title="Markdown Syntax Documentation">Syntax</a></li>
|
||||
<li><a href="/projects/markdown/license" title="Pricing and License Information">License</a></li>
|
||||
<li><a href="/projects/markdown/dingus" title="Online Markdown Web Form">Dingus</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
Getting the Gist of Markdown's Formatting Syntax
|
||||
------------------------------------------------
|
||||
|
||||
This page offers a brief overview of what it's like to use Markdown.
|
||||
The [syntax page] [s] provides complete, detailed documentation for
|
||||
every feature, but Markdown should be very easy to pick up simply by
|
||||
looking at a few examples of it in action. The examples on this page
|
||||
are written in a before/after style, showing example syntax and the
|
||||
HTML output produced by Markdown.
|
||||
|
||||
It's also helpful to simply try Markdown out; the [Dingus] [d] is a
|
||||
web application that allows you type your own Markdown-formatted text
|
||||
and translate it to XHTML.
|
||||
|
||||
**Note:** This document is itself written using Markdown; you
|
||||
can [see the source for it by adding '.text' to the URL] [src].
|
||||
|
||||
[s]: /projects/markdown/syntax "Markdown Syntax"
|
||||
[d]: /projects/markdown/dingus "Markdown Dingus"
|
||||
[src]: /projects/markdown/basics.text
|
||||
|
||||
|
||||
## Paragraphs, Headers, Blockquotes ##
|
||||
|
||||
A paragraph is simply one or more consecutive lines of text, separated
|
||||
by one or more blank lines. (A blank line is any line that looks like
|
||||
a blank line -- a line containing nothing but spaces or tabs is
|
||||
considered blank.) Normal paragraphs should not be indented with
|
||||
spaces or tabs.
|
||||
|
||||
Markdown offers two styles of headers: *Setext* and *atx*.
|
||||
Setext-style headers for `<h1>` and `<h2>` are created by
|
||||
"underlining" with equal signs (`=`) and hyphens (`-`), respectively.
|
||||
To create an atx-style header, you put 1-6 hash marks (`#`) at the
|
||||
beginning of the line -- the number of hashes equals the resulting
|
||||
HTML header level.
|
||||
|
||||
Blockquotes are indicated using email-style '`>`' angle brackets.
|
||||
|
||||
Markdown:
|
||||
|
||||
A First Level Header
|
||||
====================
|
||||
|
||||
A Second Level Header
|
||||
---------------------
|
||||
|
||||
Now is the time for all good men to come to
|
||||
the aid of their country. This is just a
|
||||
regular paragraph.
|
||||
|
||||
The quick brown fox jumped over the lazy
|
||||
dog's back.
|
||||
|
||||
### Header 3
|
||||
|
||||
> This is a blockquote.
|
||||
>
|
||||
> This is the second paragraph in the blockquote.
|
||||
>
|
||||
> ## This is an H2 in a blockquote
|
||||
|
||||
|
||||
Output:
|
||||
|
||||
<h1>A First Level Header</h1>
|
||||
|
||||
<h2>A Second Level Header</h2>
|
||||
|
||||
<p>Now is the time for all good men to come to
|
||||
the aid of their country. This is just a
|
||||
regular paragraph.</p>
|
||||
|
||||
<p>The quick brown fox jumped over the lazy
|
||||
dog's back.</p>
|
||||
|
||||
<h3>Header 3</h3>
|
||||
|
||||
<blockquote>
|
||||
<p>This is a blockquote.</p>
|
||||
|
||||
<p>This is the second paragraph in the blockquote.</p>
|
||||
|
||||
<h2>This is an H2 in a blockquote</h2>
|
||||
</blockquote>
|
||||
|
||||
|
||||
|
||||
### Phrase Emphasis ###
|
||||
|
||||
Markdown uses asterisks and underscores to indicate spans of emphasis.
|
||||
|
||||
Markdown:
|
||||
|
||||
Some of these words *are emphasized*.
|
||||
Some of these words _are emphasized also_.
|
||||
|
||||
Use two asterisks for **strong emphasis**.
|
||||
Or, if you prefer, __use two underscores instead__.
|
||||
|
||||
Output:
|
||||
|
||||
<p>Some of these words <em>are emphasized</em>.
|
||||
Some of these words <em>are emphasized also</em>.</p>
|
||||
|
||||
<p>Use two asterisks for <strong>strong emphasis</strong>.
|
||||
Or, if you prefer, <strong>use two underscores instead</strong>.</p>
|
||||
|
||||
|
||||
|
||||
## Lists ##
|
||||
|
||||
Unordered (bulleted) lists use asterisks, pluses, and hyphens (`*`,
|
||||
`+`, and `-`) as list markers. These three markers are
|
||||
interchangable; this:
|
||||
|
||||
* Candy.
|
||||
* Gum.
|
||||
* Booze.
|
||||
|
||||
this:
|
||||
|
||||
+ Candy.
|
||||
+ Gum.
|
||||
+ Booze.
|
||||
|
||||
and this:
|
||||
|
||||
- Candy.
|
||||
- Gum.
|
||||
- Booze.
|
||||
|
||||
all produce the same output:
|
||||
|
||||
<ul>
|
||||
<li>Candy.</li>
|
||||
<li>Gum.</li>
|
||||
<li>Booze.</li>
|
||||
</ul>
|
||||
|
||||
Ordered (numbered) lists use regular numbers, followed by periods, as
|
||||
list markers:
|
||||
|
||||
1. Red
|
||||
2. Green
|
||||
3. Blue
|
||||
|
||||
Output:
|
||||
|
||||
<ol>
|
||||
<li>Red</li>
|
||||
<li>Green</li>
|
||||
<li>Blue</li>
|
||||
</ol>
|
||||
|
||||
If you put blank lines between items, you'll get `<p>` tags for the
|
||||
list item text. You can create multi-paragraph list items by indenting
|
||||
the paragraphs by 4 spaces or 1 tab:
|
||||
|
||||
* A list item.
|
||||
|
||||
With multiple paragraphs.
|
||||
|
||||
* Another item in the list.
|
||||
|
||||
Output:
|
||||
|
||||
<ul>
|
||||
<li><p>A list item.</p>
|
||||
<p>With multiple paragraphs.</p></li>
|
||||
<li><p>Another item in the list.</p></li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
### Links ###
|
||||
|
||||
Markdown supports two styles for creating links: *inline* and
|
||||
*reference*. With both styles, you use square brackets to delimit the
|
||||
text you want to turn into a link.
|
||||
|
||||
Inline-style links use parentheses immediately after the link text.
|
||||
For example:
|
||||
|
||||
This is an [example link](http://example.com/).
|
||||
|
||||
Output:
|
||||
|
||||
<p>This is an <a href="http://example.com/">
|
||||
example link</a>.</p>
|
||||
|
||||
Optionally, you may include a title attribute in the parentheses:
|
||||
|
||||
This is an [example link](http://example.com/ "With a Title").
|
||||
|
||||
Output:
|
||||
|
||||
<p>This is an <a href="http://example.com/" title="With a Title">
|
||||
example link</a>.</p>
|
||||
|
||||
Reference-style links allow you to refer to your links by names, which
|
||||
you define elsewhere in your document:
|
||||
|
||||
I get 10 times more traffic from [Google][1] than from
|
||||
[Yahoo][2] or [MSN][3].
|
||||
|
||||
[1]: http://google.com/ "Google"
|
||||
[2]: http://search.yahoo.com/ "Yahoo Search"
|
||||
[3]: http://search.msn.com/ "MSN Search"
|
||||
|
||||
Output:
|
||||
|
||||
<p>I get 10 times more traffic from <a href="http://google.com/"
|
||||
title="Google">Google</a> than from <a href="http://search.yahoo.com/"
|
||||
title="Yahoo Search">Yahoo</a> or <a href="http://search.msn.com/"
|
||||
title="MSN Search">MSN</a>.</p>
|
||||
|
||||
The title attribute is optional. Link names may contain letters,
|
||||
numbers and spaces, but are *not* case sensitive:
|
||||
|
||||
I start my morning with a cup of coffee and
|
||||
[The New York Times][NY Times].
|
||||
|
||||
[ny times]: http://www.nytimes.com/
|
||||
|
||||
Output:
|
||||
|
||||
<p>I start my morning with a cup of coffee and
|
||||
<a href="http://www.nytimes.com/">The New York Times</a>.</p>
|
||||
|
||||
|
||||
### Images ###
|
||||
|
||||
Image syntax is very much like link syntax.
|
||||
|
||||
Inline (titles are optional):
|
||||
|
||||
![alt text](/path/to/img.jpg "Title")
|
||||
|
||||
Reference-style:
|
||||
|
||||
![alt text][id]
|
||||
|
||||
[id]: /path/to/img.jpg "Title"
|
||||
|
||||
Both of the above examples produce the same output:
|
||||
|
||||
<img src="/path/to/img.jpg" alt="alt text" title="Title" />
|
||||
|
||||
|
||||
|
||||
### Code ###
|
||||
|
||||
In a regular paragraph, you can create code span by wrapping text in
|
||||
backtick quotes. Any ampersands (`&`) and angle brackets (`<` or
|
||||
`>`) will automatically be translated into HTML entities. This makes
|
||||
it easy to use Markdown to write about HTML example code:
|
||||
|
||||
I strongly recommend against using any `<blink>` tags.
|
||||
|
||||
I wish SmartyPants used named entities like `&mdash;`
|
||||
instead of decimal-encoded entites like `&#8212;`.
|
||||
|
||||
Output:
|
||||
|
||||
<p>I strongly recommend against using any
|
||||
<code>&lt;blink&gt;</code> tags.</p>
|
||||
|
||||
<p>I wish SmartyPants used named entities like
|
||||
<code>&amp;mdash;</code> instead of decimal-encoded
|
||||
entites like <code>&amp;#8212;</code>.</p>
|
||||
|
||||
|
||||
To specify an entire block of pre-formatted code, indent every line of
|
||||
the block by 4 spaces or 1 tab. Just like with code spans, `&`, `<`,
|
||||
and `>` characters will be escaped automatically.
|
||||
|
||||
Markdown:
|
||||
|
||||
If you want your page to validate under XHTML 1.0 Strict,
|
||||
you've got to put paragraph tags in your blockquotes:
|
||||
|
||||
<blockquote>
|
||||
<p>For example.</p>
|
||||
</blockquote>
|
||||
|
||||
Output:
|
||||
|
||||
<p>If you want your page to validate under XHTML 1.0 Strict,
|
||||
you've got to put paragraph tags in your blockquotes:</p>
|
||||
|
||||
<pre><code>&lt;blockquote&gt;
|
||||
&lt;p&gt;For example.&lt;/p&gt;
|
||||
&lt;/blockquote&gt;
|
||||
</code></pre>
|
||||
</textarea></form>
|
||||
|
||||
<script>
|
||||
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
|
||||
mode: 'markdown',
|
||||
lineNumbers: true,
|
||||
theme: "default",
|
||||
extraKeys: {"Enter": "newlineAndIndentContinueMarkdownList"}
|
||||
});
|
||||
</script>
|
||||
|
||||
<p>Optionally depends on the XML mode for properly highlighted inline XML blocks.</p>
|
||||
|
||||
<p><strong>MIME types defined:</strong> <code>text/x-markdown</code>.</p>
|
||||
|
||||
<p><strong>Parsing/Highlighting Tests:</strong> <a href="../../test/index.html#markdown_*">normal</a>, <a href="../../test/index.html#verbose,markdown_*">verbose</a>.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,551 +0,0 @@
|
||||
CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) {
|
||||
|
||||
var htmlFound = CodeMirror.modes.hasOwnProperty("xml");
|
||||
var htmlMode = CodeMirror.getMode(cmCfg, htmlFound ? {name: "xml", htmlMode: true} : "text/plain");
|
||||
var aliases = {
|
||||
html: "htmlmixed",
|
||||
js: "javascript",
|
||||
json: "application/json",
|
||||
c: "text/x-csrc",
|
||||
"c++": "text/x-c++src",
|
||||
java: "text/x-java",
|
||||
csharp: "text/x-csharp",
|
||||
"c#": "text/x-csharp",
|
||||
scala: "text/x-scala"
|
||||
};
|
||||
|
||||
var getMode = (function () {
|
||||
var i, modes = {}, mimes = {}, mime;
|
||||
|
||||
var list = [];
|
||||
for (var m in CodeMirror.modes)
|
||||
if (CodeMirror.modes.propertyIsEnumerable(m)) list.push(m);
|
||||
for (i = 0; i < list.length; i++) {
|
||||
modes[list[i]] = list[i];
|
||||
}
|
||||
var mimesList = [];
|
||||
for (var m in CodeMirror.mimeModes)
|
||||
if (CodeMirror.mimeModes.propertyIsEnumerable(m))
|
||||
mimesList.push({mime: m, mode: CodeMirror.mimeModes[m]});
|
||||
for (i = 0; i < mimesList.length; i++) {
|
||||
mime = mimesList[i].mime;
|
||||
mimes[mime] = mimesList[i].mime;
|
||||
}
|
||||
|
||||
for (var a in aliases) {
|
||||
if (aliases[a] in modes || aliases[a] in mimes)
|
||||
modes[a] = aliases[a];
|
||||
}
|
||||
|
||||
return function (lang) {
|
||||
return modes[lang] ? CodeMirror.getMode(cmCfg, modes[lang]) : null;
|
||||
};
|
||||
}());
|
||||
|
||||
// Should underscores in words open/close em/strong?
|
||||
if (modeCfg.underscoresBreakWords === undefined)
|
||||
modeCfg.underscoresBreakWords = true;
|
||||
|
||||
// Turn on fenced code blocks? ("```" to start/end)
|
||||
if (modeCfg.fencedCodeBlocks === undefined) modeCfg.fencedCodeBlocks = false;
|
||||
|
||||
// Turn on task lists? ("- [ ] " and "- [x] ")
|
||||
if (modeCfg.taskLists === undefined) modeCfg.taskLists = false;
|
||||
|
||||
var codeDepth = 0;
|
||||
|
||||
var header = 'header'
|
||||
, code = 'comment'
|
||||
, quote1 = 'atom'
|
||||
, quote2 = 'number'
|
||||
, list1 = 'variable-2'
|
||||
, list2 = 'variable-3'
|
||||
, list3 = 'keyword'
|
||||
, hr = 'hr'
|
||||
, image = 'tag'
|
||||
, linkinline = 'link'
|
||||
, linkemail = 'link'
|
||||
, linktext = 'link'
|
||||
, linkhref = 'string'
|
||||
, em = 'em'
|
||||
, strong = 'strong';
|
||||
|
||||
var hrRE = /^([*\-=_])(?:\s*\1){2,}\s*$/
|
||||
, ulRE = /^[*\-+]\s+/
|
||||
, olRE = /^[0-9]+\.\s+/
|
||||
, taskListRE = /^\[(x| )\](?=\s)/ // Must follow ulRE or olRE
|
||||
, headerRE = /^(?:\={1,}|-{1,})$/
|
||||
, textRE = /^[^!\[\]*_\\<>` "'(]+/;
|
||||
|
||||
function switchInline(stream, state, f) {
|
||||
state.f = state.inline = f;
|
||||
return f(stream, state);
|
||||
}
|
||||
|
||||
function switchBlock(stream, state, f) {
|
||||
state.f = state.block = f;
|
||||
return f(stream, state);
|
||||
}
|
||||
|
||||
|
||||
// Blocks
|
||||
|
||||
function blankLine(state) {
|
||||
// Reset linkTitle state
|
||||
state.linkTitle = false;
|
||||
// Reset EM state
|
||||
state.em = false;
|
||||
// Reset STRONG state
|
||||
state.strong = false;
|
||||
// Reset state.quote
|
||||
state.quote = 0;
|
||||
if (!htmlFound && state.f == htmlBlock) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
}
|
||||
// Reset state.trailingSpace
|
||||
state.trailingSpace = 0;
|
||||
state.trailingSpaceNewLine = false;
|
||||
// Mark this line as blank
|
||||
state.thisLineHasContent = false;
|
||||
return null;
|
||||
}
|
||||
|
||||
function blockNormal(stream, state) {
|
||||
|
||||
var prevLineIsList = (state.list !== false);
|
||||
if (state.list !== false && state.indentationDiff >= 0) { // Continued list
|
||||
if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block
|
||||
state.indentation -= state.indentationDiff;
|
||||
}
|
||||
state.list = null;
|
||||
} else if (state.list !== false && state.indentation > 0) {
|
||||
state.list = null;
|
||||
state.listDepth = Math.floor(state.indentation / 4);
|
||||
} else if (state.list !== false) { // No longer a list
|
||||
state.list = false;
|
||||
state.listDepth = 0;
|
||||
}
|
||||
|
||||
if (state.indentationDiff >= 4) {
|
||||
state.indentation -= 4;
|
||||
stream.skipToEnd();
|
||||
return code;
|
||||
} else if (stream.eatSpace()) {
|
||||
return null;
|
||||
} else if (stream.peek() === '#' || (state.prevLineHasContent && stream.match(headerRE)) ) {
|
||||
state.header = true;
|
||||
} else if (stream.eat('>')) {
|
||||
state.indentation++;
|
||||
state.quote = 1;
|
||||
stream.eatSpace();
|
||||
while (stream.eat('>')) {
|
||||
stream.eatSpace();
|
||||
state.quote++;
|
||||
}
|
||||
} else if (stream.peek() === '[') {
|
||||
return switchInline(stream, state, footnoteLink);
|
||||
} else if (stream.match(hrRE, true)) {
|
||||
return hr;
|
||||
} else if ((!state.prevLineHasContent || prevLineIsList) && (stream.match(ulRE, true) || stream.match(olRE, true))) {
|
||||
state.indentation += 4;
|
||||
state.list = true;
|
||||
state.listDepth++;
|
||||
if (modeCfg.taskLists && stream.match(taskListRE, false)) {
|
||||
state.taskList = true;
|
||||
}
|
||||
} else if (modeCfg.fencedCodeBlocks && stream.match(/^```([\w+#]*)/, true)) {
|
||||
// try switching mode
|
||||
state.localMode = getMode(RegExp.$1);
|
||||
if (state.localMode) state.localState = state.localMode.startState();
|
||||
switchBlock(stream, state, local);
|
||||
return code;
|
||||
}
|
||||
|
||||
return switchInline(stream, state, state.inline);
|
||||
}
|
||||
|
||||
function htmlBlock(stream, state) {
|
||||
var style = htmlMode.token(stream, state.htmlState);
|
||||
if (htmlFound && style === 'tag' && state.htmlState.type !== 'openTag' && !state.htmlState.context) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
}
|
||||
if (state.md_inside && stream.current().indexOf(">")!=-1) {
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
state.htmlState.context = undefined;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
||||
function local(stream, state) {
|
||||
if (stream.sol() && stream.match(/^```/, true)) {
|
||||
state.localMode = state.localState = null;
|
||||
state.f = inlineNormal;
|
||||
state.block = blockNormal;
|
||||
return code;
|
||||
} else if (state.localMode) {
|
||||
return state.localMode.token(stream, state.localState);
|
||||
} else {
|
||||
stream.skipToEnd();
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
// Inline
|
||||
function getType(state) {
|
||||
var styles = [];
|
||||
|
||||
if (state.taskOpen) { return "meta"; }
|
||||
if (state.taskClosed) { return "property"; }
|
||||
|
||||
if (state.strong) { styles.push(strong); }
|
||||
if (state.em) { styles.push(em); }
|
||||
|
||||
if (state.linkText) { styles.push(linktext); }
|
||||
|
||||
if (state.code) { styles.push(code); }
|
||||
|
||||
if (state.header) { styles.push(header); }
|
||||
if (state.quote) { styles.push(state.quote % 2 ? quote1 : quote2); }
|
||||
if (state.list !== false) {
|
||||
var listMod = (state.listDepth - 1) % 3;
|
||||
if (!listMod) {
|
||||
styles.push(list1);
|
||||
} else if (listMod === 1) {
|
||||
styles.push(list2);
|
||||
} else {
|
||||
styles.push(list3);
|
||||
}
|
||||
}
|
||||
|
||||
if (state.trailingSpaceNewLine) {
|
||||
styles.push("trailing-space-new-line");
|
||||
} else if (state.trailingSpace) {
|
||||
styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b"));
|
||||
}
|
||||
|
||||
return styles.length ? styles.join(' ') : null;
|
||||
}
|
||||
|
||||
function handleText(stream, state) {
|
||||
if (stream.match(textRE, true)) {
|
||||
return getType(state);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inlineNormal(stream, state) {
|
||||
var style = state.text(stream, state);
|
||||
if (typeof style !== 'undefined')
|
||||
return style;
|
||||
|
||||
if (state.list) { // List marker (*, +, -, 1., etc)
|
||||
state.list = null;
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (state.taskList) {
|
||||
var taskOpen = stream.match(taskListRE, true)[1] !== "x";
|
||||
if (taskOpen) state.taskOpen = true;
|
||||
else state.taskClosed = true;
|
||||
state.taskList = false;
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
state.taskOpen = false;
|
||||
state.taskClosed = false;
|
||||
|
||||
var ch = stream.next();
|
||||
|
||||
if (ch === '\\') {
|
||||
stream.next();
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
// Matches link titles present on next line
|
||||
if (state.linkTitle) {
|
||||
state.linkTitle = false;
|
||||
var matchCh = ch;
|
||||
if (ch === '(') {
|
||||
matchCh = ')';
|
||||
}
|
||||
matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
||||
var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh;
|
||||
if (stream.match(new RegExp(regex), true)) {
|
||||
return linkhref;
|
||||
}
|
||||
}
|
||||
|
||||
// If this block is changed, it may need to be updated in GFM mode
|
||||
if (ch === '`') {
|
||||
var t = getType(state);
|
||||
var before = stream.pos;
|
||||
stream.eatWhile('`');
|
||||
var difference = 1 + stream.pos - before;
|
||||
if (!state.code) {
|
||||
codeDepth = difference;
|
||||
state.code = true;
|
||||
return getType(state);
|
||||
} else {
|
||||
if (difference === codeDepth) { // Must be exact
|
||||
state.code = false;
|
||||
return t;
|
||||
}
|
||||
return getType(state);
|
||||
}
|
||||
} else if (state.code) {
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) {
|
||||
stream.match(/\[[^\]]*\]/);
|
||||
state.inline = state.f = linkHref;
|
||||
return image;
|
||||
}
|
||||
|
||||
if (ch === '[' && stream.match(/.*\](\(| ?\[)/, false)) {
|
||||
state.linkText = true;
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
if (ch === ']' && state.linkText) {
|
||||
var type = getType(state);
|
||||
state.linkText = false;
|
||||
state.inline = state.f = linkHref;
|
||||
return type;
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) {
|
||||
return switchInline(stream, state, inlineElement(linkinline, '>'));
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) {
|
||||
return switchInline(stream, state, inlineElement(linkemail, '>'));
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^\w/, false)) {
|
||||
if (stream.string.indexOf(">")!=-1) {
|
||||
var atts = stream.string.substring(1,stream.string.indexOf(">"));
|
||||
if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) {
|
||||
state.md_inside = true;
|
||||
}
|
||||
}
|
||||
stream.backUp(1);
|
||||
return switchBlock(stream, state, htmlBlock);
|
||||
}
|
||||
|
||||
if (ch === '<' && stream.match(/^\/\w*?>/)) {
|
||||
state.md_inside = false;
|
||||
return "tag";
|
||||
}
|
||||
|
||||
var ignoreUnderscore = false;
|
||||
if (!modeCfg.underscoresBreakWords) {
|
||||
if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) {
|
||||
var prevPos = stream.pos - 2;
|
||||
if (prevPos >= 0) {
|
||||
var prevCh = stream.string.charAt(prevPos);
|
||||
if (prevCh !== '_' && prevCh.match(/(\w)/, false)) {
|
||||
ignoreUnderscore = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var t = getType(state);
|
||||
if (ch === '*' || (ch === '_' && !ignoreUnderscore)) {
|
||||
if (state.strong === ch && stream.eat(ch)) { // Remove STRONG
|
||||
state.strong = false;
|
||||
return t;
|
||||
} else if (!state.strong && stream.eat(ch)) { // Add STRONG
|
||||
state.strong = ch;
|
||||
return getType(state);
|
||||
} else if (state.em === ch) { // Remove EM
|
||||
state.em = false;
|
||||
return t;
|
||||
} else if (!state.em) { // Add EM
|
||||
state.em = ch;
|
||||
return getType(state);
|
||||
}
|
||||
} else if (ch === ' ') {
|
||||
if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces
|
||||
if (stream.peek() === ' ') { // Surrounded by spaces, ignore
|
||||
return getType(state);
|
||||
} else { // Not surrounded by spaces, back up pointer
|
||||
stream.backUp(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ch === ' ') {
|
||||
if (stream.match(/ +$/, false)) {
|
||||
state.trailingSpace++;
|
||||
} else if (state.trailingSpace) {
|
||||
state.trailingSpaceNewLine = true;
|
||||
}
|
||||
}
|
||||
|
||||
return getType(state);
|
||||
}
|
||||
|
||||
function linkHref(stream, state) {
|
||||
// Check if space, and return NULL if so (to avoid marking the space)
|
||||
if(stream.eatSpace()){
|
||||
return null;
|
||||
}
|
||||
var ch = stream.next();
|
||||
if (ch === '(' || ch === '[') {
|
||||
return switchInline(stream, state, inlineElement(linkhref, ch === '(' ? ')' : ']'));
|
||||
}
|
||||
return 'error';
|
||||
}
|
||||
|
||||
function footnoteLink(stream, state) {
|
||||
if (stream.match(/^[^\]]*\]:/, true)) {
|
||||
state.f = footnoteUrl;
|
||||
return linktext;
|
||||
}
|
||||
return switchInline(stream, state, inlineNormal);
|
||||
}
|
||||
|
||||
function footnoteUrl(stream, state) {
|
||||
// Check if space, and return NULL if so (to avoid marking the space)
|
||||
if(stream.eatSpace()){
|
||||
return null;
|
||||
}
|
||||
// Match URL
|
||||
stream.match(/^[^\s]+/, true);
|
||||
// Check for link title
|
||||
if (stream.peek() === undefined) { // End of line, set flag to check next line
|
||||
state.linkTitle = true;
|
||||
} else { // More content on line, check if link title
|
||||
stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true);
|
||||
}
|
||||
state.f = state.inline = inlineNormal;
|
||||
return linkhref;
|
||||
}
|
||||
|
||||
var savedInlineRE = [];
|
||||
function inlineRE(endChar) {
|
||||
if (!savedInlineRE[endChar]) {
|
||||
// Escape endChar for RegExp (taken from http://stackoverflow.com/a/494122/526741)
|
||||
endChar = (endChar+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
|
||||
// Match any non-endChar, escaped character, as well as the closing
|
||||
// endChar.
|
||||
savedInlineRE[endChar] = new RegExp('^(?:[^\\\\]|\\\\.)*?(' + endChar + ')');
|
||||
}
|
||||
return savedInlineRE[endChar];
|
||||
}
|
||||
|
||||
function inlineElement(type, endChar, next) {
|
||||
next = next || inlineNormal;
|
||||
return function(stream, state) {
|
||||
stream.match(inlineRE(endChar));
|
||||
state.inline = state.f = next;
|
||||
return type;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
startState: function() {
|
||||
return {
|
||||
f: blockNormal,
|
||||
|
||||
prevLineHasContent: false,
|
||||
thisLineHasContent: false,
|
||||
|
||||
block: blockNormal,
|
||||
htmlState: CodeMirror.startState(htmlMode),
|
||||
indentation: 0,
|
||||
|
||||
inline: inlineNormal,
|
||||
text: handleText,
|
||||
|
||||
linkText: false,
|
||||
linkTitle: false,
|
||||
em: false,
|
||||
strong: false,
|
||||
header: false,
|
||||
taskList: false,
|
||||
list: false,
|
||||
listDepth: 0,
|
||||
quote: 0,
|
||||
trailingSpace: 0,
|
||||
trailingSpaceNewLine: false
|
||||
};
|
||||
},
|
||||
|
||||
copyState: function(s) {
|
||||
return {
|
||||
f: s.f,
|
||||
|
||||
prevLineHasContent: s.prevLineHasContent,
|
||||
thisLineHasContent: s.thisLineHasContent,
|
||||
|
||||
block: s.block,
|
||||
htmlState: CodeMirror.copyState(htmlMode, s.htmlState),
|
||||
indentation: s.indentation,
|
||||
|
||||
localMode: s.localMode,
|
||||
localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null,
|
||||
|
||||
inline: s.inline,
|
||||
text: s.text,
|
||||
linkTitle: s.linkTitle,
|
||||
em: s.em,
|
||||
strong: s.strong,
|
||||
header: s.header,
|
||||
taskList: s.taskList,
|
||||
list: s.list,
|
||||
listDepth: s.listDepth,
|
||||
quote: s.quote,
|
||||
trailingSpace: s.trailingSpace,
|
||||
trailingSpaceNewLine: s.trailingSpaceNewLine,
|
||||
md_inside: s.md_inside
|
||||
};
|
||||
},
|
||||
|
||||
token: function(stream, state) {
|
||||
if (stream.sol()) {
|
||||
if (stream.match(/^\s*$/, true)) {
|
||||
state.prevLineHasContent = false;
|
||||
return blankLine(state);
|
||||
} else {
|
||||
state.prevLineHasContent = state.thisLineHasContent;
|
||||
state.thisLineHasContent = true;
|
||||
}
|
||||
|
||||
// Reset state.header
|
||||
state.header = false;
|
||||
|
||||
// Reset state.taskList
|
||||
state.taskList = false;
|
||||
|
||||
// Reset state.code
|
||||
state.code = false;
|
||||
|
||||
// Reset state.trailingSpace
|
||||
state.trailingSpace = 0;
|
||||
state.trailingSpaceNewLine = false;
|
||||
|
||||
state.f = state.block;
|
||||
var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length;
|
||||
var difference = Math.floor((indentation - state.indentation) / 4) * 4;
|
||||
if (difference > 4) difference = 4;
|
||||
var adjustedIndentation = state.indentation + difference;
|
||||
state.indentationDiff = adjustedIndentation - state.indentation;
|
||||
state.indentation = adjustedIndentation;
|
||||
if (indentation > 0) return null;
|
||||
}
|
||||
return state.f(stream, state);
|
||||
},
|
||||
|
||||
blankLine: blankLine,
|
||||
|
||||
getType: getType
|
||||
};
|
||||
|
||||
}, "xml");
|
||||
|
||||
CodeMirror.defineMIME("text/x-markdown", "markdown");
|
@ -1,656 +0,0 @@
|
||||
(function() {
|
||||
var mode = CodeMirror.getMode({tabSize: 4}, "markdown");
|
||||
function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); }
|
||||
|
||||
MT("plainText",
|
||||
"foo");
|
||||
|
||||
// Don't style single trailing space
|
||||
MT("trailingSpace1",
|
||||
"foo ");
|
||||
|
||||
// Two or more trailing spaces should be styled with line break character
|
||||
MT("trailingSpace2",
|
||||
"foo[trailing-space-a ][trailing-space-new-line ]");
|
||||
|
||||
MT("trailingSpace3",
|
||||
"foo[trailing-space-a ][trailing-space-b ][trailing-space-new-line ]");
|
||||
|
||||
MT("trailingSpace4",
|
||||
"foo[trailing-space-a ][trailing-space-b ][trailing-space-a ][trailing-space-new-line ]");
|
||||
|
||||
// Code blocks using 4 spaces (regardless of CodeMirror.tabSize value)
|
||||
MT("codeBlocksUsing4Spaces",
|
||||
" [comment foo]");
|
||||
|
||||
// Code blocks using 4 spaces with internal indentation
|
||||
MT("codeBlocksUsing4SpacesIndentation",
|
||||
" [comment bar]",
|
||||
" [comment hello]",
|
||||
" [comment world]",
|
||||
" [comment foo]",
|
||||
"bar");
|
||||
|
||||
// Code blocks using 4 spaces with internal indentation
|
||||
MT("codeBlocksUsing4SpacesIndentation",
|
||||
" foo",
|
||||
" [comment bar]",
|
||||
" [comment hello]",
|
||||
" [comment world]");
|
||||
|
||||
// Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value)
|
||||
MT("codeBlocksUsing1Tab",
|
||||
"\t[comment foo]");
|
||||
|
||||
// Inline code using backticks
|
||||
MT("inlineCodeUsingBackticks",
|
||||
"foo [comment `bar`]");
|
||||
|
||||
// Block code using single backtick (shouldn't work)
|
||||
MT("blockCodeSingleBacktick",
|
||||
"[comment `]",
|
||||
"foo",
|
||||
"[comment `]");
|
||||
|
||||
// Unclosed backticks
|
||||
// Instead of simply marking as CODE, it would be nice to have an
|
||||
// incomplete flag for CODE, that is styled slightly different.
|
||||
MT("unclosedBackticks",
|
||||
"foo [comment `bar]");
|
||||
|
||||
// Per documentation: "To include a literal backtick character within a
|
||||
// code span, you can use multiple backticks as the opening and closing
|
||||
// delimiters"
|
||||
MT("doubleBackticks",
|
||||
"[comment ``foo ` bar``]");
|
||||
|
||||
// Tests based on Dingus
|
||||
// http://daringfireball.net/projects/markdown/dingus
|
||||
//
|
||||
// Multiple backticks within an inline code block
|
||||
MT("consecutiveBackticks",
|
||||
"[comment `foo```bar`]");
|
||||
|
||||
// Multiple backticks within an inline code block with a second code block
|
||||
MT("consecutiveBackticks",
|
||||
"[comment `foo```bar`] hello [comment `world`]");
|
||||
|
||||
// Unclosed with several different groups of backticks
|
||||
MT("unclosedBackticks",
|
||||
"[comment ``foo ``` bar` hello]");
|
||||
|
||||
// Closed with several different groups of backticks
|
||||
MT("closedBackticks",
|
||||
"[comment ``foo ``` bar` hello``] world");
|
||||
|
||||
// atx headers
|
||||
// http://daringfireball.net/projects/markdown/syntax#header
|
||||
|
||||
MT("atxH1",
|
||||
"[header # foo]");
|
||||
|
||||
MT("atxH2",
|
||||
"[header ## foo]");
|
||||
|
||||
MT("atxH3",
|
||||
"[header ### foo]");
|
||||
|
||||
MT("atxH4",
|
||||
"[header #### foo]");
|
||||
|
||||
MT("atxH5",
|
||||
"[header ##### foo]");
|
||||
|
||||
MT("atxH6",
|
||||
"[header ###### foo]");
|
||||
|
||||
// H6 - 7x '#' should still be H6, per Dingus
|
||||
// http://daringfireball.net/projects/markdown/dingus
|
||||
MT("atxH6NotH7",
|
||||
"[header ####### foo]");
|
||||
|
||||
// Setext headers - H1, H2
|
||||
// Per documentation, "Any number of underlining =’s or -’s will work."
|
||||
// http://daringfireball.net/projects/markdown/syntax#header
|
||||
// Ideally, the text would be marked as `header` as well, but this is
|
||||
// not really feasible at the moment. So, instead, we're testing against
|
||||
// what works today, to avoid any regressions.
|
||||
//
|
||||
// Check if single underlining = works
|
||||
MT("setextH1",
|
||||
"foo",
|
||||
"[header =]");
|
||||
|
||||
// Check if 3+ ='s work
|
||||
MT("setextH1",
|
||||
"foo",
|
||||
"[header ===]");
|
||||
|
||||
// Check if single underlining - works
|
||||
MT("setextH2",
|
||||
"foo",
|
||||
"[header -]");
|
||||
|
||||
// Check if 3+ -'s work
|
||||
MT("setextH2",
|
||||
"foo",
|
||||
"[header ---]");
|
||||
|
||||
// Single-line blockquote with trailing space
|
||||
MT("blockquoteSpace",
|
||||
"[atom > foo]");
|
||||
|
||||
// Single-line blockquote
|
||||
MT("blockquoteNoSpace",
|
||||
"[atom >foo]");
|
||||
|
||||
// No blank line before blockquote
|
||||
MT("blockquoteNoBlankLine",
|
||||
"foo",
|
||||
"[atom > bar]");
|
||||
|
||||
// Nested blockquote
|
||||
MT("blockquoteSpace",
|
||||
"[atom > foo]",
|
||||
"[number > > foo]",
|
||||
"[atom > > > foo]");
|
||||
|
||||
// Single-line blockquote followed by normal paragraph
|
||||
MT("blockquoteThenParagraph",
|
||||
"[atom >foo]",
|
||||
"",
|
||||
"bar");
|
||||
|
||||
// Multi-line blockquote (lazy mode)
|
||||
MT("multiBlockquoteLazy",
|
||||
"[atom >foo]",
|
||||
"[atom bar]");
|
||||
|
||||
// Multi-line blockquote followed by normal paragraph (lazy mode)
|
||||
MT("multiBlockquoteLazyThenParagraph",
|
||||
"[atom >foo]",
|
||||
"[atom bar]",
|
||||
"",
|
||||
"hello");
|
||||
|
||||
// Multi-line blockquote (non-lazy mode)
|
||||
MT("multiBlockquote",
|
||||
"[atom >foo]",
|
||||
"[atom >bar]");
|
||||
|
||||
// Multi-line blockquote followed by normal paragraph (non-lazy mode)
|
||||
MT("multiBlockquoteThenParagraph",
|
||||
"[atom >foo]",
|
||||
"[atom >bar]",
|
||||
"",
|
||||
"hello");
|
||||
|
||||
// Check list types
|
||||
|
||||
MT("listAsterisk",
|
||||
"foo",
|
||||
"bar",
|
||||
"",
|
||||
"[variable-2 * foo]",
|
||||
"[variable-2 * bar]");
|
||||
|
||||
MT("listPlus",
|
||||
"foo",
|
||||
"bar",
|
||||
"",
|
||||
"[variable-2 + foo]",
|
||||
"[variable-2 + bar]");
|
||||
|
||||
MT("listDash",
|
||||
"foo",
|
||||
"bar",
|
||||
"",
|
||||
"[variable-2 - foo]",
|
||||
"[variable-2 - bar]");
|
||||
|
||||
MT("listNumber",
|
||||
"foo",
|
||||
"bar",
|
||||
"",
|
||||
"[variable-2 1. foo]",
|
||||
"[variable-2 2. bar]");
|
||||
|
||||
// Lists require a preceding blank line (per Dingus)
|
||||
MT("listBogus",
|
||||
"foo",
|
||||
"1. bar",
|
||||
"2. hello");
|
||||
|
||||
// Formatting in lists (*)
|
||||
MT("listAsteriskFormatting",
|
||||
"[variable-2 * ][variable-2&em *foo*][variable-2 bar]",
|
||||
"[variable-2 * ][variable-2&strong **foo**][variable-2 bar]",
|
||||
"[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
|
||||
"[variable-2 * ][variable-2&comment `foo`][variable-2 bar]");
|
||||
|
||||
// Formatting in lists (+)
|
||||
MT("listPlusFormatting",
|
||||
"[variable-2 + ][variable-2&em *foo*][variable-2 bar]",
|
||||
"[variable-2 + ][variable-2&strong **foo**][variable-2 bar]",
|
||||
"[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
|
||||
"[variable-2 + ][variable-2&comment `foo`][variable-2 bar]");
|
||||
|
||||
// Formatting in lists (-)
|
||||
MT("listDashFormatting",
|
||||
"[variable-2 - ][variable-2&em *foo*][variable-2 bar]",
|
||||
"[variable-2 - ][variable-2&strong **foo**][variable-2 bar]",
|
||||
"[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
|
||||
"[variable-2 - ][variable-2&comment `foo`][variable-2 bar]");
|
||||
|
||||
// Formatting in lists (1.)
|
||||
MT("listNumberFormatting",
|
||||
"[variable-2 1. ][variable-2&em *foo*][variable-2 bar]",
|
||||
"[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]",
|
||||
"[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]",
|
||||
"[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]");
|
||||
|
||||
// Paragraph lists
|
||||
MT("listParagraph",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]");
|
||||
|
||||
// Multi-paragraph lists
|
||||
//
|
||||
// 4 spaces
|
||||
MT("listMultiParagraph",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
" [variable-2 hello]");
|
||||
|
||||
// 4 spaces, extra blank lines (should still be list, per Dingus)
|
||||
MT("listMultiParagraphExtra",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
"",
|
||||
" [variable-2 hello]");
|
||||
|
||||
// 4 spaces, plus 1 space (should still be list, per Dingus)
|
||||
MT("listMultiParagraphExtraSpace",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
" [variable-2 hello]",
|
||||
"",
|
||||
" [variable-2 world]");
|
||||
|
||||
// 1 tab
|
||||
MT("listTab",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
"\t[variable-2 hello]");
|
||||
|
||||
// No indent
|
||||
MT("listNoIndent",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
"hello");
|
||||
|
||||
// Blockquote
|
||||
MT("blockquote",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
" [variable-2&atom > hello]");
|
||||
|
||||
// Code block
|
||||
MT("blockquoteCode",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
"[variable-2 * bar]",
|
||||
"",
|
||||
" [comment > hello]",
|
||||
"",
|
||||
" [variable-2 world]");
|
||||
|
||||
// Code block followed by text
|
||||
MT("blockquoteCodeText",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-2 bar]",
|
||||
"",
|
||||
" [comment hello]",
|
||||
"",
|
||||
" [variable-2 world]");
|
||||
|
||||
// Nested list
|
||||
|
||||
MT("listAsteriskNested",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-3 * bar]");
|
||||
|
||||
MT("listPlusNested",
|
||||
"[variable-2 + foo]",
|
||||
"",
|
||||
" [variable-3 + bar]");
|
||||
|
||||
MT("listDashNested",
|
||||
"[variable-2 - foo]",
|
||||
"",
|
||||
" [variable-3 - bar]");
|
||||
|
||||
MT("listNumberNested",
|
||||
"[variable-2 1. foo]",
|
||||
"",
|
||||
" [variable-3 2. bar]");
|
||||
|
||||
MT("listMixed",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-3 + bar]",
|
||||
"",
|
||||
" [keyword - hello]",
|
||||
"",
|
||||
" [variable-2 1. world]");
|
||||
|
||||
MT("listBlockquote",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-3 + bar]",
|
||||
"",
|
||||
" [atom&variable-3 > hello]");
|
||||
|
||||
MT("listCode",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-3 + bar]",
|
||||
"",
|
||||
" [comment hello]");
|
||||
|
||||
// Code with internal indentation
|
||||
MT("listCodeIndentation",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [comment bar]",
|
||||
" [comment hello]",
|
||||
" [comment world]",
|
||||
" [comment foo]",
|
||||
" [variable-2 bar]");
|
||||
|
||||
// List nesting edge cases
|
||||
MT("listNested",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-3 * bar]",
|
||||
"",
|
||||
" [variable-2 hello]"
|
||||
);
|
||||
MT("listNested",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [variable-3 * bar]",
|
||||
"",
|
||||
" [variable-3 * foo]"
|
||||
);
|
||||
|
||||
// Code followed by text
|
||||
MT("listCodeText",
|
||||
"[variable-2 * foo]",
|
||||
"",
|
||||
" [comment bar]",
|
||||
"",
|
||||
"hello");
|
||||
|
||||
// Following tests directly from official Markdown documentation
|
||||
// http://daringfireball.net/projects/markdown/syntax#hr
|
||||
|
||||
MT("hrSpace",
|
||||
"[hr * * *]");
|
||||
|
||||
MT("hr",
|
||||
"[hr ***]");
|
||||
|
||||
MT("hrLong",
|
||||
"[hr *****]");
|
||||
|
||||
MT("hrSpaceDash",
|
||||
"[hr - - -]");
|
||||
|
||||
MT("hrDashLong",
|
||||
"[hr ---------------------------------------]");
|
||||
|
||||
// Inline link with title
|
||||
MT("linkTitle",
|
||||
"[link [[foo]]][string (http://example.com/ \"bar\")] hello");
|
||||
|
||||
// Inline link without title
|
||||
MT("linkNoTitle",
|
||||
"[link [[foo]]][string (http://example.com/)] bar");
|
||||
|
||||
// Inline link with image
|
||||
MT("linkImage",
|
||||
"[link [[][tag ![[foo]]][string (http://example.com/)][link ]]][string (http://example.com/)] bar");
|
||||
|
||||
// Inline link with Em
|
||||
MT("linkEm",
|
||||
"[link [[][link&em *foo*][link ]]][string (http://example.com/)] bar");
|
||||
|
||||
// Inline link with Strong
|
||||
MT("linkStrong",
|
||||
"[link [[][link&strong **foo**][link ]]][string (http://example.com/)] bar");
|
||||
|
||||
// Inline link with EmStrong
|
||||
MT("linkEmStrong",
|
||||
"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string (http://example.com/)] bar");
|
||||
|
||||
// Image with title
|
||||
MT("imageTitle",
|
||||
"[tag ![[foo]]][string (http://example.com/ \"bar\")] hello");
|
||||
|
||||
// Image without title
|
||||
MT("imageNoTitle",
|
||||
"[tag ![[foo]]][string (http://example.com/)] bar");
|
||||
|
||||
// Image with asterisks
|
||||
MT("imageAsterisks",
|
||||
"[tag ![[*foo*]]][string (http://example.com/)] bar");
|
||||
|
||||
// Not a link. Should be normal text due to square brackets being used
|
||||
// regularly in text, especially in quoted material, and no space is allowed
|
||||
// between square brackets and parentheses (per Dingus).
|
||||
MT("notALink",
|
||||
"[[foo]] (bar)");
|
||||
|
||||
// Reference-style links
|
||||
MT("linkReference",
|
||||
"[link [[foo]]][string [[bar]]] hello");
|
||||
|
||||
// Reference-style links with Em
|
||||
MT("linkReferenceEm",
|
||||
"[link [[][link&em *foo*][link ]]][string [[bar]]] hello");
|
||||
|
||||
// Reference-style links with Strong
|
||||
MT("linkReferenceStrong",
|
||||
"[link [[][link&strong **foo**][link ]]][string [[bar]]] hello");
|
||||
|
||||
// Reference-style links with EmStrong
|
||||
MT("linkReferenceEmStrong",
|
||||
"[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string [[bar]]] hello");
|
||||
|
||||
// Reference-style links with optional space separator (per docuentation)
|
||||
// "You can optionally use a space to separate the sets of brackets"
|
||||
MT("linkReferenceSpace",
|
||||
"[link [[foo]]] [string [[bar]]] hello");
|
||||
|
||||
// Should only allow a single space ("...use *a* space...")
|
||||
MT("linkReferenceDoubleSpace",
|
||||
"[[foo]] [[bar]] hello");
|
||||
|
||||
// Reference-style links with implicit link name
|
||||
MT("linkImplicit",
|
||||
"[link [[foo]]][string [[]]] hello");
|
||||
|
||||
// @todo It would be nice if, at some point, the document was actually
|
||||
// checked to see if the referenced link exists
|
||||
|
||||
// Link label, for reference-style links (taken from documentation)
|
||||
|
||||
MT("labelNoTitle",
|
||||
"[link [[foo]]:] [string http://example.com/]");
|
||||
|
||||
MT("labelIndented",
|
||||
" [link [[foo]]:] [string http://example.com/]");
|
||||
|
||||
MT("labelSpaceTitle",
|
||||
"[link [[foo bar]]:] [string http://example.com/ \"hello\"]");
|
||||
|
||||
MT("labelDoubleTitle",
|
||||
"[link [[foo bar]]:] [string http://example.com/ \"hello\"] \"world\"");
|
||||
|
||||
MT("labelTitleDoubleQuotes",
|
||||
"[link [[foo]]:] [string http://example.com/ \"bar\"]");
|
||||
|
||||
MT("labelTitleSingleQuotes",
|
||||
"[link [[foo]]:] [string http://example.com/ 'bar']");
|
||||
|
||||
MT("labelTitleParenthese",
|
||||
"[link [[foo]]:] [string http://example.com/ (bar)]");
|
||||
|
||||
MT("labelTitleInvalid",
|
||||
"[link [[foo]]:] [string http://example.com/] bar");
|
||||
|
||||
MT("labelLinkAngleBrackets",
|
||||
"[link [[foo]]:] [string <http://example.com/> \"bar\"]");
|
||||
|
||||
MT("labelTitleNextDoubleQuotes",
|
||||
"[link [[foo]]:] [string http://example.com/]",
|
||||
"[string \"bar\"] hello");
|
||||
|
||||
MT("labelTitleNextSingleQuotes",
|
||||
"[link [[foo]]:] [string http://example.com/]",
|
||||
"[string 'bar'] hello");
|
||||
|
||||
MT("labelTitleNextParenthese",
|
||||
"[link [[foo]]:] [string http://example.com/]",
|
||||
"[string (bar)] hello");
|
||||
|
||||
MT("labelTitleNextMixed",
|
||||
"[link [[foo]]:] [string http://example.com/]",
|
||||
"(bar\" hello");
|
||||
|
||||
MT("linkWeb",
|
||||
"[link <http://example.com/>] foo");
|
||||
|
||||
MT("linkWebDouble",
|
||||
"[link <http://example.com/>] foo [link <http://example.com/>]");
|
||||
|
||||
MT("linkEmail",
|
||||
"[link <user@example.com>] foo");
|
||||
|
||||
MT("linkEmailDouble",
|
||||
"[link <user@example.com>] foo [link <user@example.com>]");
|
||||
|
||||
MT("emAsterisk",
|
||||
"[em *foo*] bar");
|
||||
|
||||
MT("emUnderscore",
|
||||
"[em _foo_] bar");
|
||||
|
||||
MT("emInWordAsterisk",
|
||||
"foo[em *bar*]hello");
|
||||
|
||||
MT("emInWordUnderscore",
|
||||
"foo[em _bar_]hello");
|
||||
|
||||
// Per documentation: "...surround an * or _ with spaces, it’ll be
|
||||
// treated as a literal asterisk or underscore."
|
||||
|
||||
MT("emEscapedBySpaceIn",
|
||||
"foo [em _bar _ hello_] world");
|
||||
|
||||
MT("emEscapedBySpaceOut",
|
||||
"foo _ bar[em _hello_]world");
|
||||
|
||||
// Unclosed emphasis characters
|
||||
// Instead of simply marking as EM / STRONG, it would be nice to have an
|
||||
// incomplete flag for EM and STRONG, that is styled slightly different.
|
||||
MT("emIncompleteAsterisk",
|
||||
"foo [em *bar]");
|
||||
|
||||
MT("emIncompleteUnderscore",
|
||||
"foo [em _bar]");
|
||||
|
||||
MT("strongAsterisk",
|
||||
"[strong **foo**] bar");
|
||||
|
||||
MT("strongUnderscore",
|
||||
"[strong __foo__] bar");
|
||||
|
||||
MT("emStrongAsterisk",
|
||||
"[em *foo][em&strong **bar*][strong hello**] world");
|
||||
|
||||
MT("emStrongUnderscore",
|
||||
"[em _foo][em&strong __bar_][strong hello__] world");
|
||||
|
||||
// "...same character must be used to open and close an emphasis span.""
|
||||
MT("emStrongMixed",
|
||||
"[em _foo][em&strong **bar*hello__ world]");
|
||||
|
||||
MT("emStrongMixed",
|
||||
"[em *foo][em&strong __bar_hello** world]");
|
||||
|
||||
// These characters should be escaped:
|
||||
// \ backslash
|
||||
// ` backtick
|
||||
// * asterisk
|
||||
// _ underscore
|
||||
// {} curly braces
|
||||
// [] square brackets
|
||||
// () parentheses
|
||||
// # hash mark
|
||||
// + plus sign
|
||||
// - minus sign (hyphen)
|
||||
// . dot
|
||||
// ! exclamation mark
|
||||
|
||||
MT("escapeBacktick",
|
||||
"foo \\`bar\\`");
|
||||
|
||||
MT("doubleEscapeBacktick",
|
||||
"foo \\\\[comment `bar\\\\`]");
|
||||
|
||||
MT("escapeAsterisk",
|
||||
"foo \\*bar\\*");
|
||||
|
||||
MT("doubleEscapeAsterisk",
|
||||
"foo \\\\[em *bar\\\\*]");
|
||||
|
||||
MT("escapeUnderscore",
|
||||
"foo \\_bar\\_");
|
||||
|
||||
MT("doubleEscapeUnderscore",
|
||||
"foo \\\\[em _bar\\\\_]");
|
||||
|
||||
MT("escapeHash",
|
||||
"\\# foo");
|
||||
|
||||
MT("doubleEscapeHash",
|
||||
"\\\\# foo");
|
||||
|
||||
|
||||
// Tests to make sure GFM-specific things aren't getting through
|
||||
|
||||
MT("taskList",
|
||||
"[variable-2 * [ ]] bar]");
|
||||
|
||||
MT("fencedCodeBlocks",
|
||||
"[comment ```]",
|
||||
"foo",
|
||||
"[comment ```]");
|
||||
})();
|
379
core/client/assets/vendor/countable.js
vendored
379
core/client/assets/vendor/countable.js
vendored
@ -1,379 +0,0 @@
|
||||
/**
|
||||
* Countable is a script to allow for live paragraph-, word- and character-
|
||||
* counting on an HTML element.
|
||||
*
|
||||
* @author Sacha Schmid (<https://github.com/RadLikeWhoa>)
|
||||
* @version 2.0.2
|
||||
* @license MIT
|
||||
* @see <http://radlikewhoa.github.io/Countable/>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note: For the purpose of this internal documentation, arguments of the type
|
||||
* {Nodes} are to be interpreted as either {NodeList} or {Element}.
|
||||
*/
|
||||
|
||||
;(function (global) {
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* `_liveElements` holds all elements that have the live-counting
|
||||
* functionality bound to them.
|
||||
*
|
||||
* `_event` holds the event to handle the live counting, based on the
|
||||
* browser's capabilities.
|
||||
*/
|
||||
|
||||
var _liveElements = [],
|
||||
_event = 'oninput' in document ? 'input' : 'keyup'
|
||||
|
||||
/**
|
||||
* `String.trim()` polyfill for non-supporting browsers. This is the
|
||||
* recommended polyfill on MDN.
|
||||
*
|
||||
* @see <http://goo.gl/uYveB>
|
||||
* @see <http://goo.gl/xjIxJ>
|
||||
*
|
||||
* @return {String} The original string with leading and trailing whitespace
|
||||
* removed.
|
||||
*/
|
||||
|
||||
if (!String.prototype.trim) {
|
||||
String.prototype.trim = function () {
|
||||
return this.replace(/^\s+|\s+$/g, '')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `ucs2decode` function from the punycode.js library.
|
||||
*
|
||||
* Creates an array containing the decimal code points of each Unicode
|
||||
* character in the string. While JavaScript uses UCS-2 internally, this
|
||||
* function will convert a pair of surrogate halves (each of which UCS-2
|
||||
* exposes as separate characters) into a single code point, matching
|
||||
* UTF-16.
|
||||
*
|
||||
* @see <http://goo.gl/8M09r>
|
||||
* @see <http://goo.gl/u4UUC>
|
||||
*
|
||||
* @param {String} string The Unicode input string (UCS-2).
|
||||
*
|
||||
* @return {Array} The new array of code points.
|
||||
*/
|
||||
|
||||
function _decode (string) {
|
||||
var output = [],
|
||||
counter = 0,
|
||||
length = string.length,
|
||||
value, extra
|
||||
|
||||
while (counter < length) {
|
||||
value = string.charCodeAt(counter++)
|
||||
|
||||
if ((value & 0xF800) == 0xD800 && counter < length) {
|
||||
|
||||
// High surrogate, and there is a next character.
|
||||
|
||||
extra = string.charCodeAt(counter++)
|
||||
|
||||
if ((extra & 0xFC00) == 0xDC00) {
|
||||
|
||||
// Low surrogate.
|
||||
|
||||
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000)
|
||||
} else {
|
||||
output.push(value, extra)
|
||||
}
|
||||
} else {
|
||||
output.push(value)
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
/**
|
||||
* `_validateArguments` validates the arguments given to each function call.
|
||||
* Errors are logged to the console as warnings, but Countable fails silently.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Nodes} elements The (collection of) element(s) to
|
||||
* validate.
|
||||
*
|
||||
* @param {Function} callback The callback function to validate.
|
||||
*
|
||||
* @return {Boolean} Returns whether all arguments are vaild.
|
||||
*/
|
||||
|
||||
function _validateArguments (elements, callback) {
|
||||
var elementsValid = elements && ((Object.prototype.toString.call(elements) === '[object NodeList]' && elements.length) || (elements.nodeType === 1)),
|
||||
callbackValid = callback && typeof callback === 'function'
|
||||
|
||||
if ('console' in window && 'warn' in console) {
|
||||
if (!elementsValid) console.warn('Countable: No valid elements were found')
|
||||
if (!callbackValid) console.warn('Countable: "' + callback + '" is not a valid callback function')
|
||||
}
|
||||
|
||||
return elementsValid && callbackValid
|
||||
}
|
||||
|
||||
/**
|
||||
* `_extendDefaults` is a function to extend a set of default options with the
|
||||
* ones given in the function call. Available options are described below.
|
||||
*
|
||||
* {Boolean} hardReturns Use two returns to seperate a paragraph instead
|
||||
* of one.
|
||||
* {Boolean} stripTags Strip HTML tags before counting the values.
|
||||
* {Boolean} ignoreReturns Ignore returns when calculating the `all`
|
||||
* property.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Object} options Countable allows the options described above.
|
||||
* They can be used in a function call to override
|
||||
* the default behaviour.
|
||||
*
|
||||
* @return {Object} The new options object.
|
||||
*/
|
||||
|
||||
function _extendDefaults (options) {
|
||||
var defaults = { hardReturns: false, stripTags: false, ignoreReturns: false }
|
||||
|
||||
for (var prop in options) {
|
||||
if (defaults.hasOwnProperty(prop)) defaults[prop] = options[prop]
|
||||
}
|
||||
|
||||
return defaults
|
||||
}
|
||||
|
||||
/**
|
||||
* `_count` trims an element's value, optionally strips HTML tags and counts
|
||||
* paragraphs, words, characters and characters plus spaces.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Element} element The element whose value is to be counted.
|
||||
*
|
||||
* @param {Object} options The options to use for the counting.
|
||||
*
|
||||
* @return {Object} The object containing the number of paragraphs,
|
||||
* words, characters and characters plus spaces.
|
||||
*/
|
||||
|
||||
function _count (element, options) {
|
||||
var original = 'value' in element ? element.value : element.innerText || element.textContent,
|
||||
trimmed
|
||||
|
||||
/**
|
||||
* The initial implementation to allow for HTML tags stripping was created
|
||||
* @craniumslows while the current one was created by @Rob--W.
|
||||
*
|
||||
* @see <http://goo.gl/Exmlr>
|
||||
* @see <http://goo.gl/gFQQh>
|
||||
*/
|
||||
|
||||
if (options.stripTags) original = original.replace(/<\/?[a-z][^>]*>/gi, '')
|
||||
|
||||
trimmed = original.trim()
|
||||
|
||||
/**
|
||||
* Most of the performance improvements are based on the works of @epmatsw.
|
||||
*
|
||||
* @see <http://goo.gl/SWOLB>
|
||||
*/
|
||||
|
||||
return {
|
||||
paragraphs: trimmed ? (trimmed.match(options.hardReturns ? /\n{2,}/g : /\n+/g) || []).length + 1 : 0,
|
||||
words: trimmed ? (trimmed.replace(/['";:,.?¿\-!¡]+/g, '').match(/\S+/g) || []).length : 0,
|
||||
characters: trimmed ? _decode(trimmed.replace(/\s/g, '')).length : 0,
|
||||
all: _decode(options.ignoreReturns ? original.replace(/[\n\r]/g, '') : original).length
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* `_loop` is a helper function to iterate over a collection, e.g. a NodeList
|
||||
* or an Array. The callback receives the current element as the single
|
||||
* parameter.
|
||||
*
|
||||
* @private
|
||||
*
|
||||
* @param {Array} which The collection to iterate over.
|
||||
*
|
||||
* @param {Function} callback The callback function to call on each
|
||||
* iteration.
|
||||
*/
|
||||
|
||||
function _loop (which, callback) {
|
||||
var len = which.length
|
||||
|
||||
if (typeof len !== 'undefined') {
|
||||
while (len--) {
|
||||
callback(which[len])
|
||||
}
|
||||
} else {
|
||||
callback(which)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the main object that will later be exposed to other scripts. It
|
||||
* holds all the public methods that can be used to enable the Countable
|
||||
* functionality.
|
||||
*/
|
||||
|
||||
var Countable = {
|
||||
|
||||
/**
|
||||
* The `live` method binds the counting handler to all given elements. The
|
||||
* event is either `oninput` or `onkeydown`, based on the capabilities of
|
||||
* the browser.
|
||||
*
|
||||
* @param {Nodes} elements All elements that should receive the
|
||||
* Countable functionality.
|
||||
*
|
||||
* @param {Function} callback The callback to fire whenever the
|
||||
* element's value changes. The callback is
|
||||
* called with the relevant element bound to
|
||||
* `this` and the counted values as the
|
||||
* single parameter.
|
||||
*
|
||||
* @param {Object} [options] An object to modify Countable's
|
||||
* behaviour. Refer to `_extendDefaults` for
|
||||
* a list of available options.
|
||||
*
|
||||
* @return {Object} Returns the Countable object to allow for chaining.
|
||||
*/
|
||||
|
||||
live: function (elements, callback, options) {
|
||||
var ops = _extendDefaults(options),
|
||||
bind = function (element) {
|
||||
var handler = function () {
|
||||
callback.call(element, _count(element, ops))
|
||||
}
|
||||
|
||||
_liveElements.push({ element: element, handler: handler })
|
||||
|
||||
handler()
|
||||
|
||||
if (element.addEventListener) {
|
||||
element.addEventListener(_event, handler, false)
|
||||
} else if (element.attachEvent) {
|
||||
element.attachEvent('on' + _event, handler)
|
||||
}
|
||||
}
|
||||
|
||||
if (!_validateArguments(elements, callback)) return
|
||||
|
||||
if (elements.length) {
|
||||
_loop(elements, bind)
|
||||
} else {
|
||||
bind(elements)
|
||||
}
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
/**
|
||||
* The `die` method removes the Countable functionality from all given
|
||||
* elements.
|
||||
*
|
||||
* @param {Nodes} elements All elements whose Countable functionality
|
||||
* should be unbound.
|
||||
*
|
||||
* @return {Object} Returns the Countable object to allow for chaining.
|
||||
*/
|
||||
|
||||
die: function (elements) {
|
||||
if (!_validateArguments(elements, function () {})) return
|
||||
|
||||
_loop(elements, function (element) {
|
||||
var liveElement
|
||||
|
||||
_loop(_liveElements, function (live) {
|
||||
if (live.element === element) liveElement = live
|
||||
})
|
||||
|
||||
if (!liveElement) return
|
||||
|
||||
if (element.removeEventListener) {
|
||||
element.removeEventListener(_event, liveElement.handler, false)
|
||||
} else if (element.detachEvent) {
|
||||
element.detachEvent('on' + _event, liveElement.handler)
|
||||
}
|
||||
|
||||
_liveElements.splice(_liveElements.indexOf(liveElement), 1)
|
||||
})
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
/**
|
||||
* The `once` method works mostly like the `live` method, but no events are
|
||||
* bound, the functionality is only executed once.
|
||||
*
|
||||
* @param {Nodes} elements All elements that should receive the
|
||||
* Countable functionality.
|
||||
*
|
||||
* @param {Function} callback The callback to fire whenever the
|
||||
* element's value changes. The callback is
|
||||
* called with the relevant element bound to
|
||||
* `this` and the counted values as the
|
||||
* single parameter.
|
||||
*
|
||||
* @param {Object} [options] An object to modify Countable's
|
||||
* behaviour. Refer to `_extendDefaults`
|
||||
* for a list of available options.
|
||||
*
|
||||
* @return {Object} Returns the Countable object to allow for chaining.
|
||||
*/
|
||||
|
||||
once: function (elements, callback, options) {
|
||||
if (!_validateArguments(elements, callback)) return
|
||||
|
||||
_loop(elements, function (element) {
|
||||
callback.call(element, _count(element, _extendDefaults(options)))
|
||||
})
|
||||
|
||||
return this
|
||||
},
|
||||
|
||||
/**
|
||||
* The `enabled` method checks if the live-counting functionality is bound
|
||||
* to an element.
|
||||
*
|
||||
* @param {Element} element A single Element.
|
||||
*
|
||||
* @return {Boolean} A boolean value representing whether Countable
|
||||
* functionality is bound to the given element.
|
||||
*/
|
||||
|
||||
enabled: function (element) {
|
||||
var isEnabled = false
|
||||
|
||||
if (element && element.nodeType === 1) {
|
||||
_loop(_liveElements, function (live) {
|
||||
if (live.element === element) isEnabled = true
|
||||
})
|
||||
}
|
||||
|
||||
return isEnabled
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose Countable depending on the module system used across the
|
||||
* application. (Node / CommonJS, AMD, global)
|
||||
*/
|
||||
|
||||
if (typeof exports === 'object') {
|
||||
module.exports = Countable
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define(function () { return Countable })
|
||||
} else {
|
||||
global.Countable = Countable
|
||||
}
|
||||
}(this))
|
@ -1,11 +0,0 @@
|
||||
/*!
|
||||
* iCheck v0.8.5 jQuery plugin, http://git.io/uhUPMA
|
||||
*/
|
||||
(function(f,m,z,u,k,r,l,n,D,t,v,s){function A(a,c,j){var d=a[0],b=/ble/.test(j)?r:k;active="update"==j?{checked:d[k],disabled:d[r]}:d[b];if(/^ch|di/.test(j)&&!active)w(a,b);else if(/^un|en/.test(j)&&active)x(a,b);else if("update"==j)for(var b in active)active[b]?w(a,b,!0):x(a,b,!0);else if(!c||"toggle"==j)c||a.trigger("ifClicked"),active?d[l]!==u&&x(a,b):w(a,b)}function w(a,c,j){var d=a[0],b=a.parent(),E=c==r?"enabled":"un"+k,n=e(a,E+g(d[l])),h=e(a,c+g(d[l]));if(!0!==d[c]&&!j&&(d[c]=!0,a.trigger("ifChanged").trigger("if"+
|
||||
g(c)),c==k&&d[l]==u&&d.name)){j=a.closest("form");var p='input[name="'+d.name+'"]',p=j.length?j.find(p):f(p);p.each(function(){this!==d&&f(this).data(m)&&x(f(this),c)})}d[r]&&e(a,s,!0)&&b.find("."+m+"-helper").css(s,"default");b[t](h||e(a,c));b[v](n||e(a,E)||"")}function x(a,c,j){var d=a[0],b=a.parent(),f=c==r?"enabled":"un"+k,n=e(a,f+g(d[l])),h=e(a,c+g(d[l]));!1!==d[c]&&!j&&(d[c]=!1,a.trigger("ifChanged").trigger("if"+g(f)));!d[r]&&e(a,s,!0)&&b.find("."+m+"-helper").css(s,"pointer");b[v](h||e(a,
|
||||
c)||"");b[t](n||e(a,f))}function F(a,c){a.data(m)&&(a.parent().html(a.attr("style",a.data(m).s||"").trigger(c||"")),a.off(".i").unwrap(),f('label[for="'+a[0].id+'"]').add(a.closest("label")).off(".i"))}function e(a,c,f){if(a.data(m))return a.data(m).o[c+(f?"":"Class")]}function g(a){return a.charAt(0).toUpperCase()+a.slice(1)}f.fn[m]=function(a,c){var j=navigator.userAgent,d=/ipad|iphone|ipod/i.test(j),b=":"+z+", :"+u,e=f(),g=function(a){a.each(function(){var a=f(this);e=a.is(b)?e.add(a):e.add(a.find(b))})};
|
||||
if(/^(check|uncheck|toggle|disable|enable|update|destroy)$/.test(a))return g(this),e.each(function(){var d=f(this);"destroy"==a?F(d,"ifDestroyed"):A(d,!0,a);f.isFunction(c)&&c()});if("object"==typeof a||!a){var h=f.extend({checkedClass:k,disabledClass:r,labelHover:!0},a),p=h.handle,s=h.hoverClass||"hover",I=h.focusClass||"focus",G=h.activeClass||"active",H=!!h.labelHover,C=h.labelHoverClass||"hover",y=(""+h.increaseArea).replace("%","")|0;if(p==z||p==u)b=":"+p;-50>y&&(y=-50);g(this);return e.each(function(){var a=
|
||||
f(this);F(a);var c=this,b=c.id,e=-y+"%",g=100+2*y+"%",g={position:"absolute",top:e,left:e,display:"block",width:g,height:g,margin:0,padding:0,background:"#fff",border:0,opacity:0},e=d||/android|blackberry|windows phone|opera mini/i.test(j)?{position:"absolute",visibility:"hidden"}:y?g:{position:"absolute",opacity:0},p=c[l]==z?h.checkboxClass||"i"+z:h.radioClass||"i"+u,B=f('label[for="'+b+'"]').add(a.closest("label")),q=a.wrap('<div class="'+p+'"/>').trigger("ifCreated").parent().append(h.insert),
|
||||
g=f('<ins class="'+m+'-helper"/>').css(g).appendTo(q);a.data(m,{o:h,s:a.attr("style")}).css(e);h.inheritClass&&q[t](c.className);h.inheritID&&b&&q.attr("id",m+"-"+b);"static"==q.css("position")&&q.css("position","relative");A(a,!0,"update");if(B.length)B.on(n+".i mouseenter.i mouseleave.i "+D,function(b){var e=b[l],g=f(this);if(!c[r])if(e==n?A(a,!1,!0):H&&(/ve|nd/.test(e)?(q[v](s),g[v](C)):(q[t](s),g[t](C))),d)b.stopPropagation();else return!1});a.on(n+".i focus.i blur.i keyup.i keydown.i keypress.i",
|
||||
function(b){var d=b[l];b=b.keyCode;if(d==n)return!1;if("keydown"==d&&32==b)return c[l]==u&&c[k]||(c[k]?x(a,k):w(a,k)),!1;if("keyup"==d&&c[l]==u)!c[k]&&w(a,k);else if(/us|ur/.test(d))q["blur"==d?v:t](I)});g.on(n+" mousedown mouseup mouseover mouseout "+D,function(b){var e=b[l],f=/wn|up/.test(e)?G:s;if(!c[r]){if(e==n)A(a,!1,!0);else{if(/wn|er|in/.test(e))q[t](f);else q[v](f+" "+G);if(B.length&&H&&f==s)B[/ut|nd/.test(e)?v:t](C)}if(d)b.stopPropagation();else return!1}})})}return this}})(jQuery,"iCheck",
|
||||
"checkbox","radio","checked","disabled","type","click","touchbegin.i touchend.i","addClass","removeClass","cursor");
|
File diff suppressed because one or more lines are too long
275
core/client/assets/vendor/nprogress.js
vendored
275
core/client/assets/vendor/nprogress.js
vendored
@ -1,275 +0,0 @@
|
||||
/*! NProgress (c) 2013, Rico Sta. Cruz
|
||||
* http://ricostacruz.com/nprogress */
|
||||
|
||||
;(function(factory) {
|
||||
|
||||
if (typeof module === 'function') {
|
||||
module.exports = factory(this.jQuery || require('jquery'));
|
||||
} else {
|
||||
this.NProgress = factory(this.jQuery);
|
||||
}
|
||||
|
||||
})(function($) {
|
||||
var NProgress = {};
|
||||
|
||||
NProgress.version = '0.1.2';
|
||||
|
||||
var Settings = NProgress.settings = {
|
||||
minimum: 0.08,
|
||||
easing: 'ease',
|
||||
positionUsing: '',
|
||||
speed: 200,
|
||||
trickle: true,
|
||||
trickleRate: 0.02,
|
||||
trickleSpeed: 800,
|
||||
showSpinner: true,
|
||||
template: '<div class="bar" role="bar"><div class="peg"></div></div><div class="spinner" role="spinner"><div class="spinner-icon"></div></div>'
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates configuration.
|
||||
*
|
||||
* NProgress.configure({
|
||||
* minimum: 0.1
|
||||
* });
|
||||
*/
|
||||
NProgress.configure = function(options) {
|
||||
$.extend(Settings, options);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Last number.
|
||||
*/
|
||||
|
||||
NProgress.status = null;
|
||||
|
||||
/**
|
||||
* Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.
|
||||
*
|
||||
* NProgress.set(0.4);
|
||||
* NProgress.set(1.0);
|
||||
*/
|
||||
|
||||
NProgress.set = function(n) {
|
||||
var started = NProgress.isStarted();
|
||||
|
||||
n = clamp(n, Settings.minimum, 1);
|
||||
NProgress.status = (n === 1 ? null : n);
|
||||
|
||||
var $progress = NProgress.render(!started),
|
||||
$bar = $progress.find('[role="bar"]'),
|
||||
speed = Settings.speed,
|
||||
ease = Settings.easing;
|
||||
|
||||
$progress[0].offsetWidth; /* Repaint */
|
||||
|
||||
$progress.queue(function(next) {
|
||||
// Set positionUsing if it hasn't already been set
|
||||
if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();
|
||||
|
||||
// Add transition
|
||||
$bar.css(barPositionCSS(n, speed, ease));
|
||||
|
||||
if (n === 1) {
|
||||
// Fade out
|
||||
$progress.css({ transition: 'none', opacity: 1 });
|
||||
$progress[0].offsetWidth; /* Repaint */
|
||||
|
||||
setTimeout(function() {
|
||||
$progress.css({ transition: 'all '+speed+'ms linear', opacity: 0 });
|
||||
setTimeout(function() {
|
||||
NProgress.remove();
|
||||
next();
|
||||
}, speed);
|
||||
}, speed);
|
||||
} else {
|
||||
setTimeout(next, speed);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
NProgress.isStarted = function() {
|
||||
return typeof NProgress.status === 'number';
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the progress bar.
|
||||
* This is the same as setting the status to 0%, except that it doesn't go backwards.
|
||||
*
|
||||
* NProgress.start();
|
||||
*
|
||||
*/
|
||||
NProgress.start = function() {
|
||||
if (!NProgress.status) NProgress.set(0);
|
||||
|
||||
var work = function() {
|
||||
setTimeout(function() {
|
||||
if (!NProgress.status) return;
|
||||
NProgress.trickle();
|
||||
work();
|
||||
}, Settings.trickleSpeed);
|
||||
};
|
||||
|
||||
if (Settings.trickle) work();
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the progress bar.
|
||||
* This is the *sort of* the same as setting the status to 100%, with the
|
||||
* difference being `done()` makes some placebo effect of some realistic motion.
|
||||
*
|
||||
* NProgress.done();
|
||||
*
|
||||
* If `true` is passed, it will show the progress bar even if its hidden.
|
||||
*
|
||||
* NProgress.done(true);
|
||||
*/
|
||||
|
||||
NProgress.done = function(force) {
|
||||
if (!force && !NProgress.status) return this;
|
||||
|
||||
return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Increments by a random amount.
|
||||
*/
|
||||
|
||||
NProgress.inc = function(amount) {
|
||||
var n = NProgress.status;
|
||||
|
||||
if (!n) {
|
||||
return NProgress.start();
|
||||
} else {
|
||||
if (typeof amount !== 'number') {
|
||||
amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);
|
||||
}
|
||||
|
||||
n = clamp(n + amount, 0, 0.994);
|
||||
return NProgress.set(n);
|
||||
}
|
||||
};
|
||||
|
||||
NProgress.trickle = function() {
|
||||
return NProgress.inc(Math.random() * Settings.trickleRate);
|
||||
};
|
||||
|
||||
/**
|
||||
* (Internal) renders the progress bar markup based on the `template`
|
||||
* setting.
|
||||
*/
|
||||
|
||||
NProgress.render = function(fromStart) {
|
||||
if (NProgress.isRendered()) return $("#nprogress");
|
||||
$('html').addClass('nprogress-busy');
|
||||
|
||||
var $el = $("<div id='nprogress'>")
|
||||
.html(Settings.template);
|
||||
|
||||
var perc = fromStart ? '-100' : toBarPerc(NProgress.status || 0);
|
||||
|
||||
$el.find('[role="bar"]').css({
|
||||
transition: 'all 0 linear',
|
||||
transform: 'translate3d('+perc+'%,0,0)'
|
||||
});
|
||||
|
||||
if (!Settings.showSpinner)
|
||||
$el.find('[role="spinner"]').remove();
|
||||
|
||||
$el.appendTo(document.body);
|
||||
|
||||
return $el;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the element. Opposite of render().
|
||||
*/
|
||||
|
||||
NProgress.remove = function() {
|
||||
$('html').removeClass('nprogress-busy');
|
||||
$('#nprogress').remove();
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the progress bar is rendered.
|
||||
*/
|
||||
|
||||
NProgress.isRendered = function() {
|
||||
return ($("#nprogress").length > 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine which positioning CSS rule to use.
|
||||
*/
|
||||
|
||||
NProgress.getPositioningCSS = function() {
|
||||
// Sniff on document.body.style
|
||||
var bodyStyle = document.body.style;
|
||||
|
||||
// Sniff prefixes
|
||||
var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :
|
||||
('MozTransform' in bodyStyle) ? 'Moz' :
|
||||
('msTransform' in bodyStyle) ? 'ms' :
|
||||
('OTransform' in bodyStyle) ? 'O' : '';
|
||||
|
||||
if (vendorPrefix + 'Perspective' in bodyStyle) {
|
||||
// Modern browsers with 3D support, e.g. Webkit, IE10
|
||||
return 'translate3d';
|
||||
} else if (vendorPrefix + 'Transform' in bodyStyle) {
|
||||
// Browsers without 3D support, e.g. IE9
|
||||
return 'translate';
|
||||
} else {
|
||||
// Browsers without translate() support, e.g. IE7-8
|
||||
return 'margin';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
function clamp(n, min, max) {
|
||||
if (n < min) return min;
|
||||
if (n > max) return max;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* (Internal) converts a percentage (`0..1`) to a bar translateX
|
||||
* percentage (`-100%..0%`).
|
||||
*/
|
||||
|
||||
function toBarPerc(n) {
|
||||
return (-1 + n) * 100;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (Internal) returns the correct CSS for changing the bar's
|
||||
* position given an n percentage, and speed and ease from Settings
|
||||
*/
|
||||
|
||||
function barPositionCSS(n, speed, ease) {
|
||||
var barCSS;
|
||||
|
||||
if (Settings.positionUsing === 'translate3d') {
|
||||
barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };
|
||||
} else if (Settings.positionUsing === 'translate') {
|
||||
barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };
|
||||
} else {
|
||||
barCSS = { 'margin-left': toBarPerc(n)+'%' };
|
||||
}
|
||||
|
||||
barCSS.transition = 'all '+speed+'ms '+ease;
|
||||
|
||||
return barCSS;
|
||||
}
|
||||
|
||||
return NProgress;
|
||||
});
|
||||
|
14
core/client/assets/vendor/packery.pkgd.min.js
vendored
14
core/client/assets/vendor/packery.pkgd.min.js
vendored
File diff suppressed because one or more lines are too long
62
core/client/assets/vendor/showdown/showdown.js
vendored
62
core/client/assets/vendor/showdown/showdown.js
vendored
File diff suppressed because one or more lines are too long
@ -444,7 +444,7 @@ coreHelpers.ghost_foot = function (options) {
|
||||
var foot = [];
|
||||
|
||||
foot.push(scriptTemplate({
|
||||
source: config().paths.subdir + '/shared/vendor/jquery/jquery.js',
|
||||
source: config().paths.subdir + '/public/jquery.js',
|
||||
version: coreHelpers.assetHash
|
||||
}));
|
||||
|
||||
|
@ -224,6 +224,7 @@ module.exports = function (server, dbHash) {
|
||||
expressServer.use(subdir + '/shared', express['static'](path.join(corePath, '/shared'), {maxAge: ONE_HOUR_MS}));
|
||||
expressServer.use(subdir + '/content/images', storage.get_storage().serve());
|
||||
expressServer.use(subdir + '/ghost/scripts', express['static'](path.join(corePath, '/built/scripts'), {maxAge: ONE_YEAR_MS}));
|
||||
expressServer.use(subdir + '/public', express['static'](path.join(corePath, '/built/public'), {maxAge: ONE_YEAR_MS}));
|
||||
|
||||
// First determine whether we're serving admin or theme content
|
||||
expressServer.use(manageAdminAndTheme);
|
||||
|
@ -3,8 +3,8 @@ var _ = require('lodash'),
|
||||
when = require('when'),
|
||||
errors = require('../errorHandling'),
|
||||
Showdown = require('showdown'),
|
||||
github = require('../../shared/vendor/showdown/extensions/github'),
|
||||
typography = require('../../shared/vendor/showdown/extensions/typography'),
|
||||
github = require('../../shared/lib/showdown/extensions/github'),
|
||||
typography = require('../../shared/lib/showdown/extensions/typography'),
|
||||
converter = new Showdown.converter({extensions: [typography, github]}),
|
||||
User = require('./user').User,
|
||||
Tag = require('./tag').Tag,
|
||||
|
1571
core/shared/vendor/backbone/backbone.js
vendored
1571
core/shared/vendor/backbone/backbone.js
vendored
File diff suppressed because it is too large
Load Diff
362
core/shared/vendor/handlebars/handlebars-runtime.js
vendored
362
core/shared/vendor/handlebars/handlebars-runtime.js
vendored
@ -1,362 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 2011 by Yehuda Katz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// lib/handlebars/browser-prefix.js
|
||||
var Handlebars = {};
|
||||
|
||||
(function(Handlebars, undefined) {
|
||||
;
|
||||
// lib/handlebars/base.js
|
||||
|
||||
Handlebars.VERSION = "1.0.0";
|
||||
Handlebars.COMPILER_REVISION = 4;
|
||||
|
||||
Handlebars.REVISION_CHANGES = {
|
||||
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
|
||||
2: '== 1.0.0-rc.3',
|
||||
3: '== 1.0.0-rc.4',
|
||||
4: '>= 1.0.0'
|
||||
};
|
||||
|
||||
Handlebars.helpers = {};
|
||||
Handlebars.partials = {};
|
||||
|
||||
var toString = Object.prototype.toString,
|
||||
functionType = '[object Function]',
|
||||
objectType = '[object Object]';
|
||||
|
||||
Handlebars.registerHelper = function(name, fn, inverse) {
|
||||
if (toString.call(name) === objectType) {
|
||||
if (inverse || fn) { throw new Handlebars.Exception('Arg not supported with multiple helpers'); }
|
||||
Handlebars.Utils.extend(this.helpers, name);
|
||||
} else {
|
||||
if (inverse) { fn.not = inverse; }
|
||||
this.helpers[name] = fn;
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.registerPartial = function(name, str) {
|
||||
if (toString.call(name) === objectType) {
|
||||
Handlebars.Utils.extend(this.partials, name);
|
||||
} else {
|
||||
this.partials[name] = str;
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.registerHelper('helperMissing', function(arg) {
|
||||
if(arguments.length === 2) {
|
||||
return undefined;
|
||||
} else {
|
||||
throw new Error("Missing helper: '" + arg + "'");
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('blockHelperMissing', function(context, options) {
|
||||
var inverse = options.inverse || function() {}, fn = options.fn;
|
||||
|
||||
var type = toString.call(context);
|
||||
|
||||
if(type === functionType) { context = context.call(this); }
|
||||
|
||||
if(context === true) {
|
||||
return fn(this);
|
||||
} else if(context === false || context == null) {
|
||||
return inverse(this);
|
||||
} else if(type === "[object Array]") {
|
||||
if(context.length > 0) {
|
||||
return Handlebars.helpers.each(context, options);
|
||||
} else {
|
||||
return inverse(this);
|
||||
}
|
||||
} else {
|
||||
return fn(context);
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.K = function() {};
|
||||
|
||||
Handlebars.createFrame = Object.create || function(object) {
|
||||
Handlebars.K.prototype = object;
|
||||
var obj = new Handlebars.K();
|
||||
Handlebars.K.prototype = null;
|
||||
return obj;
|
||||
};
|
||||
|
||||
Handlebars.logger = {
|
||||
DEBUG: 0, INFO: 1, WARN: 2, ERROR: 3, level: 3,
|
||||
|
||||
methodMap: {0: 'debug', 1: 'info', 2: 'warn', 3: 'error'},
|
||||
|
||||
// can be overridden in the host environment
|
||||
log: function(level, obj) {
|
||||
if (Handlebars.logger.level <= level) {
|
||||
var method = Handlebars.logger.methodMap[level];
|
||||
if (typeof console !== 'undefined' && console[method]) {
|
||||
console[method].call(console, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.log = function(level, obj) { Handlebars.logger.log(level, obj); };
|
||||
|
||||
Handlebars.registerHelper('each', function(context, options) {
|
||||
var fn = options.fn, inverse = options.inverse;
|
||||
var i = 0, ret = "", data;
|
||||
|
||||
var type = toString.call(context);
|
||||
if(type === functionType) { context = context.call(this); }
|
||||
|
||||
if (options.data) {
|
||||
data = Handlebars.createFrame(options.data);
|
||||
}
|
||||
|
||||
if(context && typeof context === 'object') {
|
||||
if(context instanceof Array){
|
||||
for(var j = context.length; i<j; i++) {
|
||||
if (data) { data.index = i; }
|
||||
ret = ret + fn(context[i], { data: data });
|
||||
}
|
||||
} else {
|
||||
for(var key in context) {
|
||||
if(context.hasOwnProperty(key)) {
|
||||
if(data) { data.key = key; }
|
||||
ret = ret + fn(context[key], {data: data});
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(i === 0){
|
||||
ret = inverse(this);
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('if', function(conditional, options) {
|
||||
var type = toString.call(conditional);
|
||||
if(type === functionType) { conditional = conditional.call(this); }
|
||||
|
||||
if(!conditional || Handlebars.Utils.isEmpty(conditional)) {
|
||||
return options.inverse(this);
|
||||
} else {
|
||||
return options.fn(this);
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('unless', function(conditional, options) {
|
||||
return Handlebars.helpers['if'].call(this, conditional, {fn: options.inverse, inverse: options.fn});
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('with', function(context, options) {
|
||||
var type = toString.call(context);
|
||||
if(type === functionType) { context = context.call(this); }
|
||||
|
||||
if (!Handlebars.Utils.isEmpty(context)) return options.fn(context);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('log', function(context, options) {
|
||||
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
|
||||
Handlebars.log(level, context);
|
||||
});
|
||||
;
|
||||
// lib/handlebars/utils.js
|
||||
|
||||
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
|
||||
|
||||
Handlebars.Exception = function(message) {
|
||||
var tmp = Error.prototype.constructor.apply(this, arguments);
|
||||
|
||||
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
|
||||
for (var idx = 0; idx < errorProps.length; idx++) {
|
||||
this[errorProps[idx]] = tmp[errorProps[idx]];
|
||||
}
|
||||
};
|
||||
Handlebars.Exception.prototype = new Error();
|
||||
|
||||
// Build out our basic SafeString type
|
||||
Handlebars.SafeString = function(string) {
|
||||
this.string = string;
|
||||
};
|
||||
Handlebars.SafeString.prototype.toString = function() {
|
||||
return this.string.toString();
|
||||
};
|
||||
|
||||
var escape = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
"`": "`"
|
||||
};
|
||||
|
||||
var badChars = /[&<>"'`]/g;
|
||||
var possible = /[&<>"'`]/;
|
||||
|
||||
var escapeChar = function(chr) {
|
||||
return escape[chr] || "&";
|
||||
};
|
||||
|
||||
Handlebars.Utils = {
|
||||
extend: function(obj, value) {
|
||||
for(var key in value) {
|
||||
if(value.hasOwnProperty(key)) {
|
||||
obj[key] = value[key];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
escapeExpression: function(string) {
|
||||
// don't escape SafeStrings, since they're already safe
|
||||
if (string instanceof Handlebars.SafeString) {
|
||||
return string.toString();
|
||||
} else if (string == null || string === false) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Force a string conversion as this will be done by the append regardless and
|
||||
// the regex test will do this transparently behind the scenes, causing issues if
|
||||
// an object's to string has escaped characters in it.
|
||||
string = string.toString();
|
||||
|
||||
if(!possible.test(string)) { return string; }
|
||||
return string.replace(badChars, escapeChar);
|
||||
},
|
||||
|
||||
isEmpty: function(value) {
|
||||
if (!value && value !== 0) {
|
||||
return true;
|
||||
} else if(toString.call(value) === "[object Array]" && value.length === 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
;
|
||||
// lib/handlebars/runtime.js
|
||||
|
||||
Handlebars.VM = {
|
||||
template: function(templateSpec) {
|
||||
// Just add water
|
||||
var container = {
|
||||
escapeExpression: Handlebars.Utils.escapeExpression,
|
||||
invokePartial: Handlebars.VM.invokePartial,
|
||||
programs: [],
|
||||
program: function(i, fn, data) {
|
||||
var programWrapper = this.programs[i];
|
||||
if(data) {
|
||||
programWrapper = Handlebars.VM.program(i, fn, data);
|
||||
} else if (!programWrapper) {
|
||||
programWrapper = this.programs[i] = Handlebars.VM.program(i, fn);
|
||||
}
|
||||
return programWrapper;
|
||||
},
|
||||
merge: function(param, common) {
|
||||
var ret = param || common;
|
||||
|
||||
if (param && common) {
|
||||
ret = {};
|
||||
Handlebars.Utils.extend(ret, common);
|
||||
Handlebars.Utils.extend(ret, param);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
programWithDepth: Handlebars.VM.programWithDepth,
|
||||
noop: Handlebars.VM.noop,
|
||||
compilerInfo: null
|
||||
};
|
||||
|
||||
return function(context, options) {
|
||||
options = options || {};
|
||||
var result = templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data);
|
||||
|
||||
var compilerInfo = container.compilerInfo || [],
|
||||
compilerRevision = compilerInfo[0] || 1,
|
||||
currentRevision = Handlebars.COMPILER_REVISION;
|
||||
|
||||
if (compilerRevision !== currentRevision) {
|
||||
if (compilerRevision < currentRevision) {
|
||||
var runtimeVersions = Handlebars.REVISION_CHANGES[currentRevision],
|
||||
compilerVersions = Handlebars.REVISION_CHANGES[compilerRevision];
|
||||
throw "Template was precompiled with an older version of Handlebars than the current runtime. "+
|
||||
"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";
|
||||
} else {
|
||||
// Use the embedded version info since the runtime doesn't know about this revision yet
|
||||
throw "Template was precompiled with a newer version of Handlebars than the current runtime. "+
|
||||
"Please update your runtime to a newer version ("+compilerInfo[1]+").";
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
},
|
||||
|
||||
programWithDepth: function(i, fn, data /*, $depth */) {
|
||||
var args = Array.prototype.slice.call(arguments, 3);
|
||||
|
||||
var program = function(context, options) {
|
||||
options = options || {};
|
||||
|
||||
return fn.apply(this, [context, options.data || data].concat(args));
|
||||
};
|
||||
program.program = i;
|
||||
program.depth = args.length;
|
||||
return program;
|
||||
},
|
||||
program: function(i, fn, data) {
|
||||
var program = function(context, options) {
|
||||
options = options || {};
|
||||
|
||||
return fn(context, options.data || data);
|
||||
};
|
||||
program.program = i;
|
||||
program.depth = 0;
|
||||
return program;
|
||||
},
|
||||
noop: function() { return ""; },
|
||||
invokePartial: function(partial, name, context, helpers, partials, data) {
|
||||
var options = { helpers: helpers, partials: partials, data: data };
|
||||
|
||||
if(partial === undefined) {
|
||||
throw new Handlebars.Exception("The partial " + name + " could not be found");
|
||||
} else if(partial instanceof Function) {
|
||||
return partial(context, options);
|
||||
} else if (!Handlebars.compile) {
|
||||
throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode");
|
||||
} else {
|
||||
partials[name] = Handlebars.compile(partial, {data: data !== undefined});
|
||||
return partials[name](context, options);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Handlebars.template = Handlebars.VM.template;
|
||||
;
|
||||
// lib/handlebars/browser-suffix.js
|
||||
})(Handlebars);
|
||||
;
|
File diff suppressed because one or more lines are too long
1301
core/shared/vendor/jquery/jquery.fileupload.js
vendored
1301
core/shared/vendor/jquery/jquery.fileupload.js
vendored
File diff suppressed because it is too large
Load Diff
185
core/shared/vendor/jquery/jquery.iframe-transport.js
vendored
185
core/shared/vendor/jquery/jquery.iframe-transport.js
vendored
@ -1,185 +0,0 @@
|
||||
/*
|
||||
* jQuery Iframe Transport Plugin 1.6.1
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2011, Sebastian Tschan
|
||||
* https://blueimp.net
|
||||
*
|
||||
* Licensed under the MIT license:
|
||||
* http://www.opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
/*jslint unparam: true, nomen: true */
|
||||
/*global define, window, document */
|
||||
|
||||
(function (factory) {
|
||||
'use strict';
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(['jquery'], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
'use strict';
|
||||
|
||||
// Helper variable to create unique names for the transport iframes:
|
||||
var counter = 0;
|
||||
|
||||
// The iframe transport accepts three additional options:
|
||||
// options.fileInput: a jQuery collection of file input fields
|
||||
// options.paramName: the parameter name for the file form data,
|
||||
// overrides the name property of the file input field(s),
|
||||
// can be a string or an array of strings.
|
||||
// options.formData: an array of objects with name and value properties,
|
||||
// equivalent to the return data of .serializeArray(), e.g.:
|
||||
// [{name: 'a', value: 1}, {name: 'b', value: 2}]
|
||||
$.ajaxTransport('iframe', function (options) {
|
||||
if (options.async) {
|
||||
var form,
|
||||
iframe,
|
||||
addParamChar;
|
||||
return {
|
||||
send: function (_, completeCallback) {
|
||||
form = $('<form style="display:none;"></form>');
|
||||
form.attr('accept-charset', options.formAcceptCharset);
|
||||
addParamChar = /\?/.test(options.url) ? '&' : '?';
|
||||
// XDomainRequest only supports GET and POST:
|
||||
if (options.type === 'DELETE') {
|
||||
options.url = options.url + addParamChar + '_method=DELETE';
|
||||
options.type = 'POST';
|
||||
} else if (options.type === 'PUT') {
|
||||
options.url = options.url + addParamChar + '_method=PUT';
|
||||
options.type = 'POST';
|
||||
} else if (options.type === 'PATCH') {
|
||||
options.url = options.url + addParamChar + '_method=PATCH';
|
||||
options.type = 'POST';
|
||||
}
|
||||
// javascript:false as initial iframe src
|
||||
// prevents warning popups on HTTPS in IE6.
|
||||
// IE versions below IE8 cannot set the name property of
|
||||
// elements that have already been added to the DOM,
|
||||
// so we set the name along with the iframe HTML markup:
|
||||
iframe = $(
|
||||
'<iframe src="javascript:false;" name="iframe-transport-' +
|
||||
(counter += 1) + '"></iframe>'
|
||||
).bind('load', function () {
|
||||
var fileInputClones,
|
||||
paramNames = $.isArray(options.paramName) ?
|
||||
options.paramName : [options.paramName];
|
||||
iframe
|
||||
.unbind('load')
|
||||
.bind('load', function () {
|
||||
var response;
|
||||
// Wrap in a try/catch block to catch exceptions thrown
|
||||
// when trying to access cross-domain iframe contents:
|
||||
try {
|
||||
response = iframe.contents();
|
||||
// Google Chrome and Firefox do not throw an
|
||||
// exception when calling iframe.contents() on
|
||||
// cross-domain requests, so we unify the response:
|
||||
if (!response.length || !response[0].firstChild) {
|
||||
throw new Error();
|
||||
}
|
||||
} catch (e) {
|
||||
response = undefined;
|
||||
}
|
||||
// The complete callback returns the
|
||||
// iframe content document as response object:
|
||||
completeCallback(
|
||||
200,
|
||||
'success',
|
||||
{'iframe': response}
|
||||
);
|
||||
// Fix for IE endless progress bar activity bug
|
||||
// (happens on form submits to iframe targets):
|
||||
$('<iframe src="javascript:false;"></iframe>')
|
||||
.appendTo(form);
|
||||
form.remove();
|
||||
});
|
||||
form
|
||||
.prop('target', iframe.prop('name'))
|
||||
.prop('action', options.url)
|
||||
.prop('method', options.type);
|
||||
if (options.formData) {
|
||||
$.each(options.formData, function (index, field) {
|
||||
$('<input type="hidden"/>')
|
||||
.prop('name', field.name)
|
||||
.val(field.value)
|
||||
.appendTo(form);
|
||||
});
|
||||
}
|
||||
if (options.fileInput && options.fileInput.length &&
|
||||
options.type === 'POST') {
|
||||
fileInputClones = options.fileInput.clone();
|
||||
// Insert a clone for each file input field:
|
||||
options.fileInput.after(function (index) {
|
||||
return fileInputClones[index];
|
||||
});
|
||||
if (options.paramName) {
|
||||
options.fileInput.each(function (index) {
|
||||
$(this).prop(
|
||||
'name',
|
||||
paramNames[index] || options.paramName
|
||||
);
|
||||
});
|
||||
}
|
||||
// Appending the file input fields to the hidden form
|
||||
// removes them from their original location:
|
||||
form
|
||||
.append(options.fileInput)
|
||||
.prop('enctype', 'multipart/form-data')
|
||||
// enctype must be set as encoding for IE:
|
||||
.prop('encoding', 'multipart/form-data');
|
||||
}
|
||||
form.submit();
|
||||
// Insert the file input fields at their original location
|
||||
// by replacing the clones with the originals:
|
||||
if (fileInputClones && fileInputClones.length) {
|
||||
options.fileInput.each(function (index, input) {
|
||||
var clone = $(fileInputClones[index]);
|
||||
$(input).prop('name', clone.prop('name'));
|
||||
clone.replaceWith(input);
|
||||
});
|
||||
}
|
||||
});
|
||||
form.append(iframe).appendTo(document.body);
|
||||
},
|
||||
abort: function () {
|
||||
if (iframe) {
|
||||
// javascript:false as iframe src aborts the request
|
||||
// and prevents warning popups on HTTPS in IE6.
|
||||
// concat is used to avoid the "Script URL" JSLint error:
|
||||
iframe
|
||||
.unbind('load')
|
||||
.prop('src', 'javascript'.concat(':false;'));
|
||||
}
|
||||
if (form) {
|
||||
form.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// The iframe transport returns the iframe content document as response.
|
||||
// The following adds converters from iframe to text, json, html, and script:
|
||||
$.ajaxSetup({
|
||||
converters: {
|
||||
'iframe text': function (iframe) {
|
||||
return iframe && $(iframe[0].body).text();
|
||||
},
|
||||
'iframe json': function (iframe) {
|
||||
return iframe && $.parseJSON($(iframe[0].body).text());
|
||||
},
|
||||
'iframe html': function (iframe) {
|
||||
return iframe && $(iframe[0].body).html();
|
||||
},
|
||||
'iframe script': function (iframe) {
|
||||
return iframe && $.globalEval($(iframe[0].body).text());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}));
|
5
core/shared/vendor/jquery/jquery.js
vendored
5
core/shared/vendor/jquery/jquery.js
vendored
File diff suppressed because one or more lines are too long
530
core/shared/vendor/jquery/jquery.ui.widget.js
vendored
530
core/shared/vendor/jquery/jquery.ui.widget.js
vendored
@ -1,530 +0,0 @@
|
||||
/*
|
||||
* jQuery UI Widget 1.10.1+amd
|
||||
* https://github.com/blueimp/jQuery-File-Upload
|
||||
*
|
||||
* Copyright 2013 jQuery Foundation and other contributors
|
||||
* Released under the MIT license.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* http://api.jqueryui.com/jQuery.widget/
|
||||
*/
|
||||
|
||||
(function (factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
// Register as an anonymous AMD module:
|
||||
define(["jquery"], factory);
|
||||
} else {
|
||||
// Browser globals:
|
||||
factory(jQuery);
|
||||
}
|
||||
}(function( $, undefined ) {
|
||||
|
||||
var uuid = 0,
|
||||
slice = Array.prototype.slice,
|
||||
_cleanData = $.cleanData;
|
||||
$.cleanData = function( elems ) {
|
||||
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
|
||||
try {
|
||||
$( elem ).triggerHandler( "remove" );
|
||||
// http://bugs.jquery.com/ticket/8235
|
||||
} catch( e ) {}
|
||||
}
|
||||
_cleanData( elems );
|
||||
};
|
||||
|
||||
$.widget = function( name, base, prototype ) {
|
||||
var fullName, existingConstructor, constructor, basePrototype,
|
||||
// proxiedPrototype allows the provided prototype to remain unmodified
|
||||
// so that it can be used as a mixin for multiple widgets (#8876)
|
||||
proxiedPrototype = {},
|
||||
namespace = name.split( "." )[ 0 ];
|
||||
|
||||
name = name.split( "." )[ 1 ];
|
||||
fullName = namespace + "-" + name;
|
||||
|
||||
if ( !prototype ) {
|
||||
prototype = base;
|
||||
base = $.Widget;
|
||||
}
|
||||
|
||||
// create selector for plugin
|
||||
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
|
||||
return !!$.data( elem, fullName );
|
||||
};
|
||||
|
||||
$[ namespace ] = $[ namespace ] || {};
|
||||
existingConstructor = $[ namespace ][ name ];
|
||||
constructor = $[ namespace ][ name ] = function( options, element ) {
|
||||
// allow instantiation without "new" keyword
|
||||
if ( !this._createWidget ) {
|
||||
return new constructor( options, element );
|
||||
}
|
||||
|
||||
// allow instantiation without initializing for simple inheritance
|
||||
// must use "new" keyword (the code above always passes args)
|
||||
if ( arguments.length ) {
|
||||
this._createWidget( options, element );
|
||||
}
|
||||
};
|
||||
// extend with the existing constructor to carry over any static properties
|
||||
$.extend( constructor, existingConstructor, {
|
||||
version: prototype.version,
|
||||
// copy the object used to create the prototype in case we need to
|
||||
// redefine the widget later
|
||||
_proto: $.extend( {}, prototype ),
|
||||
// track widgets that inherit from this widget in case this widget is
|
||||
// redefined after a widget inherits from it
|
||||
_childConstructors: []
|
||||
});
|
||||
|
||||
basePrototype = new base();
|
||||
// we need to make the options hash a property directly on the new instance
|
||||
// otherwise we'll modify the options hash on the prototype that we're
|
||||
// inheriting from
|
||||
basePrototype.options = $.widget.extend( {}, basePrototype.options );
|
||||
$.each( prototype, function( prop, value ) {
|
||||
if ( !$.isFunction( value ) ) {
|
||||
proxiedPrototype[ prop ] = value;
|
||||
return;
|
||||
}
|
||||
proxiedPrototype[ prop ] = (function() {
|
||||
var _super = function() {
|
||||
return base.prototype[ prop ].apply( this, arguments );
|
||||
},
|
||||
_superApply = function( args ) {
|
||||
return base.prototype[ prop ].apply( this, args );
|
||||
};
|
||||
return function() {
|
||||
var __super = this._super,
|
||||
__superApply = this._superApply,
|
||||
returnValue;
|
||||
|
||||
this._super = _super;
|
||||
this._superApply = _superApply;
|
||||
|
||||
returnValue = value.apply( this, arguments );
|
||||
|
||||
this._super = __super;
|
||||
this._superApply = __superApply;
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
})();
|
||||
});
|
||||
constructor.prototype = $.widget.extend( basePrototype, {
|
||||
// TODO: remove support for widgetEventPrefix
|
||||
// always use the name + a colon as the prefix, e.g., draggable:start
|
||||
// don't prefix for widgets that aren't DOM-based
|
||||
widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
|
||||
}, proxiedPrototype, {
|
||||
constructor: constructor,
|
||||
namespace: namespace,
|
||||
widgetName: name,
|
||||
widgetFullName: fullName
|
||||
});
|
||||
|
||||
// If this widget is being redefined then we need to find all widgets that
|
||||
// are inheriting from it and redefine all of them so that they inherit from
|
||||
// the new version of this widget. We're essentially trying to replace one
|
||||
// level in the prototype chain.
|
||||
if ( existingConstructor ) {
|
||||
$.each( existingConstructor._childConstructors, function( i, child ) {
|
||||
var childPrototype = child.prototype;
|
||||
|
||||
// redefine the child widget using the same prototype that was
|
||||
// originally used, but inherit from the new version of the base
|
||||
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
|
||||
});
|
||||
// remove the list of existing child constructors from the old constructor
|
||||
// so the old child constructors can be garbage collected
|
||||
delete existingConstructor._childConstructors;
|
||||
} else {
|
||||
base._childConstructors.push( constructor );
|
||||
}
|
||||
|
||||
$.widget.bridge( name, constructor );
|
||||
};
|
||||
|
||||
$.widget.extend = function( target ) {
|
||||
var input = slice.call( arguments, 1 ),
|
||||
inputIndex = 0,
|
||||
inputLength = input.length,
|
||||
key,
|
||||
value;
|
||||
for ( ; inputIndex < inputLength; inputIndex++ ) {
|
||||
for ( key in input[ inputIndex ] ) {
|
||||
value = input[ inputIndex ][ key ];
|
||||
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
|
||||
// Clone objects
|
||||
if ( $.isPlainObject( value ) ) {
|
||||
target[ key ] = $.isPlainObject( target[ key ] ) ?
|
||||
$.widget.extend( {}, target[ key ], value ) :
|
||||
// Don't extend strings, arrays, etc. with objects
|
||||
$.widget.extend( {}, value );
|
||||
// Copy everything else by reference
|
||||
} else {
|
||||
target[ key ] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
};
|
||||
|
||||
$.widget.bridge = function( name, object ) {
|
||||
var fullName = object.prototype.widgetFullName || name;
|
||||
$.fn[ name ] = function( options ) {
|
||||
var isMethodCall = typeof options === "string",
|
||||
args = slice.call( arguments, 1 ),
|
||||
returnValue = this;
|
||||
|
||||
// allow multiple hashes to be passed on init
|
||||
options = !isMethodCall && args.length ?
|
||||
$.widget.extend.apply( null, [ options ].concat(args) ) :
|
||||
options;
|
||||
|
||||
if ( isMethodCall ) {
|
||||
this.each(function() {
|
||||
var methodValue,
|
||||
instance = $.data( this, fullName );
|
||||
if ( !instance ) {
|
||||
return $.error( "cannot call methods on " + name + " prior to initialization; " +
|
||||
"attempted to call method '" + options + "'" );
|
||||
}
|
||||
if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
|
||||
return $.error( "no such method '" + options + "' for " + name + " widget instance" );
|
||||
}
|
||||
methodValue = instance[ options ].apply( instance, args );
|
||||
if ( methodValue !== instance && methodValue !== undefined ) {
|
||||
returnValue = methodValue && methodValue.jquery ?
|
||||
returnValue.pushStack( methodValue.get() ) :
|
||||
methodValue;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.each(function() {
|
||||
var instance = $.data( this, fullName );
|
||||
if ( instance ) {
|
||||
instance.option( options || {} )._init();
|
||||
} else {
|
||||
$.data( this, fullName, new object( options, this ) );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
};
|
||||
|
||||
$.Widget = function( /* options, element */ ) {};
|
||||
$.Widget._childConstructors = [];
|
||||
|
||||
$.Widget.prototype = {
|
||||
widgetName: "widget",
|
||||
widgetEventPrefix: "",
|
||||
defaultElement: "<div>",
|
||||
options: {
|
||||
disabled: false,
|
||||
|
||||
// callbacks
|
||||
create: null
|
||||
},
|
||||
_createWidget: function( options, element ) {
|
||||
element = $( element || this.defaultElement || this )[ 0 ];
|
||||
this.element = $( element );
|
||||
this.uuid = uuid++;
|
||||
this.eventNamespace = "." + this.widgetName + this.uuid;
|
||||
this.options = $.widget.extend( {},
|
||||
this.options,
|
||||
this._getCreateOptions(),
|
||||
options );
|
||||
|
||||
this.bindings = $();
|
||||
this.hoverable = $();
|
||||
this.focusable = $();
|
||||
|
||||
if ( element !== this ) {
|
||||
$.data( element, this.widgetFullName, this );
|
||||
this._on( true, this.element, {
|
||||
remove: function( event ) {
|
||||
if ( event.target === element ) {
|
||||
this.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.document = $( element.style ?
|
||||
// element within the document
|
||||
element.ownerDocument :
|
||||
// element is window or document
|
||||
element.document || element );
|
||||
this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
|
||||
}
|
||||
|
||||
this._create();
|
||||
this._trigger( "create", null, this._getCreateEventData() );
|
||||
this._init();
|
||||
},
|
||||
_getCreateOptions: $.noop,
|
||||
_getCreateEventData: $.noop,
|
||||
_create: $.noop,
|
||||
_init: $.noop,
|
||||
|
||||
destroy: function() {
|
||||
this._destroy();
|
||||
// we can probably remove the unbind calls in 2.0
|
||||
// all event bindings should go through this._on()
|
||||
this.element
|
||||
.unbind( this.eventNamespace )
|
||||
// 1.9 BC for #7810
|
||||
// TODO remove dual storage
|
||||
.removeData( this.widgetName )
|
||||
.removeData( this.widgetFullName )
|
||||
// support: jquery <1.6.3
|
||||
// http://bugs.jquery.com/ticket/9413
|
||||
.removeData( $.camelCase( this.widgetFullName ) );
|
||||
this.widget()
|
||||
.unbind( this.eventNamespace )
|
||||
.removeAttr( "aria-disabled" )
|
||||
.removeClass(
|
||||
this.widgetFullName + "-disabled " +
|
||||
"ui-state-disabled" );
|
||||
|
||||
// clean up events and states
|
||||
this.bindings.unbind( this.eventNamespace );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
},
|
||||
_destroy: $.noop,
|
||||
|
||||
widget: function() {
|
||||
return this.element;
|
||||
},
|
||||
|
||||
option: function( key, value ) {
|
||||
var options = key,
|
||||
parts,
|
||||
curOption,
|
||||
i;
|
||||
|
||||
if ( arguments.length === 0 ) {
|
||||
// don't return a reference to the internal hash
|
||||
return $.widget.extend( {}, this.options );
|
||||
}
|
||||
|
||||
if ( typeof key === "string" ) {
|
||||
// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
|
||||
options = {};
|
||||
parts = key.split( "." );
|
||||
key = parts.shift();
|
||||
if ( parts.length ) {
|
||||
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
|
||||
for ( i = 0; i < parts.length - 1; i++ ) {
|
||||
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
|
||||
curOption = curOption[ parts[ i ] ];
|
||||
}
|
||||
key = parts.pop();
|
||||
if ( value === undefined ) {
|
||||
return curOption[ key ] === undefined ? null : curOption[ key ];
|
||||
}
|
||||
curOption[ key ] = value;
|
||||
} else {
|
||||
if ( value === undefined ) {
|
||||
return this.options[ key ] === undefined ? null : this.options[ key ];
|
||||
}
|
||||
options[ key ] = value;
|
||||
}
|
||||
}
|
||||
|
||||
this._setOptions( options );
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOptions: function( options ) {
|
||||
var key;
|
||||
|
||||
for ( key in options ) {
|
||||
this._setOption( key, options[ key ] );
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
_setOption: function( key, value ) {
|
||||
this.options[ key ] = value;
|
||||
|
||||
if ( key === "disabled" ) {
|
||||
this.widget()
|
||||
.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
|
||||
.attr( "aria-disabled", value );
|
||||
this.hoverable.removeClass( "ui-state-hover" );
|
||||
this.focusable.removeClass( "ui-state-focus" );
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
enable: function() {
|
||||
return this._setOption( "disabled", false );
|
||||
},
|
||||
disable: function() {
|
||||
return this._setOption( "disabled", true );
|
||||
},
|
||||
|
||||
_on: function( suppressDisabledCheck, element, handlers ) {
|
||||
var delegateElement,
|
||||
instance = this;
|
||||
|
||||
// no suppressDisabledCheck flag, shuffle arguments
|
||||
if ( typeof suppressDisabledCheck !== "boolean" ) {
|
||||
handlers = element;
|
||||
element = suppressDisabledCheck;
|
||||
suppressDisabledCheck = false;
|
||||
}
|
||||
|
||||
// no element argument, shuffle and use this.element
|
||||
if ( !handlers ) {
|
||||
handlers = element;
|
||||
element = this.element;
|
||||
delegateElement = this.widget();
|
||||
} else {
|
||||
// accept selectors, DOM elements
|
||||
element = delegateElement = $( element );
|
||||
this.bindings = this.bindings.add( element );
|
||||
}
|
||||
|
||||
$.each( handlers, function( event, handler ) {
|
||||
function handlerProxy() {
|
||||
// allow widgets to customize the disabled handling
|
||||
// - disabled as an array instead of boolean
|
||||
// - disabled class as method for disabling individual parts
|
||||
if ( !suppressDisabledCheck &&
|
||||
( instance.options.disabled === true ||
|
||||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
|
||||
return;
|
||||
}
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
|
||||
// copy the guid so direct unbinding works
|
||||
if ( typeof handler !== "string" ) {
|
||||
handlerProxy.guid = handler.guid =
|
||||
handler.guid || handlerProxy.guid || $.guid++;
|
||||
}
|
||||
|
||||
var match = event.match( /^(\w+)\s*(.*)$/ ),
|
||||
eventName = match[1] + instance.eventNamespace,
|
||||
selector = match[2];
|
||||
if ( selector ) {
|
||||
delegateElement.delegate( selector, eventName, handlerProxy );
|
||||
} else {
|
||||
element.bind( eventName, handlerProxy );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_off: function( element, eventName ) {
|
||||
eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
|
||||
element.unbind( eventName ).undelegate( eventName );
|
||||
},
|
||||
|
||||
_delay: function( handler, delay ) {
|
||||
function handlerProxy() {
|
||||
return ( typeof handler === "string" ? instance[ handler ] : handler )
|
||||
.apply( instance, arguments );
|
||||
}
|
||||
var instance = this;
|
||||
return setTimeout( handlerProxy, delay || 0 );
|
||||
},
|
||||
|
||||
_hoverable: function( element ) {
|
||||
this.hoverable = this.hoverable.add( element );
|
||||
this._on( element, {
|
||||
mouseenter: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-hover" );
|
||||
},
|
||||
mouseleave: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-hover" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_focusable: function( element ) {
|
||||
this.focusable = this.focusable.add( element );
|
||||
this._on( element, {
|
||||
focusin: function( event ) {
|
||||
$( event.currentTarget ).addClass( "ui-state-focus" );
|
||||
},
|
||||
focusout: function( event ) {
|
||||
$( event.currentTarget ).removeClass( "ui-state-focus" );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_trigger: function( type, event, data ) {
|
||||
var prop, orig,
|
||||
callback = this.options[ type ];
|
||||
|
||||
data = data || {};
|
||||
event = $.Event( event );
|
||||
event.type = ( type === this.widgetEventPrefix ?
|
||||
type :
|
||||
this.widgetEventPrefix + type ).toLowerCase();
|
||||
// the original event may come from any element
|
||||
// so we need to reset the target on the new event
|
||||
event.target = this.element[ 0 ];
|
||||
|
||||
// copy original event properties over to the new event
|
||||
orig = event.originalEvent;
|
||||
if ( orig ) {
|
||||
for ( prop in orig ) {
|
||||
if ( !( prop in event ) ) {
|
||||
event[ prop ] = orig[ prop ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.element.trigger( event, data );
|
||||
return !( $.isFunction( callback ) &&
|
||||
callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
|
||||
event.isDefaultPrevented() );
|
||||
}
|
||||
};
|
||||
|
||||
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
|
||||
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
|
||||
if ( typeof options === "string" ) {
|
||||
options = { effect: options };
|
||||
}
|
||||
var hasOptions,
|
||||
effectName = !options ?
|
||||
method :
|
||||
options === true || typeof options === "number" ?
|
||||
defaultEffect :
|
||||
options.effect || defaultEffect;
|
||||
options = options || {};
|
||||
if ( typeof options === "number" ) {
|
||||
options = { duration: options };
|
||||
}
|
||||
hasOptions = !$.isEmptyObject( options );
|
||||
options.complete = callback;
|
||||
if ( options.delay ) {
|
||||
element.delay( options.delay );
|
||||
}
|
||||
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
|
||||
element[ method ]( options );
|
||||
} else if ( effectName !== method && element[ effectName ] ) {
|
||||
element[ effectName ]( options.duration, options.easing, callback );
|
||||
} else {
|
||||
element.queue(function( next ) {
|
||||
$( this )[ method ]();
|
||||
if ( callback ) {
|
||||
callback.call( element[ 0 ] );
|
||||
}
|
||||
next();
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
}));
|
4979
core/shared/vendor/lodash.underscore.js
vendored
4979
core/shared/vendor/lodash.underscore.js
vendored
File diff suppressed because it is too large
Load Diff
2314
core/shared/vendor/moment.js
vendored
2314
core/shared/vendor/moment.js
vendored
File diff suppressed because it is too large
Load Diff
@ -45,7 +45,7 @@ CasperTest.begin("Ghost editor is correct", 10, function suite(test) {
|
||||
});
|
||||
});
|
||||
|
||||
CasperTest.begin("Haunted markdown in editor works", 3, function suite(test) {
|
||||
CasperTest.begin("Markdown in editor works", 3, function suite(test) {
|
||||
casper.thenOpen(url + "ghost/editor/", function testTitleAndUrl() {
|
||||
test.assertTitle("Ghost Admin", "Ghost admin has no title");
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ var testUtils = require('../utils'),
|
||||
should = require('should'),
|
||||
|
||||
// Stuff we are testing
|
||||
gdPath = "../../client/assets/vendor/showdown/extensions/ghostdown.js",
|
||||
gdPath = "../../client/assets/lib/showdown/extensions/ghostdown.js",
|
||||
ghostdown = require(gdPath);
|
||||
|
||||
describe("Ghostdown showdown extensions", function () {
|
||||
|
@ -10,8 +10,8 @@ var testUtils = require('../utils'),
|
||||
|
||||
// Stuff we are testing
|
||||
Showdown = require('showdown'),
|
||||
github = require('../../shared/vendor/showdown/extensions/github'),
|
||||
ghostdown = require('../../client/assets/vendor/showdown/extensions/ghostdown'),
|
||||
github = require('../../shared/lib/showdown/extensions/github'),
|
||||
ghostdown = require('../../client/assets/lib/showdown/extensions/ghostdown'),
|
||||
converter = new Showdown.converter({extensions: [ghostdown, github]});
|
||||
|
||||
describe("Showdown client side converter", function () {
|
||||
|
@ -452,7 +452,7 @@ describe('Core Helpers', function () {
|
||||
|
||||
helpers.ghost_foot.call().then(function (rendered) {
|
||||
should.exist(rendered);
|
||||
rendered.string.should.match(/<script src=".*\/shared\/vendor\/jquery\/jquery.js\?v=abc"><\/script>/);
|
||||
rendered.string.should.match(/<script src=".*\/public\/jquery.js\?v=abc"><\/script>/);
|
||||
|
||||
done();
|
||||
}).then(null, done);
|
||||
|
@ -8,7 +8,7 @@ var testUtils = require('../utils'),
|
||||
should = require('should'),
|
||||
|
||||
// Stuff we are testing
|
||||
ghPath = "../../shared/vendor/showdown/extensions/github.js",
|
||||
ghPath = "../../shared/lib/showdown/extensions/github.js",
|
||||
github = require(ghPath);
|
||||
|
||||
function _ExecuteExtension(ext, text) {
|
||||
|
@ -24,7 +24,8 @@
|
||||
"main": "./core/index",
|
||||
"scripts": {
|
||||
"start": "node index",
|
||||
"test": "./node_modules/.bin/grunt validate --verbose"
|
||||
"test": "./node_modules/.bin/grunt validate --verbose",
|
||||
"postinstall": "bower install"
|
||||
},
|
||||
"engines": {
|
||||
"node": "~0.10.0"
|
||||
@ -59,6 +60,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"blanket": "~1.1.5",
|
||||
"bower": "~1.2.8",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
|
Loading…
Reference in New Issue
Block a user