diff --git a/.afignore b/.afignore
new file mode 100644
index 0000000000..08665d9e86
--- /dev/null
+++ b/.afignore
@@ -0,0 +1,24 @@
+#ignore database
+b-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+npm-debug.log
+
+.idea/*
+*.iml
+projectFilesBackup
+
+.DS_Store
+
+# Ghost DB file
+ghost/data/*.db
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..8f567c00f0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,31 @@
+b-cov
+*.seed
+*.log
+*.csv
+*.dat
+*.out
+*.pid
+*.gz
+
+pids
+logs
+results
+
+npm-debug.log
+node_modules
+
+.idea/*
+*.iml
+projectFilesBackup
+
+.DS_Store
+
+# Ghost DB file
+*.db
+
+/core/admin/assets/css
+.sass-cache/
+/core/admin/assets/sass/config.rb
+/core/admin/assets/sass/layouts/config.rb
+/core/admin/assets/sass/modules/config.rb
+/ghost/.idea/
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..4020711c1a
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "content/themes/casper"]
+ path = content/themes/casper
+ url = git@github.com:TryGhost/Casper.git
diff --git a/.groc.json b/.groc.json
new file mode 100644
index 0000000000..a21fd648bc
--- /dev/null
+++ b/.groc.json
@@ -0,0 +1,5 @@
+{
+ "glob": ["README.md", "config.js", "app.js", "core/ghost.js", "core/admin/assets/js/*.js", "core/frontend/helpers/index.js", "core/lang/i18n.js"],
+ "except": ["core/admin/assets/lib/chart.min.js"],
+ "out": "./docs"
+}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000..240a1516d9
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2013 Ghost
+
+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.
\ No newline at end of file
diff --git a/README.md b/README.md
index a1624f8c14..433d66f06b 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,85 @@
-Ghost
-=====
+# Ghost
+
+Welcome to the Ghost core repo. The code here is the result of a few stolen hours of free time hacking a proof of concept for the Kickstarter video. Pretty much everything is subject to and expected to change.
+
+The top priorities right now are:
+
+* Having a core RESTful API and consuming it internally
+* Data model design & implementation - including a potential switch from JugglingDB to bookshelf.js
+* Authentication and ACL
+* Improving core architecture & design - modular structure, better dependency injection, testable code with tests
+
+
+
+###To Install:
+
+**Note:** It is highly recommended that you use the [Ghost-Vagrant](https://github.com/TryGhost/Ghost-Vagrant) setup for developing Ghost.
+
+1. Clone the git repo
+1. cd into the project folder and run ```npm install```.
+ * If the install fails with errors to do with "node-gyp rebuild", follow the Sqlite3 install instructions
+1. cd into /core/admin/assets and run ```compass compile --css-dir=css```
+
+
+Frontend can be located at [localhost:3333](localhost:3333), Admin is at [localhost:3333/ghost](localhost:3333/ghost)
+
+
+#### Sqlite3 Install Instructions
+Ghost depends upon sqlite3, which has to be built for each OS. NPM is as smart as it can be about this, and as long as your machine has all the pre-requisites for compiling/building a C++ program, the npm install still works.
+
+However, if you don't have the required pre-requisites, you will need to either get them, or as a shortcut, obtain a precompiled sqlite3 package for your OS.
+
+I have created some of these, and they can be obtained from [this GitHub issue](https://github.com/developmentseed/node-sqlite3/issues/106).
+
+The pre-compiled package should be downloaded, extracted and placed in the node\_modules folder, such that it lives in node\_modules/sqlite3, if you have a partial install of the sqlite3 package, replace it with the files you downloaded from github. Be sure that all the sqlite3 files and folders live directly in node\_modules/sqlite3 - there should note be a node\_modules/sqlite3/sqlite3 folder.
+
+
+###Dependencies:
+
+* express.js framework
+* handlebars for templating
+* standard css for frontend
+* sass for admin (pre-compiled)
+* moment.js for time / date manipulation
+* underscore for object & array utils
+* showdown for converting markdown to HTML
+* nodeunit for unit testing
+* sqlite3 for data storage
+* jugglingdb ORM for interacting with the database
+* Polyglot.js for i18n
+
+#### Frontend libraries:
+
+* jQuery 1.9.1
+* showdown for converting markdown to HTML
+* codemirror editor
+
+### Working features:
+
+* Dashboard
+ * new post link
+* Admin menu
+ * G, dashboard, content, new post & settings menu items go to correct pages
+* Content screen
+ * Lists all posts with correct titles (incorrect time etc)
+ * Select post in list highlights that post and opens it in the preview pane
+* Write screen
+ * Live preview works for all standard markdown
+ * Save draft button saves entered title & content. Everything is published by default.
+ * Editing/opening existing post puts correct info in title and content panels & save updates content.
+* Database
+ * The database is created and populated with basic data on first run of the server
+ * New posts and edits save and last forever
+ * The data can be reset by opening data/datastore.db and emptying the file. The next restart of the server will cause the database to be recreated and repopulated.
+* Frontend
+ * Homepage lists a number of posts as configured in config.js
+ * Clicking on an individual post loads an individual post page
+ * Date formatting helper uses moment
+
+### Front End Work
+
+A SASS compiler is required to work with the CSS in this project.
+
+Run ```compass compile --css-dir=css``` from /core/admin/assets.
+
+We also recommend [CodeKit](http://incident57.com/codekit/) (Paid/Mac) and [Scout](http://mhs.github.io/scout-app/) (Free/Mac/PC).
\ No newline at end of file
diff --git a/app.js b/app.js
new file mode 100644
index 0000000000..b8663819c9
--- /dev/null
+++ b/app.js
@@ -0,0 +1,80 @@
+// # Ghost main app file
+
+/*global require */
+(function () {
+ "use strict";
+
+ // Module dependencies.
+ var express = require('express'),
+ fs = require('fs'),
+ admin = require('./core/admin/controllers'),
+ frontend = require('./core/frontend/controllers'),
+ flash = require('connect-flash'),
+ Ghost = require('./core/ghost'),
+ I18n = require('./core/lang/i18n'),
+ helpers = require('./core/frontend/helpers'),
+ auth,
+
+ // ## Variables
+ /**
+ * Create new Ghost object
+ * @type {Ghost}
+ */
+ ghost = new Ghost();
+
+ ghost.app().configure('development', function () {
+ ghost.app().use(express.favicon(__dirname + '/content/images/favicon.ico'));
+ ghost.app().use(express.errorHandler());
+ ghost.app().use(I18n.load(ghost));
+ ghost.app().use(express.bodyParser());
+ ghost.app().use(express.cookieParser('try-ghost'));
+ ghost.app().use(express.session({ cookie: { maxAge: 60000 }}));
+ ghost.app().use(flash());
+ ghost.app().use(ghost.initTheme(ghost.app()));
+ });
+
+ /**
+ * Setup login details
+ * p.s. love it.
+ *
+ * @type {*}
+ */
+ auth = express.basicAuth('ghostadmin', 'Wh0YouGonnaCall?');
+
+ helpers.loadCoreHelpers(ghost);
+
+
+ /**
+ * API routes..
+ * @todo convert these into a RESTful, public, authenticated API!
+ */
+ ghost.app().post('/api/v0.1/posts/create', auth, admin.posts.create);
+ ghost.app().post('/api/v0.1/posts/edit', auth, admin.posts.edit);
+ ghost.app().get('/api/v0.1/posts', auth, admin.posts.index);
+
+ /**
+ * Admin routes..
+ * @todo put these somewhere in admin
+ */
+ ghost.app().get('/ghost/editor/:id', auth, admin.editor);
+ ghost.app().get('/ghost/editor', auth, admin.editor);
+ ghost.app().get('/ghost/blog', auth, admin.blog);
+ ghost.app().get('/ghost/settings', auth, admin.settings);
+ ghost.app().get('/ghost/debug', auth, admin.debug.index);
+ ghost.app().get('/ghost/debug/db/delete/', auth, admin.debug.dbdelete);
+ ghost.app().get('/ghost/debug/db/populate/', auth, admin.debug.dbpopulate);
+ ghost.app().get('/ghost', auth, admin.index);
+
+ /**
+ * Frontend routes..
+ * @todo dynamic routing, homepage generator, filters ETC ETC
+ */
+ ghost.app().get('/:slug', frontend.single);
+ ghost.app().get('/', frontend.homepage);
+
+
+ ghost.app().listen(3333, function () {
+ console.log("Express server listening on port " + 3333);
+ console.log('process: ', process.env);
+ });
+}());
\ No newline at end of file
diff --git a/config.js b/config.js
new file mode 100644
index 0000000000..28875e22f6
--- /dev/null
+++ b/config.js
@@ -0,0 +1,62 @@
+// # Ghost Configuration
+
+/**
+ * global module
+ **/
+(function () {
+ "use strict";
+
+ /**
+ * @module config
+ * @type {Object}
+ */
+ var config = {};
+
+ // ## Admin settings
+
+ /**
+ * @property {string} defaultLang
+ */
+ config.defaultLang = 'en';
+
+ /**
+ * @property {boolean} forceI18n
+ */
+ config.forceI18n = true;
+
+ // ## Themes
+
+ /**
+ * @property {string} themeDir
+ */
+
+ // Themes
+ config.themeDir = 'themes';
+
+ /**
+ * @property {string} activeTheme
+ */
+ config.activeTheme = 'casper';
+
+ // ## Homepage settings
+ /**
+ * @module homepage
+ * @type {Object}
+ */
+ config.homepage = {};
+
+ /**
+ * @property {number} features
+ */
+ config.homepage.features = 1;
+
+ /**
+ * @property {number} posts
+ */
+ config.homepage.posts = 4;
+
+ /**
+ * @property {Object} exports
+ */
+ module.exports = config;
+}());
\ No newline at end of file
diff --git a/config.rb b/config.rb
new file mode 100644
index 0000000000..960397bb55
--- /dev/null
+++ b/config.rb
@@ -0,0 +1,26 @@
+# Require any additional compass plugins here.
+
+
+# Set this to the root of your project when deployed:
+http_path = "/"
+css_dir = "core/admin/assets/css"
+sass_dir = "core/admin/assets/sass"
+images_dir = "core/admin/assets/img"
+javascripts_dir = "core/admin/assets/js"
+fonts_dir = "core/admin/assets/fonts"
+
+output_style = :nested
+
+# To enable relative paths to assets via compass helper functions. Uncomment:
+# relative_assets = true
+
+# To disable debugging comments that display the original location of your selectors. Uncomment:
+# line_comments = false
+color_output = false
+
+
+# If you prefer the indented syntax, you might want to regenerate this
+# project again passing --syntax sass, or you can uncomment this:
+# preferred_syntax = :sass
+# and then run:
+# sass-convert -R --from scss --to sass sass scss && rm -rf sass && mv scss sass
diff --git a/content/README.md b/content/README.md
new file mode 100644
index 0000000000..8f09551936
--- /dev/null
+++ b/content/README.md
@@ -0,0 +1,13 @@
+#Content
+
+This section of the repo is the area that a normal user is allowed to add and change stuff. This is where their themes, plugins and images will live.
+
+By default for an install:
+
+* the themes directory will contain Casper
+* the plugins directory will be empty
+* the images directory will be empty
+
+Currently the plugins and images directory contain some stuff for testing.
+
+By default, Ghost will support very basic image uploads. It will be expected and encouraged for users to connect to a 3rd party service for improved media support and a CDN. Much like comments, we don't see supporting advanced file uploads, having a media library or being a CDN as core competencies - there are already plenty of people out there doing this much better than we can.
diff --git a/content/images/DSCF1202-1-800x420.jpg b/content/images/DSCF1202-1-800x420.jpg
new file mode 100644
index 0000000000..20ac957539
Binary files /dev/null and b/content/images/DSCF1202-1-800x420.jpg differ
diff --git a/content/images/DSCF1308-800x420.jpg b/content/images/DSCF1308-800x420.jpg
new file mode 100644
index 0000000000..18f555f468
Binary files /dev/null and b/content/images/DSCF1308-800x420.jpg differ
diff --git a/content/images/DSCF1703-800x420.jpg b/content/images/DSCF1703-800x420.jpg
new file mode 100644
index 0000000000..27ae159d36
Binary files /dev/null and b/content/images/DSCF1703-800x420.jpg differ
diff --git a/content/images/Egypt-Vimeo-Cover-800x420.jpg b/content/images/Egypt-Vimeo-Cover-800x420.jpg
new file mode 100644
index 0000000000..c56b9b68cb
Binary files /dev/null and b/content/images/Egypt-Vimeo-Cover-800x420.jpg differ
diff --git a/content/images/depostimg.jpg b/content/images/depostimg.jpg
new file mode 100644
index 0000000000..8a31745c61
Binary files /dev/null and b/content/images/depostimg.jpg differ
diff --git a/content/images/favicon.ico b/content/images/favicon.ico
new file mode 100644
index 0000000000..f614472c91
Binary files /dev/null and b/content/images/favicon.ico differ
diff --git a/content/images/ghost-dashboard.jpg b/content/images/ghost-dashboard.jpg
new file mode 100644
index 0000000000..9ff6a2c44c
Binary files /dev/null and b/content/images/ghost-dashboard.jpg differ
diff --git a/content/images/ghostpost.jpg b/content/images/ghostpost.jpg
new file mode 100644
index 0000000000..2eaa9667f5
Binary files /dev/null and b/content/images/ghostpost.jpg differ
diff --git a/content/images/logo.png b/content/images/logo.png
new file mode 100644
index 0000000000..5d6532825c
Binary files /dev/null and b/content/images/logo.png differ
diff --git a/content/plugins/fancyFirstChar.js b/content/plugins/fancyFirstChar.js
new file mode 100644
index 0000000000..f133346be9
--- /dev/null
+++ b/content/plugins/fancyFirstChar.js
@@ -0,0 +1,45 @@
+/*globals exports */
+(function () {
+ "use strict";
+
+ var FancyFirstChar;
+
+ FancyFirstChar = function (ghost) {
+ this.ghost = function () {
+ return ghost;
+ };
+ };
+ FancyFirstChar.prototype.init = function () {
+ this.ghost().registerFilter('prePostsRender', function (posts) {
+ var post,
+ originalContent,
+ newContent,
+ firstCharIndex = 0;
+
+ console.log('got content to filter', posts);
+
+ for (post in posts) {
+ if (posts.hasOwnProperty(post)) {
+ originalContent = posts[post].content;
+ if (originalContent.substr(0, 1) === '<') {
+ firstCharIndex = originalContent.indexOf('>') + 1;
+ }
+
+ newContent = originalContent.substr(0, firstCharIndex);
+ newContent += '';
+ newContent += originalContent.substr(firstCharIndex, 1);
+ newContent += '';
+ newContent += originalContent.substr(firstCharIndex + 1, originalContent.length - firstCharIndex - 1);
+
+ posts[post].content = newContent;
+ }
+ }
+ return posts;
+ });
+ };
+
+ FancyFirstChar.prototype.activate = function () {};
+ FancyFirstChar.prototype.deactivate = function () {};
+
+ module.exports = FancyFirstChar;
+}());
diff --git a/content/themes/casper b/content/themes/casper
new file mode 160000
index 0000000000..151f5d3f4c
--- /dev/null
+++ b/content/themes/casper
@@ -0,0 +1 @@
+Subproject commit 151f5d3f4c3b613a283a0733ffd1f97f403f477c
diff --git a/core/README.md b/core/README.md
new file mode 100644
index 0000000000..9268207010
--- /dev/null
+++ b/core/README.md
@@ -0,0 +1,12 @@
+# Core
+
+Core contains the bread and butter of ghost. It is currently divided up into:
+
+* **admin** - the views, controllers, assets and helpers for rendering & working the admin panel
+* **frontend** - the controllers & helpers for creating the frontend of the blog. Views & assets live in themes
+* **lang** - the current home of everything i18n, this was done as a proof of concept on a very early version of the prototype and needs love
+* **shared** - basically everything to do with data & models. The sqlite db file lives in the data folder here. This is the part that needs the most work so it doesn't make much sense yet, and is also the highest priority
+* **test** - currently contains two sad unit tests and a set of html prototypes of the admin UI. Really, this folder should reflect all of core. It is my personal mission to make that happen ASAP & get us linked up with Travis.
+* **ghost.js** - currently both the glue that binds everything together and what gives us the API for registering themes and plugins. The initTheme function is a bit of a hack which lets us serve different views & static content up for the admin & frontend.
+
+This structure is by no means final and recommendations are more than welcome.
\ No newline at end of file
diff --git a/core/admin/assets/fonts/icons.dev.svg b/core/admin/assets/fonts/icons.dev.svg
new file mode 100644
index 0000000000..d707fa219b
--- /dev/null
+++ b/core/admin/assets/fonts/icons.dev.svg
@@ -0,0 +1,196 @@
+
+
+
\ No newline at end of file
diff --git a/core/admin/assets/fonts/icons.eot b/core/admin/assets/fonts/icons.eot
new file mode 100644
index 0000000000..4c59f6a9d6
Binary files /dev/null and b/core/admin/assets/fonts/icons.eot differ
diff --git a/core/admin/assets/fonts/icons.svg b/core/admin/assets/fonts/icons.svg
new file mode 100644
index 0000000000..1a10f9a124
--- /dev/null
+++ b/core/admin/assets/fonts/icons.svg
@@ -0,0 +1,196 @@
+
+
+
\ No newline at end of file
diff --git a/core/admin/assets/fonts/icons.ttf b/core/admin/assets/fonts/icons.ttf
new file mode 100644
index 0000000000..1defe310dd
Binary files /dev/null and b/core/admin/assets/fonts/icons.ttf differ
diff --git a/core/admin/assets/fonts/icons.woff b/core/admin/assets/fonts/icons.woff
new file mode 100644
index 0000000000..f95f6f16ee
Binary files /dev/null and b/core/admin/assets/fonts/icons.woff differ
diff --git a/core/admin/assets/img/dash/CampaignMonitor@2x.png b/core/admin/assets/img/dash/CampaignMonitor@2x.png
new file mode 100644
index 0000000000..895a8a3c45
Binary files /dev/null and b/core/admin/assets/img/dash/CampaignMonitor@2x.png differ
diff --git a/core/admin/assets/img/dash/Facebook@2x.png b/core/admin/assets/img/dash/Facebook@2x.png
new file mode 100644
index 0000000000..d14600c087
Binary files /dev/null and b/core/admin/assets/img/dash/Facebook@2x.png differ
diff --git a/core/admin/assets/img/dash/GooglePlus@2x.png b/core/admin/assets/img/dash/GooglePlus@2x.png
new file mode 100644
index 0000000000..4534c86e76
Binary files /dev/null and b/core/admin/assets/img/dash/GooglePlus@2x.png differ
diff --git a/core/admin/assets/img/dash/Image@2x.png b/core/admin/assets/img/dash/Image@2x.png
new file mode 100644
index 0000000000..e75a4861ae
Binary files /dev/null and b/core/admin/assets/img/dash/Image@2x.png differ
diff --git a/core/admin/assets/img/dash/PostsStats@2x.png b/core/admin/assets/img/dash/PostsStats@2x.png
new file mode 100644
index 0000000000..fac316bd0a
Binary files /dev/null and b/core/admin/assets/img/dash/PostsStats@2x.png differ
diff --git a/core/admin/assets/img/dash/Stats@2x.png b/core/admin/assets/img/dash/Stats@2x.png
new file mode 100644
index 0000000000..92cd80479b
Binary files /dev/null and b/core/admin/assets/img/dash/Stats@2x.png differ
diff --git a/core/admin/assets/img/dash/Time@2x.png b/core/admin/assets/img/dash/Time@2x.png
new file mode 100644
index 0000000000..bb705aea39
Binary files /dev/null and b/core/admin/assets/img/dash/Time@2x.png differ
diff --git a/core/admin/assets/img/dash/Twitter@2x.png b/core/admin/assets/img/dash/Twitter@2x.png
new file mode 100644
index 0000000000..3ab4e06312
Binary files /dev/null and b/core/admin/assets/img/dash/Twitter@2x.png differ
diff --git a/core/admin/assets/img/ghost-icon.png b/core/admin/assets/img/ghost-icon.png
new file mode 100644
index 0000000000..a5673f8c47
Binary files /dev/null and b/core/admin/assets/img/ghost-icon.png differ
diff --git a/core/admin/assets/img/logo.png b/core/admin/assets/img/logo.png
new file mode 100644
index 0000000000..18ae21c1f4
Binary files /dev/null and b/core/admin/assets/img/logo.png differ
diff --git a/core/admin/assets/img/postimg.jpg b/core/admin/assets/img/postimg.jpg
new file mode 100644
index 0000000000..b181ba40e3
Binary files /dev/null and b/core/admin/assets/img/postimg.jpg differ
diff --git a/core/admin/assets/img/test-icon.png b/core/admin/assets/img/test-icon.png
new file mode 100644
index 0000000000..cd8374360e
Binary files /dev/null and b/core/admin/assets/img/test-icon.png differ
diff --git a/core/admin/assets/img/user.jpg b/core/admin/assets/img/user.jpg
new file mode 100644
index 0000000000..733c41b112
Binary files /dev/null and b/core/admin/assets/img/user.jpg differ
diff --git a/core/admin/assets/img/users.png b/core/admin/assets/img/users.png
new file mode 100644
index 0000000000..4e32e7ba99
Binary files /dev/null and b/core/admin/assets/img/users.png differ
diff --git a/core/admin/assets/js/admin-ui-temp.js b/core/admin/assets/js/admin-ui-temp.js
new file mode 100644
index 0000000000..1d0ac5cccc
--- /dev/null
+++ b/core/admin/assets/js/admin-ui-temp.js
@@ -0,0 +1,75 @@
+// # Temporary Admin UI
+
+/*global document, jQuery */
+
+(function ($) {
+ "use strict";
+
+ // UTILS
+
+ /**
+ * Allows to check contents of each element exactly
+ * @param obj
+ * @param index
+ * @param meta
+ * @param stack
+ * @returns {boolean}
+ */
+ $.expr[":"].containsExact = function (obj, index, meta, stack) {
+ return (obj.textContent || obj.innerText || $(obj).text() || "") === meta[3];
+ };
+
+
+ $(document).ready(function () {
+
+ // ## Set interactions for all menus
+ // This finds all visible '.overlay' elements and hides them upon clicking away from the element itself.
+ $("body").on('click', function (event) {
+ var $target = $(event.target);
+ if (!$target.parents().is(".overlay:visible") && !$target.is(".overlay:visible")) {
+ $("body").find(".overlay:visible").fadeOut();
+ }
+ });
+
+ // EDITOR / NOTIFICATIONS
+
+ $('.entry-content header, .entry-preview header').on('click', function () {
+ $('.entry-content, .entry-preview').removeClass('active');
+ $(this).closest('section').addClass('active');
+ });
+
+ $('.entry-title .icon-fullscreen').on('click', function (e) {
+ e.preventDefault();
+ $('body').toggleClass('fullscreen');
+ });
+
+ $('.content-list-content li').on('click', function (e) {
+ var $target = $(e.target).closest('li'),
+ $preview = $('.content-preview');
+ $('.content-list-content li').removeClass('active');
+ $target.addClass('active');
+ // *****
+ // this means a *lot* of extra gumpf is in the DOM and should really be done with AJAX when we have proper
+ // data API endpoints
+ // ideally, we need a way to bind data to views properly... backbone marionette, angular, etc
+ // *****
+ //
+ /**
+ * @todo Remove gumpf
+ */
+ $preview.find('.content-preview-content .wrapper').html($target.data('content'));
+ $preview.find('.post-controls .post-edit').attr('href', '/ghost/editor/' + $target.data('id'));
+ });
+
+ $('.options.up').on('click', function (e) {
+ e.stopPropagation();
+ $(this).next("ul").fadeToggle(200);
+ });
+
+ $('.editor-options').on('click', 'li', function (e) {
+ $('.button-save').data("state", $(this).data("title")).attr('data-state', $(this).data("title")).text($(this).text());
+ $('.editor-options .active').removeClass('active');
+ $(this).addClass('active');
+ });
+ });
+}(jQuery));
\ No newline at end of file
diff --git a/core/admin/assets/js/blog.js b/core/admin/assets/js/blog.js
new file mode 100644
index 0000000000..84a2a199af
--- /dev/null
+++ b/core/admin/assets/js/blog.js
@@ -0,0 +1,27 @@
+/*global window, history, jQuery, Showdown, CodeMirror */
+(function ($) {
+ "use strict";
+
+ $(document).ready(function () {
+
+ // Shadow on Markdown if scrolled
+ $('.content-list-content').on('scroll', function (e) {
+ if ($('.content-list-content').scrollTop() > 10) {
+ $('.content-list').addClass('scrolling');
+ } else {
+ $('.content-list').removeClass('scrolling');
+ }
+ });
+
+ // Shadow on Preview if scrolled
+ $('.content-preview-content').on('scroll', function (e) {
+ if ($('.content-preview-content').scrollTop() > 10) {
+ $('.content-preview').addClass('scrolling');
+ } else {
+ $('.content-preview').removeClass('scrolling');
+ }
+ });
+
+ });
+
+}(jQuery));
\ No newline at end of file
diff --git a/core/admin/assets/js/editor.js b/core/admin/assets/js/editor.js
new file mode 100644
index 0000000000..1a56d386e4
--- /dev/null
+++ b/core/admin/assets/js/editor.js
@@ -0,0 +1,157 @@
+// # Article Editor
+
+/*global window, document, history, jQuery, Showdown, CodeMirror, shortcut */
+(function ($, ShowDown, CodeMirror, shortcut) {
+ "use strict";
+
+ // ## Converter Initialisation
+ /**
+ * @property converter
+ * @type {ShowDown.converter}
+ */
+ // Initialise the Showdown converter for Markdown.
+ // var delay;
+ var converter = new ShowDown.converter({extensions: ['ghostdown']}),
+ editor = CodeMirror.fromTextArea(document.getElementById('entry-markdown'), {
+ mode: 'markdown',
+ tabMode: 'indent',
+ lineWrapping: true
+ });
+
+ // ## Functions
+ /**
+ * @method Update word count
+ * @todo Really not the best way to do things as it includes Markdown formatting along with words
+ * @constructor
+ */
+ // This updates the word count on the editor preview panel.
+ function updateWordCount() {
+ var wordCount = document.getElementsByClassName('entry-word-count')[0],
+ editorValue = editor.getValue();
+
+ if (editorValue.length) {
+ wordCount.innerHTML = editorValue.match(/\S+/g).length + ' words';
+ }
+ }
+
+ /**
+ * @method updatePreview
+ * @constructor
+ */
+ // This updates the editor preview panel.
+ // Currently gets called on every key press.
+ // Also trigger word count update
+ function updatePreview() {
+ var preview = document.getElementsByClassName('rendered-markdown')[0];
+ preview.innerHTML = converter.makeHtml(editor.getValue());
+
+ updateWordCount();
+ }
+
+ /**
+ * @method Save
+ * @constructor
+ */
+ // This method saves a post
+ function save() {
+ var entry = {
+ title: document.getElementById('entry-title').value,
+ markdown: editor.getValue()
+ },
+ urlSegments = window.location.pathname.split('/');
+
+ if (urlSegments[2] === 'editor' && urlSegments[3] && /^[a-zA-Z0-9]+$/.test(urlSegments[2])) {
+ entry.id = urlSegments[3];
+ $.ajax({
+ url: '/api/v0.1/posts/edit',
+ method: 'POST',
+ data: entry,
+ success: function (data) {
+ console.log('response', data);
+ },
+ error: function (error) {
+ console.log('error', error);
+ }
+ });
+ } else {
+ $.ajax({
+ url: '/api/v0.1/posts/create',
+ method: 'POST',
+ data: entry,
+ success: function (data) {
+ console.log('response', data);
+ history.pushState(data, '', '/ghost/editor/' + data.id);
+ },
+ error: function (jqXHR, status, error) {
+ var errors = JSON.parse(jqXHR.responseText);
+ console.log('FAILED', errors);
+ }
+ });
+ }
+ }
+
+ // ## Main Initialisation
+ $(document).ready(function () {
+
+ $('.entry-markdown header, .entry-preview header').click(function (e) {
+ $('.entry-markdown, .entry-preview').removeClass('active');
+ $(e.target).closest('section').addClass('active');
+ });
+
+ editor.on("change", function () {
+ //clearTimeout(delay);
+ //delay = setTimeout(updatePreview, 50);
+ updatePreview();
+ });
+
+ updatePreview();
+
+ $('.button-save').on('click', function () {
+ save();
+ });
+
+ // Sync scrolling
+ function syncScroll(e) {
+ // vars
+ var $codeViewport = $(e.target),
+ $previewViewport = $('.entry-preview-content'),
+ $codeContent = $('.CodeMirror-sizer'),
+ $previewContent = $('.rendered-markdown'),
+
+ // calc position
+ codeHeight = $codeContent.height() - $codeViewport.height(),
+ previewHeight = $previewContent.height() - $previewViewport.height(),
+ ratio = previewHeight / codeHeight,
+ previewPostition = $codeViewport.scrollTop() * ratio;
+
+ // apply new scroll
+ $previewViewport.scrollTop(previewPostition);
+
+ }
+ // TODO: Debounce
+ $('.CodeMirror-scroll').on('scroll', syncScroll);
+
+ // Shadow on Markdown if scrolled
+ $('.CodeMirror-scroll').on('scroll', function (e) {
+ if ($('.CodeMirror-scroll').scrollTop() > 10) {
+ $('.entry-markdown').addClass('scrolling');
+ } else {
+ $('.entry-markdown').removeClass('scrolling');
+ }
+ });
+ // Shadow on Preview if scrolled
+ $('.entry-preview-content').on('scroll', function (e) {
+ if ($('.entry-preview-content').scrollTop() > 10) {
+ $('.entry-preview').addClass('scrolling');
+ } else {
+ $('.entry-preview').removeClass('scrolling');
+ }
+ });
+
+ // Zen writing mode
+ shortcut.add("Alt+Shift+Z", function () {
+ $('body').toggleClass('zen');
+ });
+
+ });
+}(jQuery, Showdown, CodeMirror, shortcut));
\ No newline at end of file
diff --git a/core/admin/assets/js/settings.js b/core/admin/assets/js/settings.js
new file mode 100644
index 0000000000..8f458d93e4
--- /dev/null
+++ b/core/admin/assets/js/settings.js
@@ -0,0 +1,21 @@
+/*globals document, jQuery */
+(function ($) {
+ "use strict";
+
+ var changePage = function (e) {
+ var newPage = $(this).children('a').attr('href');
+
+ e.preventDefault();
+ $('.settings-menu .active').removeClass('active');
+ $(this).addClass('active');
+
+ $('.settings-content').fadeOut().delay(250);
+ $(newPage).fadeIn();
+
+ };
+
+ $(document).ready(function() {
+ $('.settings-menu li').on('click', changePage);
+ });
+
+}(jQuery));
\ No newline at end of file
diff --git a/core/admin/assets/js/tagui.js b/core/admin/assets/js/tagui.js
new file mode 100644
index 0000000000..2713e8f8d3
--- /dev/null
+++ b/core/admin/assets/js/tagui.js
@@ -0,0 +1,196 @@
+// ## Tag Selector UI
+
+/*jslint regexp: true */ // - would like to remove this
+/*global jQuery, document, window */
+
+(function ($) {
+ "use strict";
+
+ var suggestions,
+ categoryOffset,
+ existingTags = [ // This will be replaced by an API return.
+ 'quim',
+ 'quimtastic',
+ 'quimmy',
+ 'quimlord',
+ 'quickly',
+ 'joaquim pheonix',
+ 'quimcy jones'
+ ],
+ keys = {
+ UP: 38,
+ DOWN: 40,
+ ESC: 27,
+ ENTER: 13,
+ COMMA: 188,
+ BACKSPACE: 8
+ };
+
+ function findTerms(searchTerm, array) {
+ searchTerm = searchTerm.toUpperCase();
+ return $.map(array, function (item) {
+ var match = item.toUpperCase().indexOf(searchTerm) !== -1;
+ return match ? item : null;
+ });
+ }
+
+ function showSuggestions($target, searchTerm) {
+ suggestions.show();
+ var results = findTerms(searchTerm, existingTags),
+ pos = $target.position(),
+ styles = {
+ left: pos.left
+ },
+ maxSuggestions = 5, // Limit the suggestions number
+ results_length = results.length,
+ i,
+ suggest;
+
+ suggestions.css(styles);
+ suggestions.html("");
+
+ if (results_length < maxSuggestions) {
+ maxSuggestions = results_length;
+ }
+ for (i = 0; i < maxSuggestions; i += 1) {
+ suggestions.append("
").append(b.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},b.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){b.fn[t]=function(e){return this.on(t,e)}}),b.each(["get","post"],function(e,n){b[n]=function(e,r,i,o){return b.isFunction(r)&&(o=o||i,i=r,r=t),b.ajax({url:e,type:n,dataType:o,data:r,success:i})}}),b.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:"GET",isLocal:Nn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Dn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Mn(Mn(e,b.ajaxSettings),t):Mn(b.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){"object"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,u,l,c,p=b.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?b(f):b.event,h=b.Deferred(),g=b.Callbacks("once memory"),m=p.statusCode||{},y={},v={},x=0,T="canceled",N={readyState:0,getResponseHeader:function(e){var t;if(2===x){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===x?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return x||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return x||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>x)for(t in e)m[t]=[m[t],e[t]];else N.always(e[N.status]);return this},abort:function(e){var t=e||T;return l&&l.abort(t),k(0,t),this}};if(h.promise(N).complete=g.add,N.success=N.done,N.error=N.fail,p.url=((e||p.url||yn)+"").replace(xn,"").replace(kn,mn[1]+"//"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=b.trim(p.dataType||"*").toLowerCase().match(w)||[""],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||("http:"===r[1]?80:443))==(mn[3]||("http:"===mn[1]?80:443)))),p.data&&p.processData&&"string"!=typeof p.data&&(p.data=b.param(p.data,p.traditional)),qn(An,p,n,N),2===x)return N;u=p.global,u&&0===b.active++&&b.event.trigger("ajaxStart"),p.type=p.type.toUpperCase(),p.hasContent=!Cn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?"&":"?")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,"$1_="+vn++):o+(bn.test(o)?"&":"?")+"_="+vn++)),p.ifModified&&(b.lastModified[o]&&N.setRequestHeader("If-Modified-Since",b.lastModified[o]),b.etag[o]&&N.setRequestHeader("If-None-Match",b.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&N.setRequestHeader("Content-Type",p.contentType),N.setRequestHeader("Accept",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+("*"!==p.dataTypes[0]?", "+Dn+"; q=0.01":""):p.accepts["*"]);for(i in p.headers)N.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,N,p)===!1||2===x))return N.abort();T="abort";for(i in{success:1,error:1,complete:1})N[i](p[i]);if(l=qn(jn,p,n,N)){N.readyState=1,u&&d.trigger("ajaxSend",[N,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){N.abort("timeout")},p.timeout));try{x=1,l.send(y,k)}catch(C){if(!(2>x))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,n,r,i){var c,y,v,w,T,C=n;2!==x&&(x=2,s&&clearTimeout(s),l=t,a=i||"",N.readyState=e>0?4:0,r&&(w=_n(p,N,r)),e>=200&&300>e||304===e?(p.ifModified&&(T=N.getResponseHeader("Last-Modified"),T&&(b.lastModified[o]=T),T=N.getResponseHeader("etag"),T&&(b.etag[o]=T)),204===e?(c=!0,C="nocontent"):304===e?(c=!0,C="notmodified"):(c=Fn(p,w),C=c.state,y=c.data,v=c.error,c=!v)):(v=C,(e||!C)&&(C="error",0>e&&(e=0))),N.status=e,N.statusText=(n||C)+"",c?h.resolveWith(f,[y,C,N]):h.rejectWith(f,[N,C,v]),N.statusCode(m),m=t,u&&d.trigger(c?"ajaxSuccess":"ajaxError",[N,p,c?y:v]),g.fireWith(f,[N,C]),u&&(d.trigger("ajaxComplete",[N,p]),--b.active||b.event.trigger("ajaxStop")))}return N},getScript:function(e,n){return b.get(e,t,n,"script")},getJSON:function(e,t,n){return b.get(e,t,n,"json")}});function _n(e,n,r){var i,o,a,s,u=e.contents,l=e.dataTypes,c=e.responseFields;for(s in c)s in r&&(n[c[s]]=r[s]);while("*"===l[0])l.shift(),o===t&&(o=e.mimeType||n.getResponseHeader("Content-Type"));if(o)for(s in u)if(u[s]&&u[s].test(o)){l.unshift(s);break}if(l[0]in r)a=l[0];else{for(s in r){if(!l[0]||e.converters[s+" "+l[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==l[0]&&l.unshift(a),r[a]):t}function Fn(e,t){var n,r,i,o,a={},s=0,u=e.dataTypes.slice(),l=u[0];if(e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u[1])for(i in e.converters)a[i.toLowerCase()]=e.converters[i];for(;r=u[++s];)if("*"!==r){if("*"!==l&&l!==r){if(i=a[l+" "+r]||a["* "+r],!i)for(n in a)if(o=n.split(" "),o[1]===r&&(i=a[l+" "+o[0]]||a["* "+o[0]])){i===!0?i=a[n]:a[n]!==!0&&(r=o[0],u.splice(s--,0,r));break}if(i!==!0)if(i&&e["throws"])t=i(t);else try{t=i(t)}catch(c){return{state:"parsererror",error:i?c:"No conversion from "+l+" to "+r}}}l=r}return{state:"success",data:t}}b.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return b.globalEval(e),e}}}),b.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),b.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=o.head||b("head")[0]||o.documentElement;return{send:function(t,i){n=o.createElement("script"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,"success"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var On=[],Bn=/(=)\?(?=&|$)|\?\?/;b.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=On.pop()||b.expando+"_"+vn++;return this[e]=!0,e}}),b.ajaxPrefilter("json jsonp",function(n,r,i){var o,a,s,u=n.jsonp!==!1&&(Bn.test(n.url)?"url":"string"==typeof n.data&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Bn.test(n.data)&&"data");return u||"jsonp"===n.dataTypes[0]?(o=n.jsonpCallback=b.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,u?n[u]=n[u].replace(Bn,"$1"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?"&":"?")+n.jsonp+"="+o),n.converters["script json"]=function(){return s||b.error(o+" was not called"),s[0]},n.dataTypes[0]="json",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,On.push(o)),s&&b.isFunction(a)&&a(s[0]),s=a=t}),"script"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}b.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=b.ajaxSettings.xhr(),b.support.cors=!!Rn&&"withCredentials"in Rn,Rn=b.support.ajax=!!Rn,Rn&&b.ajaxTransport(function(n){if(!n.crossDomain||b.support.cors){var r;return{send:function(i,o){var a,s,u=n.xhr();if(n.username?u.open(n.type,n.url,n.async,n.username,n.password):u.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)u[s]=n.xhrFields[s];n.mimeType&&u.overrideMimeType&&u.overrideMimeType(n.mimeType),n.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");try{for(s in i)u.setRequestHeader(s,i[s])}catch(l){}u.send(n.hasContent&&n.data||null),r=function(e,i){var s,l,c,p;try{if(r&&(i||4===u.readyState))if(r=t,a&&(u.onreadystatechange=b.noop,$n&&delete Pn[a]),i)4!==u.readyState&&u.abort();else{p={},s=u.status,l=u.getAllResponseHeaders(),"string"==typeof u.responseText&&(p.text=u.responseText);try{c=u.statusText}catch(f){c=""}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,l)},n.async?4===u.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},b(e).unload($n)),Pn[a]=r),u.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp("^(?:([+-])=|)("+x+")([a-z%]*)$","i"),Jn=/queueHooks$/,Gn=[nr],Qn={"*":[function(e,t){var n,r,i=this.createTween(e,t),o=Yn.exec(t),a=i.cur(),s=+a||0,u=1,l=20;if(o){if(n=+o[2],r=o[3]||(b.cssNumber[e]?"":"px"),"px"!==r&&s){s=b.css(i.elem,e,!0)||n||1;do u=u||".5",s/=u,b.style(i.elem,e,s+r);while(u!==(u=i.cur()/a)&&1!==u&&--l)}i.unit=r,i.start=s,i.end=o[1]?s+(o[1]+1)*n:n}return i}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=b.now()}function Zn(e,t){b.each(t,function(t,n){var r=(Qn[t]||[]).concat(Qn["*"]),i=0,o=r.length;for(;o>i;i++)if(r[i].call(e,t,n))return})}function er(e,t,n){var r,i,o=0,a=Gn.length,s=b.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,a=0,u=l.tweens.length;for(;u>a;a++)l.tweens[a].run(o);return s.notifyWith(e,[l,o,n]),1>o&&u?n:(s.resolveWith(e,[l]),!1)},l=s.promise({elem:e,props:b.extend({},t),opts:b.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=b.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?s.resolveWith(e,[l,t]):s.rejectWith(e,[l,t]),this}}),c=l.props;for(tr(c,l.opts.specialEasing);a>o;o++)if(r=Gn[o].call(l,e,c,l.opts))return r;return Zn(l,c),b.isFunction(l.opts.start)&&l.opts.start.call(e,l),b.fx.timer(b.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function tr(e,t){var n,r,i,o,a;for(i in e)if(r=b.camelCase(i),o=t[r],n=e[i],b.isArray(n)&&(o=n[1],n=e[i]=n[0]),i!==r&&(e[r]=n,delete e[i]),a=b.cssHooks[r],a&&"expand"in a){n=a.expand(n),delete e[r];for(i in n)i in e||(e[i]=n[i],t[i]=o)}else t[r]=o}b.Animation=b.extend(er,{tweener:function(e,t){b.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,u,l,c,p,f=this,d=e.style,h={},g=[],m=e.nodeType&&nn(e);n.queue||(c=b._queueHooks(e,"fx"),null==c.unqueued&&(c.unqueued=0,p=c.empty.fire,c.empty.fire=function(){c.unqueued||p()}),c.unqueued++,f.always(function(){f.always(function(){c.unqueued--,b.queue(e,"fx").length||c.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[d.overflow,d.overflowX,d.overflowY],"inline"===b.css(e,"display")&&"none"===b.css(e,"float")&&(b.support.inlineBlockNeedsLayout&&"inline"!==un(e.nodeName)?d.zoom=1:d.display="inline-block")),n.overflow&&(d.overflow="hidden",b.support.shrinkWrapBlocks||f.always(function(){d.overflow=n.overflow[0],d.overflowX=n.overflow[1],d.overflowY=n.overflow[2]}));for(i in t)if(a=t[i],Vn.exec(a)){if(delete t[i],u=u||"toggle"===a,a===(m?"hide":"show"))continue;g.push(i)}if(o=g.length){s=b._data(e,"fxshow")||b._data(e,"fxshow",{}),"hidden"in s&&(m=s.hidden),u&&(s.hidden=!m),m?b(e).show():f.done(function(){b(e).hide()}),f.done(function(){var t;b._removeData(e,"fxshow");for(t in h)b.style(e,t,h[t])});for(i=0;o>i;i++)r=g[i],l=f.createTween(r,m?s[r]:0),h[r]=s[r]||b.style(e,r),r in s||(s[r]=l.start,m&&(l.end=l.start,l.start="width"===r||"height"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}b.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(b.cssNumber[n]?"":"px")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?b.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=b.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){b.fx.step[e.prop]?b.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[b.cssProps[e.prop]]||b.cssHooks[e.prop])?b.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},b.each(["toggle","show","hide"],function(e,t){var n=b.fn[t];b.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),b.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=b.isEmptyObject(e),o=b.speed(t,n,r),a=function(){var t=er(this,b.extend({},e),o);a.finish=function(){t.stop(!0)},(i||b._data(this,"finish"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return"string"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=null!=e&&e+"queueHooks",o=b.timers,a=b._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&b.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=b._data(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=b.timers,a=r?r.length:0;for(n.finish=!0,b.queue(this,e,[]),i&&i.cur&&i.cur.finish&&i.cur.finish.call(this),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}b.each({slideDown:ir("show"),slideUp:ir("hide"),slideToggle:ir("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){b.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),b.speed=function(e,t,n){var r=e&&"object"==typeof e?b.extend({},e):{complete:n||!n&&t||b.isFunction(e)&&e,duration:e,easing:n&&t||t&&!b.isFunction(t)&&t};return r.duration=b.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in b.fx.speeds?b.fx.speeds[r.duration]:b.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){b.isFunction(r.old)&&r.old.call(this),r.queue&&b.dequeue(this,r.queue)},r},b.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},b.timers=[],b.fx=rr.prototype.init,b.fx.tick=function(){var e,n=b.timers,r=0;for(Xn=b.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||b.fx.stop(),Xn=t},b.fx.timer=function(e){e()&&b.timers.push(e)&&b.fx.start()},b.fx.interval=13,b.fx.start=function(){Un||(Un=setInterval(b.fx.tick,b.fx.interval))},b.fx.stop=function(){clearInterval(Un),Un=null},b.fx.speeds={slow:600,fast:200,_default:400},b.fx.step={},b.expr&&b.expr.filters&&(b.expr.filters.animated=function(e){return b.grep(b.timers,function(t){return e===t.elem}).length}),b.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){b.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,b.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},b.offset={setOffset:function(e,t,n){var r=b.css(e,"position");"static"===r&&(e.style.position="relative");var i=b(e),o=i.offset(),a=b.css(e,"top"),s=b.css(e,"left"),u=("absolute"===r||"fixed"===r)&&b.inArray("auto",[a,s])>-1,l={},c={},p,f;u?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),b.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(l.top=t.top-o.top+p),null!=t.left&&(l.left=t.left-o.left+f),"using"in t?t.using.call(e,l):i.css(l)}},b.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return"fixed"===b.css(r,"position")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),b.nodeName(e[0],"html")||(n=e.offset()),n.top+=b.css(e[0],"borderTopWidth",!0),n.left+=b.css(e[0],"borderLeftWidth",!0)),{top:t.top-n.top-b.css(r,"marginTop",!0),left:t.left-n.left-b.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||o.documentElement;while(e&&!b.nodeName(e,"html")&&"static"===b.css(e,"position"))e=e.offsetParent;return e||o.documentElement})}}),b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);b.fn[e]=function(i){return b.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?b(a).scrollLeft():o,r?o:b(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return b.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}b.each({Height:"height",Width:"width"},function(e,n){b.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){b.fn[i]=function(i,o){var a=arguments.length&&(r||"boolean"!=typeof i),s=r||(i===!0||o===!0?"margin":"border");return b.access(this,function(n,r,i){var o;return b.isWindow(n)?n.document.documentElement["client"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body["scroll"+e],o["scroll"+e],n.body["offset"+e],o["offset"+e],o["client"+e])):i===t?b.css(n,r,s):b.style(n,r,i,s)},n,a?i:t,a,null)}})}),e.jQuery=e.$=b,"function"==typeof define&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return b})})(window);
\ No newline at end of file
diff --git a/core/admin/assets/lib/shortcuts.js b/core/admin/assets/lib/shortcuts.js
new file mode 100644
index 0000000000..1704005d82
--- /dev/null
+++ b/core/admin/assets/lib/shortcuts.js
@@ -0,0 +1,223 @@
+/**
+ * http://www.openjs.com/scripts/events/keyboard_shortcuts/
+ * Version : 2.01.B
+ * By Binny V A
+ * License : BSD
+ */
+shortcut = {
+ 'all_shortcuts':{},//All the shortcuts are stored in this array
+ 'add': function(shortcut_combination,callback,opt) {
+ //Provide a set of default options
+ var default_options = {
+ 'type':'keydown',
+ 'propagate':false,
+ 'disable_in_input':false,
+ 'target':document,
+ 'keycode':false
+ }
+ if(!opt) opt = default_options;
+ else {
+ for(var dfo in default_options) {
+ if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
+ }
+ }
+
+ var ele = opt.target;
+ if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
+ var ths = this;
+ shortcut_combination = shortcut_combination.toLowerCase();
+
+ //The function to be called at keypress
+ var func = function(e) {
+ e = e || window.event;
+
+ if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
+ var element;
+ if(e.target) element=e.target;
+ else if(e.srcElement) element=e.srcElement;
+ if(element.nodeType==3) element=element.parentNode;
+
+ if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
+ }
+
+ //Find Which key is pressed
+ if (e.keyCode) code = e.keyCode;
+ else if (e.which) code = e.which;
+ var character = String.fromCharCode(code).toLowerCase();
+
+ if(code == 188) character=","; //If the user presses , when the type is onkeydown
+ if(code == 190) character="."; //If the user presses , when the type is onkeydown
+
+ var keys = shortcut_combination.split("+");
+ //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
+ var kp = 0;
+
+ //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
+ var shift_nums = {
+ "`":"~",
+ "1":"!",
+ "2":"@",
+ "3":"#",
+ "4":"$",
+ "5":"%",
+ "6":"^",
+ "7":"&",
+ "8":"*",
+ "9":"(",
+ "0":")",
+ "-":"_",
+ "=":"+",
+ ";":":",
+ "'":"\"",
+ ",":"<",
+ ".":">",
+ "/":"?",
+ "\\":"|"
+ }
+ //Special Keys - and their codes
+ var special_keys = {
+ 'esc':27,
+ 'escape':27,
+ 'tab':9,
+ 'space':32,
+ 'return':13,
+ 'enter':13,
+ 'backspace':8,
+
+ 'scrolllock':145,
+ 'scroll_lock':145,
+ 'scroll':145,
+ 'capslock':20,
+ 'caps_lock':20,
+ 'caps':20,
+ 'numlock':144,
+ 'num_lock':144,
+ 'num':144,
+
+ 'pause':19,
+ 'break':19,
+
+ 'insert':45,
+ 'home':36,
+ 'delete':46,
+ 'end':35,
+
+ 'pageup':33,
+ 'page_up':33,
+ 'pu':33,
+
+ 'pagedown':34,
+ 'page_down':34,
+ 'pd':34,
+
+ 'left':37,
+ 'up':38,
+ 'right':39,
+ 'down':40,
+
+ 'f1':112,
+ 'f2':113,
+ 'f3':114,
+ 'f4':115,
+ 'f5':116,
+ 'f6':117,
+ 'f7':118,
+ 'f8':119,
+ 'f9':120,
+ 'f10':121,
+ 'f11':122,
+ 'f12':123
+ }
+
+ var modifiers = {
+ shift: { wanted:false, pressed:false},
+ ctrl : { wanted:false, pressed:false},
+ alt : { wanted:false, pressed:false},
+ meta : { wanted:false, pressed:false} //Meta is Mac specific
+ };
+
+ if(e.ctrlKey) modifiers.ctrl.pressed = true;
+ if(e.shiftKey) modifiers.shift.pressed = true;
+ if(e.altKey) modifiers.alt.pressed = true;
+ if(e.metaKey) modifiers.meta.pressed = true;
+
+ for(var i=0; k=keys[i],i 1) { //If it is a special key
+ if(special_keys[k] == code) kp++;
+
+ } else if(opt['keycode']) {
+ if(opt['keycode'] == code) kp++;
+
+ } else { //The special keys did not match
+ if(character == k) kp++;
+ else {
+ if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
+ character = shift_nums[character];
+ if(character == k) kp++;
+ }
+ }
+ }
+ }
+
+ if(kp == keys.length &&
+ modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
+ modifiers.shift.pressed == modifiers.shift.wanted &&
+ modifiers.alt.pressed == modifiers.alt.wanted &&
+ modifiers.meta.pressed == modifiers.meta.wanted) {
+ callback(e);
+
+ if(!opt['propagate']) { //Stop the event
+ //e.cancelBubble is supported by IE - this will kill the bubbling process.
+ e.cancelBubble = true;
+ e.returnValue = false;
+
+ //e.stopPropagation works in Firefox.
+ if (e.stopPropagation) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ return false;
+ }
+ }
+ }
+ this.all_shortcuts[shortcut_combination] = {
+ 'callback':func,
+ 'target':ele,
+ 'event': opt['type']
+ };
+ //Attach the function with the event
+ if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
+ else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
+ else ele['on'+opt['type']] = func;
+ },
+
+ //Remove the shortcut - just specify the shortcut and I will remove the binding
+ 'remove':function(shortcut_combination) {
+ shortcut_combination = shortcut_combination.toLowerCase();
+ var binding = this.all_shortcuts[shortcut_combination];
+ delete(this.all_shortcuts[shortcut_combination])
+ if(!binding) return;
+ var type = binding['event'];
+ var ele = binding['target'];
+ var callback = binding['callback'];
+
+ if(ele.detachEvent) ele.detachEvent('on'+type, callback);
+ else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
+ else ele['on'+type] = false;
+ }
+}
\ No newline at end of file
diff --git a/core/admin/assets/lib/showdown/extensions/ghostdown.js b/core/admin/assets/lib/showdown/extensions/ghostdown.js
new file mode 100644
index 0000000000..67f27107f2
--- /dev/null
+++ b/core/admin/assets/lib/showdown/extensions/ghostdown.js
@@ -0,0 +1,22 @@
+(function () {
+ var ghostdown = function (converter) {
+ return [
+ // [image] syntax
+ {
+ type: 'lang',
+ filter: function (source) {
+ return source.replace(/\n+!image\[([\d\w\s]*)\]/gi, function (match, alt, a) {
+ return 'Image Upload
Add image of ' + alt + '
URLWebcam';
+ });
+ }
+ }
+ ];
+ };
+
+ // Client-side export
+ if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) {
+ window.Showdown.extensions.ghostdown = ghostdown;
+ }
+ // Server-side export
+ if (typeof module !== 'undefined') module.exports = ghostdown;
+}());
\ No newline at end of file
diff --git a/core/admin/assets/lib/showdown/showdown.js b/core/admin/assets/lib/showdown/showdown.js
new file mode 100644
index 0000000000..65ee602359
--- /dev/null
+++ b/core/admin/assets/lib/showdown/showdown.js
@@ -0,0 +1,62 @@
+//
+// showdown.js -- A javascript port of Markdown.
+//
+// Copyright (c) 2007 John Fraser.
+//
+// Original Markdown Copyright (c) 2004-2005 John Gruber
+//
+//
+// Redistributable under a BSD-style open source license.
+// See license.txt for more information.
+//
+// The full source distribution is at:
+//
+// A A L
+// T C A
+// T K B
+//
+//
+//
+//
+// Wherever possible, Showdown is a straight, line-by-line port
+// of the Perl version of Markdown.
+//
+// This is not a normal parser design; it's basically just a
+// series of string substitutions. It's hard to read and
+// maintain this way, but keeping Showdown close to the original
+// design makes it easier to port new features.
+//
+// More importantly, Showdown behaves like markdown.pl in most
+// edge cases. So web applications can do client-side preview
+// in Javascript, and then build identical HTML on the server.
+//
+// This port needs the new RegExp functionality of ECMA 262,
+// 3rd Edition (i.e. Javascript 1.5). Most modern web browsers
+// should do fine. Even with the new regular expression features,
+// We do a lot of work to emulate Perl's regex functionality.
+// The tricky changes in this file mostly have the "attacklab:"
+// label. Major or self-explanatory changes don't.
+//
+// Smart diff tools like Araxis Merge will be able to match up
+// this file with markdown.pl in a useful way. A little tweaking
+// helps: in a copy of markdown.pl, replace "#" with "//" and
+// replace "$text" with "text". Be sure to ignore whitespace
+// and line endings.
+//
+//
+// Showdown usage:
+//
+// var text = "Markdown *rocks*.";
+//
+// var converter = new Showdown.converter();
+// var html = converter.makeHtml(text);
+//
+// alert(html);
+//
+// Note: move the sample code to the bottom of this
+// file before uncommenting it.
+//
+//
+// Showdown namespace
+//
+var Showdown={extensions:{}},forEach=Showdown.forEach=function(a,b){if(typeof a.forEach=="function")a.forEach(b);else{var c,d=a.length;for(c=0;c?[ \t]*\n?[ \t]*(?:(\n*)["(](.+?)[")][ \t]*)?(?:\n+|(?=~0))/gm,function(a,d,e,f,g){return d=d.toLowerCase(),b[d]=G(e),f?f+g:(g&&(c[d]=g.replace(/"/g,""")),"")}),a=a.replace(/~0/,""),a},m=function(a){a=a.replace(/\n/g,"\n\n");var b="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del|style|section|header|footer|nav|article|aside",c="p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside";return a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del)\b[^\r]*?\n<\/\2>[ \t]*(?=\n+))/gm,n),a=a.replace(/^(<(p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|style|section|header|footer|nav|article|aside)\b[^\r]*?<\/\2>[ \t]*(?=\n+)\n)/gm,n),a=a.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,n),a=a.replace(/(\n\n[ ]{0,3}[ \t]*(?=\n{2,}))/g,n),a=a.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,n),a=a.replace(/\n\n/g,"\n"),a},n=function(a,b){var c=b;return c=c.replace(/\n\n/g,"\n"),c=c.replace(/^\n/,""),c=c.replace(/\n+$/g,""),c="\n\n~K"+(d.push(c)-1)+"K\n\n",c},o=function(a){a=v(a);var b=A("");return a=a.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm,b),a=a.replace(/^[ ]{0,2}([ ]?\_[ ]?){3,}[ \t]*$/gm,b),a=x(a),a=y(a),a=E(a),a=m(a),a=F(a),a},p=function(a){return a=B(a),a=q(a),a=H(a),a=t(a),a=r(a),a=I(a),a=G(a),a=D(a),a=a.replace(/ +\n/g," \n"),a},q=function(a){var b=/(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|)/gi;return a=a.replace(b,function(a){var b=a.replace(/(.)<\/?code>(?=.)/g,"$1`");return b=N(b,"\\`*_"),b}),a},r=function(a){return a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,s),a=a.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,s),a=a.replace(/(\[([^\[\]]+)\])()()()()()/g,s),a},s=function(a,d,e,f,g,h,i,j){j==undefined&&(j="");var k=d,l=e,m=f.toLowerCase(),n=g,o=j;if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(b[m]!=undefined)n=b[m],c[m]!=undefined&&(o=c[m]);else{if(!(k.search(/\(\s*\)$/m)>-1))return k;n=""}}n=N(n,"*_");var p='"+l+"",p},t=function(a){return a=a.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g,u),a=a.replace(/(!\[(.*?)\]\s?\([ \t]*()(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,u),a},u=function(a,d,e,f,g,h,i,j){var k=d,l=e,m=f.toLowerCase(),n=g,o=j;o||(o="");if(n==""){m==""&&(m=l.toLowerCase().replace(/ ?\n/g," ")),n="#"+m;if(b[m]==undefined)return k;n=b[m],c[m]!=undefined&&(o=c[m])}l=l.replace(/"/g,"""),n=N(n,"*_");var p='",p},v=function(a){function b(a){return a.replace(/[^\w]/g,"").toLowerCase()}return a=a.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,function(a,c){return A('
+ *
+ * Extend this object into your markup.
+ *
+ */
+.dictionary-style {
+ @include definition-list-style(dictionary-style);
+}
+
+
+// $S t a t s T a b
+// --------------------------------------------------------------------------
+
+/**
+ * Stats Tab Markup
+ *
+