Merge pull request #2256 from caerphoto/1795-typography

Add support for typographically-correct punctuation
This commit is contained in:
Hannah Wolfe 2014-02-28 10:49:06 +00:00
commit c64148f361
5 changed files with 121 additions and 4 deletions

View File

@ -382,6 +382,7 @@ var path = require('path'),
'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/vendor/shortcuts.js',
'core/client/assets/vendor/validator-client.js',
@ -437,6 +438,7 @@ var path = require('path'),
'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/vendor/shortcuts.js',
'core/client/assets/vendor/validator-client.js',

View File

@ -449,7 +449,7 @@
initMarkdown: function () {
var self = this;
this.converter = new Showdown.converter({extensions: ['ghostdown', 'github']});
this.converter = new Showdown.converter({extensions: ['typography', 'ghostdown', 'github']});
this.editor = CodeMirror.fromTextArea(document.getElementById('entry-markdown'), {
mode: 'gfm',
tabMode: 'indent',

View File

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

View File

@ -0,0 +1,114 @@
/*global module */
//
// Replaces straight quotes with curly ones, -- and --- with en dash and em
// dash respectively, and ... with horizontal ellipses.
//
(function () {
var typography = function () {
return [
{
type: "lang",
filter: function (text) {
var fCodeblocks = {}, nCodeblocks = {}, iCodeblocks = {},
e = {
endash: '\u2009\u2013\u2009', // U+2009 = thin space
emdash: '\u2014',
lsquo: '\u2018',
rsquo: '\u2019',
ldquo: '\u201c',
rdquo: '\u201d',
hellip: '\u2026'
},
i;
// Extract fenced code blocks.
i = -1;
text = text.replace(/```((?:.|\n)+?)```/g,
function (match, code) {
i += 1;
fCodeblocks[i] = "```" + code + "```";
return "{typog-fcb-" + i + "}";
});
// Extract indented code blocks.
i = -1;
text = text.replace(/((\n+([ ]{4}|\t).+)+)/g,
function (match, code) {
i += 1;
nCodeblocks[i] = " " + code;
return "{typog-ncb-" + i + "}";
});
// Extract inline code blocks
i = -1;
text = text.replace(/`(.+)`/g, function (match, code) {
i += 1;
iCodeblocks[i] = "`" + code + "`";
return "{typog-icb-" + i + "}";
});
// Perform typographic symbol replacement.
// Double quotes. There might be a reason this doesn't use
// the same \b matching style as the single quotes, but I
// can't remember what it is :(
text = text.
// Opening quotes
replace(/"([\w'])/g, e.ldquo + "$1").
// All the rest
replace(/"/g, e.rdquo);
// Single quotes/apostrophes
text = text.
// Apostrophes first
replace(/\b'\b/g, e.rsquo).
// Opening quotes
replace(/'\b/g, e.lsquo).
// All the rest
replace(/'/g, e.rsquo);
// Dashes
text = text.
// Don't replace lines containing only hyphens
replace(/^-+$/gm, "{typog-hr}").
replace(/---/g, e.emdash).
replace(/ -- /g, e.endash).
replace(/{typog-hr}/g, "----");
// Ellipses.
text = text.replace(/\.{3}/g, e.hellip);
// Restore fenced code blocks.
text = text.replace(/{typog-fcb-([0-9]+)}/g, function (x, y) {
return fCodeblocks[y];
});
// Restore indented code blocks.
text = text.replace(/{typog-ncb-([0-9]+)}/g, function (x, y) {
return nCodeblocks[y];
});
// Restore inline code blocks.
text = text.replace(/{typog-icb-([0-9]+)}/g, function (x, y) {
return iCodeblocks[y];
});
return text;
}
}
];
};
// Client-side export
if (typeof window !== 'undefined' && window.Showdown && window.Showdown.extensions) {
window.Showdown.extensions.typography = typography;
}
// Server-side export
if (typeof module !== 'undefined') {
module.exports = typography;
}
}());

View File

@ -10,7 +10,7 @@ CasperTest.begin('Ensure that RSS is available', 11, function suite(test) {
siteDescription = '<description><![CDATA[Just a blogging platform.]]></description>',
siteUrl = '<link>http://127.0.0.1:2369/</link>',
postTitle = '<![CDATA[Welcome to Ghost]]>',
postStart = '<description><![CDATA[<p>You\'re live!',
postStart = '<description><![CDATA[<p>Youre live!',
postEnd = 'you think :)</p>]]></description>',
postLink = '<link>http://127.0.0.1:2369/welcome-to-ghost/</link>',
postCreator = '<dc:creator><![CDATA[Test User]]>';