0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-10 23:36:14 -05:00

Improving the showdown extensions

fixes #2381

- renamed the ghost extensions
- added new html tests
This commit is contained in:
Hannah Wolfe 2014-03-20 13:52:16 +00:00
parent 3ad4c27968
commit c02fd70c63
8 changed files with 93 additions and 67 deletions

View file

@ -460,8 +460,8 @@ var path = require('path'),
'bower_components/showdown/src/showdown.js',
'bower_components/validator-js/validator.js',
'core/client/assets/lib/showdown/extensions/ghostdown.js',
'core/shared/lib/showdown/extensions/github.js',
'core/shared/lib/showdown/extensions/ghostimagepreview.js',
'core/shared/lib/showdown/extensions/ghostgfm.js',
// ToDo: Remove or replace
'core/client/assets/vendor/shortcuts.js',
@ -522,8 +522,8 @@ var path = require('path'),
'bower_components/showdown/src/showdown.js',
'bower_components/validator-js/validator.js',
'core/client/assets/lib/showdown/extensions/ghostdown.js',
'core/shared/lib/showdown/extensions/github.js',
'core/shared/lib/showdown/extensions/ghostimagepreview.js',
'core/shared/lib/showdown/extensions/ghostgfm.js',
// ToDo: Remove or replace
'core/client/assets/vendor/shortcuts.js',

View file

@ -9,7 +9,7 @@
'use strict';
var HTMLPreview = function (markdown, uploadMgr) {
var converter = new Showdown.converter({extensions: ['ghostdown', 'github']}),
var converter = new Showdown.converter({extensions: ['ghostimagepreview', 'ghostgfm']}),
preview = document.getElementsByClassName('rendered-markdown')[0],
update;

View file

@ -3,8 +3,8 @@ var _ = require('lodash'),
when = require('when'),
errors = require('../errorHandling'),
Showdown = require('showdown'),
github = require('../../shared/lib/showdown/extensions/github'),
converter = new Showdown.converter({extensions: [github]}),
ghostgfm = require('../../shared/lib/showdown/extensions/ghostgfm'),
converter = new Showdown.converter({extensions: [ghostgfm]}),
User = require('./user').User,
Tag = require('./tag').Tag,
Tags = require('./tag').Tags,

View file

@ -1,10 +1,16 @@
/* jshint node:true, browser:true */
// Ghost GFM
// Taken and extended from the Showdown Github Extension (WIP)
// Makes a number of pre and post-processing changes to the way markdown is handled
//
// Github Extension (WIP)
// ~~strike-through~~ -> <del>strike-through</del>
//
// ~~strike-through~~ -> <del>strike-through</del> (Pre)
// GFM newlines & underscores (Pre)
// 4 or more underscores (Pre)
// autolinking / custom image handling (Post)
(function () {
var github = function (converter) {
var ghostgfm = function () {
return [
{
// strike-through
@ -73,6 +79,17 @@
return text;
}
},
// 4 or more inline underscores e.g. Ghost rocks my _____!
{
type: 'lang',
filter: function (text) {
return text.replace(/([^_\n\r])(_{4,})/g, function (match, prefix, underscores) {
return prefix + underscores.replace(/_/g, '&#95;');
});
}
},
{
// GFM autolinking & custom image handling, happens AFTER showdown
type : 'html',
@ -131,7 +148,11 @@
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) { window.Showdown.extensions.github = github; }
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) {
window.Showdown.extensions.ghostgfm = ghostgfm;
}
// Server-side export
if (typeof module !== 'undefined') module.exports = github;
if (typeof module !== 'undefined') {
module.exports = ghostgfm;
}
}());

View file

@ -1,7 +1,15 @@
/* jshint node:true, browser:true */
// Ghost Image Preview
//
// Manages the conversion of image markdown `![]()` from markdown into the HTML image preview
// This provides a dropzone and other interface elements for adding images
// Is only used in the admin client.
var Ghost = Ghost || {};
(function () {
var ghostdown = function () {
var ghostimagepreview = function () {
return [
// ![] image syntax
{
@ -33,26 +41,16 @@ var Ghost = Ghost || {};
return output;
});
}
},
// 4 or more inline underscores e.g. Ghost rocks my _____!
{
type: 'lang',
filter: function (text) {
return text.replace(/([^_\n\r])(_{4,})/g, function (match, prefix, underscores) {
return prefix + underscores.replace(/_/g, '&#95;');
});
}
}
];
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) {
window.Showdown.extensions.ghostdown = ghostdown;
window.Showdown.extensions.ghostimagepreview = ghostimagepreview;
}
// Server-side export
if (typeof module !== 'undefined') {
module.exports = ghostdown;
module.exports = ghostimagepreview;
}
}());

