Merge pull request #920 from ErisDS/0.3.1-wip-markdown

0.3.1 wip markdown
This commit is contained in:
Hannah Wolfe 2013-09-27 04:30:23 -07:00
commit 11296c0064
5 changed files with 75 additions and 19 deletions

View File

@ -12,7 +12,7 @@ var fixtures = {
"title": "Welcome to Ghost", "title": "Welcome to Ghost",
"slug": "welcome-to-ghost", "slug": "welcome-to-ghost",
"markdown": "You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!\n\n## Getting Started\n\nWriting in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use *formatting* shortcuts to style your content. For example, a list:\n\n* Item number one\n* Item number two\n * A nested item\n* A final item\n\nor with numbers!\n\n1. Remember to buy some milk\n2. Drink the milk\n3. Tweet that I remembered to buy the milk, and drank it\n\n### Links\n\nWant to link to a source? No problem. If you paste in url, like http://ghost.org - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to [the Ghost website](http://ghost.org). Neat.\n\n### What about Images?\n\nImages work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:\n\n![The Ghost Logo](http://tryghost.org/ghost.png)\n\nNot sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:\n\n![A bowl of bananas]\n\n\n### Quoting\n\nSometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.\n\n> Wisdomous - it's definitely a word.\n\n### Working with Code\n\nGot a streak of geek? We've got you covered there, too. You can write inline `<code>` blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.\n\n .awesome-thing {\n display: block;\n width: 100%;\n }\n\n### Ready for a Break? \n\nThrow 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.\n\n---\n\n### Advanced Usage\n\nThere's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.\n\n<input type=\"text\" placeholder=\"I'm an input field!\" />\n\nThat should be enough to get you started. Have fun - and let us know what you think :)", "markdown": "You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!\n\n## Getting Started\n\nWriting in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use *formatting* shortcuts to style your content. For example, a list:\n\n* Item number one\n* Item number two\n * A nested item\n* A final item\n\nor with numbers!\n\n1. Remember to buy some milk\n2. Drink the milk\n3. Tweet that I remembered to buy the milk, and drank it\n\n### Links\n\nWant to link to a source? No problem. If you paste in url, like http://ghost.org - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to [the Ghost website](http://ghost.org). Neat.\n\n### What about Images?\n\nImages work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:\n\n![The Ghost Logo](http://tryghost.org/ghost.png)\n\nNot sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:\n\n![A bowl of bananas]\n\n\n### Quoting\n\nSometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.\n\n> Wisdomous - it's definitely a word.\n\n### Working with Code\n\nGot a streak of geek? We've got you covered there, too. You can write inline `<code>` blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.\n\n .awesome-thing {\n display: block;\n width: 100%;\n }\n\n### Ready for a Break? \n\nThrow 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.\n\n---\n\n### Advanced Usage\n\nThere's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.\n\n<input type=\"text\" placeholder=\"I'm an input field!\" />\n\nThat should be enough to get you started. Have fun - and let us know what you think :)",
"html": "<p>You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!</p>\n\n<h2 id=\"gettingstarted\">Getting Started</h2>\n\n<p>Writing in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use <em>formatting</em> shortcuts to style your content. For example, a list:</p>\n\n<ul>\n<li>Item number one</li>\n<li>Item number two\n<ul><li>A nested item</li></ul></li>\n<li>A final item</li>\n</ul>\n\n<p>or with numbers!</p>\n\n<ol>\n<li>Remember to buy some milk </li>\n<li>Drink the milk </li>\n<li>Tweet that I remembered to buy the milk, and drank it</li>\n</ol>\n\n<h3 id=\"links\">Links</h3>\n\n<p>Want to link to a source? No problem. If you paste in url, like <a href='http://ghost.org'>http://ghost.org</a> - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to <a href=\"http://ghost.org\">the Ghost website</a>. Neat.</p>\n\n<h3 id=\"whataboutimages\">What about Images?</h3>\n\n<p>Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:</p>\n\n<p><img src=\"http://tryghost.org/ghost.png\" alt=\"The Ghost Logo\" /></p>\n\n<p>Not sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:</p>\n\n<p><img src=\"undefined\" alt=\"A bowl of bananas\" /></p>\n\n<h3 id=\"quoting\">Quoting</h3>\n\n<p>Sometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.</p>\n\n<blockquote>\n <p>Wisdomous - it's definitely a word.</p>\n</blockquote>\n\n<h3 id=\"workingwithcode\">Working with Code</h3>\n\n<p>Got a streak of geek? We've got you covered there, too. You can write inline <code>&lt;code&gt;</code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.</p>\n\n<pre><code>.awesome-thing {\n display: block;\n width: 100%;\n}\n</code></pre>\n\n<h3 id=\"readyforabreak\">Ready for a Break?</h3>\n\n<p>Throw 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.</p>\n\n<hr />\n\n<h3 id=\"advancedusage\">Advanced Usage</h3>\n\n<p>There's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.</p>\n\n<p><input type=\"text\" placeholder=\"I'm an input field!\" /></p>\n\n<p>That should be enough to get you started. Have fun - and let us know what you think :)</p>", "html": "<p>You're in! Nice. We've put together a little post to introduce you to the Ghost editor and get you started. Go ahead and edit this post to get going and learn how it all works!</p>\n\n<h2 id=\"gettingstarted\">Getting Started</h2>\n\n<p>Writing in markdown is really easy. In the left hand panel of Ghost, you simply write as you normally would. Where appropriate, you can use <em>formatting</em> shortcuts to style your content. For example, a list:</p>\n\n<ul>\n<li>Item number one</li>\n<li>Item number two\n<ul><li>A nested item</li></ul></li>\n<li>A final item</li>\n</ul>\n\n<p>or with numbers!</p>\n\n<ol>\n<li>Remember to buy some milk </li>\n<li>Drink the milk </li>\n<li>Tweet that I remembered to buy the milk, and drank it</li>\n</ol>\n\n<h3 id=\"links\">Links</h3>\n\n<p>Want to link to a source? No problem. If you paste in url, like <a href='http://ghost.org'>http://ghost.org</a> - it'll automatically be linked up. But if you want to customise your anchor text, you can do that too! Here's a link to <a href=\"http://ghost.org\">the Ghost website</a>. Neat.</p>\n\n<h3 id=\"whataboutimages\">What about Images?</h3>\n\n<p>Images work too! Already know the URL of the image you want to include in your article? Simply paste it in like this to make it show up:</p>\n\n<p><img src=\"http://tryghost.org/ghost.png\" alt=\"The Ghost Logo\" /></p>\n\n<p>Not sure which image you want to use yet? That's ok too. Leave yourself a descriptive placeholder and keep writing. Come back later and drag and drop the image in to upload:</p>\n\n<h3 id=\"quoting\">Quoting</h3>\n\n<p>Sometimes a link isn't enough, you want to quote someone on what they've said. It was probably very wisdomous. Is wisdomous a word? Find out in a future release when we introduce spellcheck! For now - it's definitely a word.</p>\n\n<blockquote>\n <p>Wisdomous - it's definitely a word.</p>\n</blockquote>\n\n<h3 id=\"workingwithcode\">Working with Code</h3>\n\n<p>Got a streak of geek? We've got you covered there, too. You can write inline <code>&lt;code&gt;</code> blocks really easily with back ticks. Want to show off something more comprehensive? 4 spaces of indentation gets you there.</p>\n\n<pre><code>.awesome-thing {\n display: block;\n width: 100%;\n}\n</code></pre>\n\n<h3 id=\"readyforabreak\">Ready for a Break?</h3>\n\n<p>Throw 3 or more dashes down on any new line and you've got yourself a fancy new divider. Aw yeah.</p>\n\n<hr />\n\n<h3 id=\"advancedusage\">Advanced Usage</h3>\n\n<p>There's one fantastic secret about Markdown. If you want, you can write plain old HTML and it'll still work! Very flexible.</p>\n\n<p><input type=\"text\" placeholder=\"I'm an input field!\" /></p>\n\n<p>That should be enough to get you started. Have fun - and let us know what you think :)</p>",
"image": null, "image": null,
"featured": false, "featured": false,
"page": false, "page": false,

View File

@ -16,11 +16,10 @@
} }
}, },
{ {
// GFM newline and underscore modifications // GFM newline and underscore modifications, happen BEFORE showdown
type : 'lang', type : 'lang',
filter : function (text) { filter : function (text) {
var extractions = {}, var preExtractions = {},
imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim,
hashID = 0; hashID = 0;
function hashId() { function hashId() {
@ -30,15 +29,10 @@
// Extract pre blocks // Extract pre blocks
text = text.replace(/<pre>[\s\S]*?<\/pre>/gim, function (x) { text = text.replace(/<pre>[\s\S]*?<\/pre>/gim, function (x) {
var hash = hashId(); var hash = hashId();
extractions[hash] = x; preExtractions[hash] = x;
return "{gfm-js-extract-pre-" + hash + "}"; return "{gfm-js-extract-pre-" + hash + "}";
}, 'm'); }, 'm');
// better URL support, but no title support
text = text.replace(imageMarkdownRegex, function (match, key, alt, src) {
return '<img src="' + src + '" alt="' + alt + '" />';
});
//prevent foo_bar and foo_bar_baz from ending up with an italic word in the middle //prevent foo_bar and foo_bar_baz from ending up with an italic word in the middle
text = text.replace(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/gm, function (x) { text = text.replace(/(^(?! {4}|\t)\w+_\w+_\w[\w_]*)/gm, function (x) {
return x.replace(/_/gm, '\\_'); return x.replace(/_/gm, '\\_');
@ -49,8 +43,9 @@
return x.match(/\n{2}/) ? x : x.trim() + " \n"; return x.match(/\n{2}/) ? x : x.trim() + " \n";
}); });
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) { text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
return "\n\n" + extractions[y]; return "\n\n" + preExtractions[y];
}); });
@ -58,25 +53,43 @@
} }
}, },
{ {
// Auto-link URLs and emails // GFM autolinking & custom image handling, happens AFTER showdown
type : 'lang', type : 'html',
filter : function (text) { filter : function (text) {
var extractions = {}, var refExtractions = {},
preExtractions = {},
imageMarkdownRegex = /^(?:\{(.*?)\})?!(?:\[([^\n\]]*)\])(?:\(([^\n\]]*)\))?$/gim,
hashID = 0; hashID = 0;
function hashId() { function hashId() {
return hashID++; return hashID++;
} }
// Extract pre blocks
text = text.replace(/<(pre|code)>[\s\S]*?<\/(\1)>/gim, function (x) {
var hash = hashId();
preExtractions[hash] = x;
return "{gfm-js-extract-pre-" + hash + "}";
}, 'm');
// filter out def urls // filter out def urls
// from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24 // from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24
text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi, text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi,
function (x) { function (x) {
var hash = hashId(); var hash = hashId();
extractions[hash] = x; refExtractions[hash] = x;
return "{gfm-js-extract-ref-url-" + hash + "}"; return "{gfm-js-extract-ref-url-" + hash + "}";
}); });
// better URL support, but no title support
text = text.replace(imageMarkdownRegex, function (match, key, alt, src) {
if (src) {
return '<img src="' + src + '" alt="' + alt + '" />';
}
return '';
});
// match a URL // match a URL
// adapted from https://gist.github.com/jorilallo/1283095#L158 // adapted from https://gist.github.com/jorilallo/1283095#L158
// and http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript // and http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript
@ -91,13 +104,18 @@
return lookBehind ? wholeMatch : "<a href='" + wholeMatch + "'>" + wholeMatch + "</a>"; return lookBehind ? wholeMatch : "<a href='" + wholeMatch + "'>" + wholeMatch + "</a>";
}); });
// match emil // match email
text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) { text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) {
return "<a href='mailto:" + wholeMatch + "'>" + wholeMatch + "</a>"; return "<a href='mailto:" + wholeMatch + "'>" + wholeMatch + "</a>";
}); });
// replace extractions
text = text.replace(/\{gfm-js-extract-pre-([0-9]+)\}/gm, function (x, y) {
return preExtractions[y];
});
text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) { text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) {
return "\n\n" + extractions[y]; return "\n\n" + refExtractions[y];
}); });
return text; return text;

