FEATURE: Replace markdown-it replacements rule. (#12417)
We override the default replacements rule to no longer replace "(c)", "(p)", and "(p)". Additionally, we merged the custom arrows rule into the replacement function.
This commit is contained in:
parent
1a433193d1
commit
da210b6d77
|
@ -1601,4 +1601,74 @@ var bar = 'bar';
|
|||
assert.cookedOptions(" -->asd ", enabledTypographer, "<p>–>asd</p>");
|
||||
assert.cookedOptions(" -->asd", enabledTypographer, "<p>–>asd</p>");
|
||||
});
|
||||
|
||||
test("default typhographic replacements", function (assert) {
|
||||
const enabledTypographer = {
|
||||
siteSettings: { enable_markdown_typographer: true },
|
||||
};
|
||||
|
||||
assert.cookedOptions("(bad)", enabledTypographer, "<p>(bad)</p>");
|
||||
assert.cookedOptions("+-5", enabledTypographer, "<p>±5</p>");
|
||||
assert.cookedOptions(
|
||||
"test.. test... test..... test?..... test!....",
|
||||
enabledTypographer,
|
||||
"<p>test… test… test… test?.. test!..</p>"
|
||||
);
|
||||
assert.cookedOptions(
|
||||
"!!!!!! ???? ,,",
|
||||
enabledTypographer,
|
||||
"<p>!!! ??? ,</p>"
|
||||
);
|
||||
assert.cookedOptions(
|
||||
"!!!!!! ???? ,,",
|
||||
enabledTypographer,
|
||||
"<p>!!! ??? ,</p>"
|
||||
);
|
||||
assert.cookedOptions("(tm) (TM)", enabledTypographer, "<p>™ ™</p>");
|
||||
});
|
||||
|
||||
test("default typhographic replacements - dashes", function (assert) {
|
||||
const enabledTypographer = {
|
||||
siteSettings: { enable_markdown_typographer: true },
|
||||
};
|
||||
|
||||
assert.cookedOptions(
|
||||
"---markdownit --- super---",
|
||||
enabledTypographer,
|
||||
"<p>—markdownit — super—</p>"
|
||||
);
|
||||
assert.cookedOptions(
|
||||
"markdownit---awesome",
|
||||
enabledTypographer,
|
||||
"<p>markdownit—awesome</p>"
|
||||
);
|
||||
assert.cookedOptions("abc ----", enabledTypographer, "<p>abc ----</p>");
|
||||
assert.cookedOptions(
|
||||
"--markdownit -- super--",
|
||||
enabledTypographer,
|
||||
"<p>–markdownit – super–</p>"
|
||||
);
|
||||
assert.cookedOptions(
|
||||
"markdownit--awesome",
|
||||
enabledTypographer,
|
||||
"<p>markdownit–awesome</p>"
|
||||
);
|
||||
assert.cookedOptions("1---2---3", enabledTypographer, "<p>1—2—3</p>");
|
||||
assert.cookedOptions("1--2--3", enabledTypographer, "<p>1–2–3</p>");
|
||||
assert.cookedOptions(
|
||||
"<p>1 – – 3</p>",
|
||||
enabledTypographer,
|
||||
"<p>1 – – 3</p>"
|
||||
);
|
||||
});
|
||||
|
||||
test("disabled typhographic replacements", function (assert) {
|
||||
const enabledTypographer = {
|
||||
siteSettings: { enable_markdown_typographer: true },
|
||||
};
|
||||
|
||||
assert.cookedOptions("(c) (C)", enabledTypographer, "<p>(c) (C)</p>");
|
||||
assert.cookedOptions("(r) (R)", enabledTypographer, "<p>(r) (R)</p>");
|
||||
assert.cookedOptions("(p) (P)", enabledTypographer, "<p>(p) (P)</p>");
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
// Simple typographic replacements
|
||||
//
|
||||
// (tm) (TM) → ™
|
||||
// +- → ±
|
||||
// ... → … (also ?.... → ?.., !.... → !..)
|
||||
// ???????? → ???, !!!!! → !!!, `,,` → `,`
|
||||
// -- → –, --- → —
|
||||
// --> <-- -> <- to → ← → ←
|
||||
//
|
||||
// Disabled replacements:
|
||||
//
|
||||
// (c) (C) → ©
|
||||
// (r) (R) → ®
|
||||
// (p) (P) -> §
|
||||
|
||||
let RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--|-->|<--|->|<-/;
|
||||
let SCOPED_ABBR_RE = /\((tm)\)/gi;
|
||||
|
||||
function replaceScoped(inlineTokens) {
|
||||
let i, token;
|
||||
|
||||
for (i = inlineTokens.length - 1; i >= 0; i--) {
|
||||
token = inlineTokens[i];
|
||||
if (token.type === "text") {
|
||||
token.content = token.content.replace(SCOPED_ABBR_RE, () => {
|
||||
return "™";
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceRare(inlineTokens) {
|
||||
let i,
|
||||
token,
|
||||
inside_autolink = 0;
|
||||
|
||||
for (i = inlineTokens.length - 1; i >= 0; i--) {
|
||||
token = inlineTokens[i];
|
||||
|
||||
if (token.type === "text" && !inside_autolink) {
|
||||
if (RARE_RE.test(token.content)) {
|
||||
token.content = token.content
|
||||
.replace(/\+-/g, "±")
|
||||
// Custom arrows
|
||||
.replace(/(^|\s)-{1,2}>(\s|$)/gm, "\u0020\u2192\u0020")
|
||||
.replace(/(^|\s)<-{1,2}(\s|$)/gm, "\u0020\u2190\u0020")
|
||||
// .., ..., ....... -> …
|
||||
// but ?..... & !..... -> ?.. & !..
|
||||
.replace(/\.{2,}/g, "…")
|
||||
.replace(/([?!])…/g, "$1..")
|
||||
.replace(/([?!]){4,}/g, "$1$1$1")
|
||||
.replace(/,{2,}/g, ",")
|
||||
// em-dash
|
||||
.replace(/(^|[^-])---(?=[^-]|$)/gm, "$1\u2014")
|
||||
// en-dash
|
||||
.replace(/(^|\s)--(?=\s|$)/gm, "$1\u2013")
|
||||
.replace(/(^|[^-\s])--(?=[^-\s]|$)/gm, "$1\u2013");
|
||||
}
|
||||
}
|
||||
|
||||
if (token.type === "link_open" && token.info === "auto") {
|
||||
inside_autolink--;
|
||||
}
|
||||
|
||||
if (token.type === "link_close" && token.info === "auto") {
|
||||
inside_autolink++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replace(state) {
|
||||
let blkIdx;
|
||||
|
||||
for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
|
||||
if (state.tokens[blkIdx].type !== "inline") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SCOPED_ABBR_RE.test(state.tokens[blkIdx].content)) {
|
||||
replaceScoped(state.tokens[blkIdx].children);
|
||||
}
|
||||
|
||||
if (RARE_RE.test(state.tokens[blkIdx].content)) {
|
||||
replaceRare(state.tokens[blkIdx].children);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setup(helper) {
|
||||
helper.registerPlugin((md) => {
|
||||
if (md.options.typographer) {
|
||||
md.core.ruler.at("replacements", replace);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
function replaceArrows(state) {
|
||||
for (let i = 0; i < state.tokens.length; i++) {
|
||||
let token = state.tokens[i];
|
||||
|
||||
if (token.type !== "inline") {
|
||||
continue;
|
||||
}
|
||||
|
||||
const arrowsRegexp = /-->|<--|->|<-/;
|
||||
if (arrowsRegexp.test(token.content)) {
|
||||
for (let ci = 0; ci < token.children.length; ci++) {
|
||||
let child = token.children[ci];
|
||||
|
||||
if (child.type === "text") {
|
||||
if (arrowsRegexp.test(child.content)) {
|
||||
child.content = child.content
|
||||
.replace(/(^|\s)-{1,2}>(\s|$)/gm, "\u0020\u2192\u0020")
|
||||
.replace(/(^|\s)<-{1,2}(\s|$)/gm, "\u0020\u2190\u0020");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function setup(helper) {
|
||||
helper.registerPlugin((md) => {
|
||||
if (md.options.typographer) {
|
||||
md.core.ruler.before("replacements", "typographer-arrow", replaceArrows);
|
||||
}
|
||||
});
|
||||
}
|
|
@ -1442,10 +1442,10 @@ HTML
|
|||
|
||||
it 'supports typographer' do
|
||||
SiteSetting.enable_markdown_typographer = true
|
||||
expect(PrettyText.cook('(tm)')).to eq('<p>™</p>')
|
||||
expect(PrettyText.cook('->')).to eq('<p> → </p>')
|
||||
|
||||
SiteSetting.enable_markdown_typographer = false
|
||||
expect(PrettyText.cook('(tm)')).to eq('<p>(tm)</p>')
|
||||
expect(PrettyText.cook('->')).to eq('<p>-></p>')
|
||||
end
|
||||
|
||||
it 'uses quotation marks from site settings' do
|
||||
|
|
Loading…
Reference in New Issue