View file

@ -5,14 +5,15 @@
*/
/*globals describe, it */
var testUtils = require('../utils'),
should = require('should'),
var testUtils = require('../utils'),
should = require('should'),
// Stuff we are testing
Showdown = require('showdown'),
github = require('../../shared/lib/showdown/extensions/github'),
ghostdown = require('../../client/assets/lib/showdown/extensions/ghostdown'),
converter = new Showdown.converter({extensions: [ghostdown, github]});
Showdown = require('showdown'),
ghostgfm = require('../../shared/lib/showdown/extensions/ghostgfm'),
ghostimagepreview = require('../../shared/lib/showdown/extensions/ghostimagepreview'),
converter = new Showdown.converter({extensions: [ghostimagepreview, ghostgfm]});
describe("Showdown client side converter", function () {
/*jslint regexp: true */
@ -107,7 +108,7 @@ describe("Showdown client side converter", function () {
it("should turn newlines into br tags in simple cases", function () {
var testPhrases = [
{input: "fizz\nbuzz", output: /^<p>fizz <br \/>\nbuzz<\/p>$/},
{input: "Hello world\nIt's a fine day", output: /^<p>Hello world <br \/>\nIt\'s a fine day<\/p>$/},
{input: "Hello world\nIt is a fine day", output: /^<p>Hello world <br \/>\nIt is a fine day<\/p>$/},
{input: "\"first\nsecond", output: /^<p>\"first <br \/>\nsecond<\/p>$/},
{input: "\'first\nsecond", output: /^<p>\'first <br \/>\nsecond<\/p>$/}
],
@ -122,7 +123,7 @@ describe("Showdown client side converter", function () {
it("should convert newlines in all groups", function () {
var testPhrases = [
{input: "ruby\npython\nerlang", output: /^<p>ruby <br \/>\npython <br \/>\nerlang<\/p>$/},
{input: "Hello world\nIt's a fine day\nout", output: /^<p>Hello world <br \/>\nIt\'s a fine day <br \/>\nout<\/p>$/}
{input: "Hello world\nIt is a fine day\nout", output: /^<p>Hello world <br \/>\nIt is a fine day <br \/>\nout<\/p>$/}
],
processedMarkup;
@ -134,10 +135,13 @@ describe("Showdown client side converter", function () {
it("should convert newlines in even long groups", function () {
var testPhrases = [
{input: "ruby\npython\nerlang\ngo", output: /^<p>ruby <br \/>\npython <br \/>\nerlang <br \/>\ngo<\/p>$/},
{
input: "Hello world\nIt's a fine day\noutside\nthe window",
output: /^<p>Hello world <br \/>\nIt\'s a fine day <br \/>\noutside <br \/>\nthe window<\/p>$/
input: "ruby\npython\nerlang\ngo",
output: /^<p>ruby <br \/>\npython <br \/>\nerlang <br \/>\ngo<\/p>$/
},
{
input: "Hello world\nIt is a fine day\noutside\nthe window",
output: /^<p>Hello world <br \/>\nIt is a fine day <br \/>\noutside <br \/>\nthe window<\/p>$/
}
],
processedMarkup;
@ -150,8 +154,14 @@ describe("Showdown client side converter", function () {
it("should not convert newlines in lists", function () {
var testPhrases = [
{input: "#fizz\n# buzz\n### baz", output: /^<h1 id="fizz">fizz<\/h1>\n\n<h1 id="buzz">buzz<\/h1>\n\n<h3 id="baz">baz<\/h3>$/},
{input: "* foo\n* bar", output: /^<ul>\n<li>foo<\/li>\n<li>bar<\/li>\n<\/ul>$/}
{
input: "#fizz\n# buzz\n### baz",
output: /^<h1 id="fizz">fizz<\/h1>\n\n<h1 id="buzz">buzz<\/h1>\n\n<h3 id="baz">baz<\/h3>$/
},
{
input: "* foo\n* bar",
output: /^<ul>\n<li>foo<\/li>\n<li>bar<\/li>\n<\/ul>$/
}
],
processedMarkup;

View file

@ -4,12 +4,11 @@
*/
/*globals describe, it */
var testUtils = require('../utils'),
should = require('should'),
var testUtils = require('../utils'),
should = require('should'),
// Stuff we are testing
ghPath = "../../shared/lib/showdown/extensions/github.js",
github = require(ghPath);
ghostgfm = require('../../shared/lib/showdown/extensions/ghostgfm');
function _ExecuteExtension(ext, text) {
if (ext.regex) {
@ -21,20 +20,20 @@ function _ExecuteExtension(ext, text) {
}
function _ConvertPhrase(testPhrase) {
return github().reduce(function (text, ext) {
return ghostgfm().reduce(function (text, ext) {
return _ExecuteExtension(ext, text);
}, testPhrase);
}
describe("Github showdown extensions", function () {
describe("Ghost GFM showdown extension", function () {
/*jslint regexp: true */
it("should export an array of methods for processing", function () {
github.should.be.a.function;
github().should.be.an.Array;
ghostgfm.should.be.a.function;
ghostgfm().should.be.an.Array;
github().forEach(function (processor) {
ghostgfm().forEach(function (processor) {
processor.should.be.an.Object;
processor.should.have.property("type");
processor.type.should.be.a.String;
@ -50,6 +49,14 @@ describe("Github showdown extensions", function () {
processedMarkup.should.match(testPhrase.output);
});
it("should allow 4 underscores", function () {
var testPhrase = {input: 'Ghost ____', output: /Ghost\s(?:&#95;){4}$/},
processedMarkup = _ConvertPhrase(testPhrase.input);
processedMarkup.should.match(testPhrase.output);
});
it("should auto-link URL in text with markdown syntax", function () {
var testPhrases = [
{

View file

@ -6,21 +6,20 @@
*/
/*globals describe, it */
var testUtils = require('../utils'),
should = require('should'),
var testUtils = require('../utils'),
should = require('should'),
// Stuff we are testing
gdPath = "../../client/assets/lib/showdown/extensions/ghostdown.js",
ghostdown = require(gdPath);
ghostimagepreview = require('../../shared/lib/showdown/extensions/ghostimagepreview');
describe("Ghostdown showdown extensions", function () {
describe("Ghost Image Preview showdown extension", function () {
it("should export an array of methods for processing", function () {
ghostdown.should.be.a.function;
ghostdown().should.be.an.instanceof(Array);
ghostimagepreview.should.be.a.function;
ghostimagepreview().should.be.an.instanceof(Array);
ghostdown().forEach(function (processor) {
ghostimagepreview().forEach(function (processor) {
processor.should.be.an.Object;
processor.should.have.property("type");
processor.should.have.property("filter");
@ -46,7 +45,7 @@ describe("Ghostdown showdown extensions", function () {
]
.forEach(function (imageMarkup) {
var processedMarkup =
ghostdown().reduce(function (prev, processor) {
ghostimagepreview().reduce(function (prev, processor) {
return processor.filter(prev);
}, imageMarkup);
@ -55,15 +54,6 @@ describe("Ghostdown showdown extensions", function () {
});
});
it("should allow 4 underscores", function () {
var processedMarkup =
ghostdown().reduce(function (prev, processor) {
return processor.filter(prev);
}, "Ghost ____");
processedMarkup.should.match(/Ghost\s(?:&#95;){4}$/);
});
it("should correctly include an image", function () {
[
"![image and another,/ image](http://dsurl.stuff)",
@ -75,7 +65,7 @@ describe("Ghostdown showdown extensions", function () {
]
.forEach(function (imageMarkup) {
var processedMarkup =
ghostdown().reduce(function (prev, processor) {
ghostimagepreview().reduce(function (prev, processor) {
return processor.filter(prev);
}, imageMarkup);