View File

@ -205,7 +205,6 @@ describe('Settings Model', function () {
it('populates any unset settings from the JSON defaults', function (done) { it('populates any unset settings from the JSON defaults', function (done) {
SettingsModel.findAll().then(function (allSettings) { SettingsModel.findAll().then(function (allSettings) {
console.log(allSettings.models)
allSettings.length.should.equal(0); allSettings.length.should.equal(0);
return SettingsModel.populateDefaults(); return SettingsModel.populateDefaults();
}).then(function () { }).then(function () {

View File

@ -178,7 +178,7 @@ describe("Showdown client side converter", function () {
}, },
{ {
input: "# http://google.co.uk", input: "# http://google.co.uk",
output: /^<h1 id="ahrefhttpgooglecoukhttpgooglecouka"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/ output: /^<h1 id="httpgooglecouk"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/
}, },
{ {
input: "* http://google.co.uk", input: "* http://google.co.uk",
@ -279,6 +279,30 @@ describe("Showdown client side converter", function () {
}); });
}); });
it("should NOT auto-link URLS inside of code/pre blocks", function () {
var testPhrases = [
{
input: "```\nurl: http://google.co.uk\n```",
output: /^<pre><code>url: http:\/\/google.co.uk \n<\/code><\/pre>$/
},
{
input: "`url: http://google.co.uk`",
output: /^<p><code>url: http:\/\/google.co.uk<\/code><\/p>$/
},
{
input: "Hello type some `url: http://google.co.uk` stuff",
output: /^<p>Hello type some <code>url: http:\/\/google.co.uk<\/code> stuff<\/p>$/
}
],
processedMarkup;
testPhrases.forEach(function (testPhrase) {
processedMarkup = converter.makeHtml(testPhrase.input);
processedMarkup.should.match(testPhrase.output);
});
});
it("should not display anything for reference URL", function () { it("should not display anything for reference URL", function () {
var testPhrases = [ var testPhrases = [
{ {

View File

@ -252,4 +252,19 @@ describe("Github showdown extensions", function () {
}); });
}); });
it("should not output image if there is no src", function () {
var testPhrases = [
{
input: "![anything here]()",
output: /^$/
}
],
processedMarkup;
testPhrases.forEach(function (testPhrase) {
processedMarkup = _ConvertPhrase(testPhrase.input);
processedMarkup.should.match(testPhrase.output);
});
});
}); });