mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-24 19:33:02 +03:00
Merge pull request #590 from ErisDS/showdown-gfm-fix
GFM Auto-linking fixes
This commit is contained in:
commit
859e20d8a3
31
core/shared/vendor/showdown/extensions/github.js
vendored
31
core/shared/vendor/showdown/extensions/github.js
vendored
@ -63,29 +63,34 @@
|
||||
}
|
||||
|
||||
// filter out def urls
|
||||
text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gim,
|
||||
// from Marked https://github.com/chjj/marked/blob/master/lib/marked.js#L24
|
||||
text = text.replace(/^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/gmi,
|
||||
function (x) {
|
||||
var hash = hashId();
|
||||
extractions[hash] = x;
|
||||
return "{gfm-js-extract-ref-url-" + hash + "}";
|
||||
});
|
||||
|
||||
// taken from https://gist.github.com/jorilallo/1283095#L158
|
||||
text = text.replace(/https?\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!]/g, function (wholeMatch, matchIndex) {
|
||||
var left = text.slice(0, matchIndex), right = text.slice(matchIndex),
|
||||
href;
|
||||
if (left.match(/<[^>]+$/) && right.match(/^[^>]*>/)) {
|
||||
return wholeMatch;
|
||||
}
|
||||
href = wholeMatch.replace(/^http:\/\/github.com\//, "https://github.com/");
|
||||
return "<a href='" + href + "'>" + wholeMatch + "</a>";
|
||||
});
|
||||
// match a URL
|
||||
// adapted from https://gist.github.com/jorilallo/1283095#L158
|
||||
// and http://blog.stevenlevithan.com/archives/mimic-lookbehind-javascript
|
||||
text = text.replace(/(\]\(|\]|\[|<a[^\>]*?\>)?https?\:\/\/[^"\s\<\>]*[^.,;'">\:\s\<\>\)\]\!]/gmi,
|
||||
function (wholeMatch, lookBehind, matchIndex) {
|
||||
// Check we are not inside an HTML tag
|
||||
var left = text.slice(0, matchIndex), right = text.slice(matchIndex);
|
||||
if ((left.match(/<[^>]+$/) && right.match(/^[^>]*>/)) || lookBehind) {
|
||||
return wholeMatch;
|
||||
}
|
||||
// If we have a matching lookBehind, this is a failure, else wrap the match in <a> tag
|
||||
return lookBehind ? wholeMatch : "<a href='" + wholeMatch + "'>" + wholeMatch + "</a>";
|
||||
});
|
||||
|
||||
text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/ig, function (wholeMatch) {
|
||||
// match emil
|
||||
text = text.replace(/[a-z0-9_\-+=.]+@[a-z0-9\-]+(\.[a-z0-9-]+)+/gmi, function (wholeMatch) {
|
||||
return "<a href='mailto:" + wholeMatch + "'>" + wholeMatch + "</a>";
|
||||
});
|
||||
|
||||
text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gm, function (x, y) {
|
||||
text = text.replace(/\{gfm-js-extract-ref-url-([0-9]+)\}/gi, function (x, y) {
|
||||
return "\n\n" + extractions[y];
|
||||
});
|
||||
|
||||
|
@ -136,12 +136,43 @@ describe("Showdown client side converter", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("should auto-link URL", function () {
|
||||
it("should auto-link URL in text with markdown syntax", function () {
|
||||
var testPhrases = [
|
||||
{input: "http://google.co.uk", output: /^<p><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>$/},
|
||||
{
|
||||
input: "http://google.co.uk",
|
||||
output: /^<p><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "https://atest.com/fizz/buzz?baz=fizzbuzz",
|
||||
output: /^<p><a href=\'https:\/\/atest.com\/fizz\/buzz\?baz=fizzbuzz\'>https:\/\/atest.com\/fizz\/buzz\?baz=fizzbuzz<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "Some [ text (http://www.google.co.uk) some other text",
|
||||
output: /^<p>Some \[ text \(<a href=\'http:\/\/www.google.co.uk\'>http:\/\/www.google.co.uk<\/a>\) some other text<\/p>$/
|
||||
},
|
||||
{
|
||||
input: ">http://google.co.uk",
|
||||
output: /^<blockquote>\n <p><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>\n<\/blockquote>$/
|
||||
},
|
||||
{
|
||||
input: "> http://google.co.uk",
|
||||
output: /^<blockquote>\n <p><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>\n<\/blockquote>$/
|
||||
},
|
||||
{
|
||||
input: "<>>> http://google.co.uk",
|
||||
output: /^<p><>>> <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "<strong>http://google.co.uk",
|
||||
output: /^<p><strong><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "# http://google.co.uk",
|
||||
output: /^<h1 id="ahrefhttpgooglecoukhttpgooglecouka"><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/h1>$/
|
||||
},
|
||||
{
|
||||
input: "* http://google.co.uk",
|
||||
output: /^<ul>\n<li><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/li>\n<\/ul>$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
@ -159,7 +190,6 @@ describe("Showdown client side converter", function () {
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
|
||||
// Fails
|
||||
it("should convert reference format URL", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
@ -169,6 +199,10 @@ describe("Showdown client side converter", function () {
|
||||
{
|
||||
input: "[Google][1]\n\n[1]: http://google.co.uk \"some text\"",
|
||||
output: /^<p><a href="http:\/\/google.co.uk" title="some text">Google<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "[http://google.co.uk]: http://google.co.uk\n\n[Hello][http://google.co.uk]",
|
||||
output: /^<p><a href="http:\/\/google.co.uk">Hello<\/a><\/p>$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
@ -188,6 +222,10 @@ describe("Showdown client side converter", function () {
|
||||
{
|
||||
input: "![Google][1]\n\n[1]: http://dsurl.stuff/something.jpg \"some text\"",
|
||||
output: /^<section.*?<img.*?src="http:\/\/dsurl.stuff\/something.jpg"\/>.*?<\/section>$/
|
||||
},
|
||||
{
|
||||
input: "[http://www.google.co.uk]: http://www.google.co.uk\n\n![Hello][http://www.google.co.uk]",
|
||||
output: /^<section.*?<img.*?src="http:\/\/www.google.co.uk"\/>.*?<\/section>$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
@ -198,19 +236,70 @@ describe("Showdown client side converter", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("should NOT auto-link reference URL", function () {
|
||||
var testPhrase = {input: "[1]: http://google.co.uk", output: /^$/},
|
||||
processedMarkup = converter.makeHtml(testPhrase.input);
|
||||
it("should NOT auto-link URL in HTML", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
input: '<img src="http://placekitten.com/50">',
|
||||
output: /^<p><img src=\"http:\/\/placekitten.com\/50\"><\/p>$/
|
||||
},
|
||||
{
|
||||
input: '<img src="http://placekitten.com/50" />',
|
||||
output: /^<p><img src=\"http:\/\/placekitten.com\/50\" \/><\/p>$/
|
||||
},
|
||||
{
|
||||
input: '<script type="text/javascript" src="http://google.co.uk"></script>',
|
||||
output: /^<script type=\"text\/javascript\" src=\"http:\/\/google.co.uk\"><\/script>$/
|
||||
},
|
||||
{
|
||||
input: '<a href="http://facebook.com">http://google.co.uk</a>',
|
||||
output: /^<p><a href=\"http:\/\/facebook.com\">http:\/\/google.co.uk<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: '<a href="http://facebook.com">test</a> http://google.co.uk',
|
||||
output: /^<p><a href=\"http:\/\/facebook.com\">test<\/a> <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a><\/p>$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
testPhrases.forEach(function (testPhrase) {
|
||||
processedMarkup = converter.makeHtml(testPhrase.input);
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
it("should not display anything for reference URL", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
input: "[1]: http://www.google.co.uk",
|
||||
output: /^$/
|
||||
},
|
||||
{
|
||||
input: "[http://www.google.co.uk]: http://www.google.co.uk",
|
||||
output: /^$/
|
||||
},
|
||||
{
|
||||
input: "[1]: http://dsurl.stuff/something.jpg",
|
||||
output: /^$/
|
||||
},
|
||||
{
|
||||
input: "[1]:http://www.google.co.uk",
|
||||
output: /^$/
|
||||
},
|
||||
{
|
||||
input: " [1]:http://www.google.co.uk",
|
||||
output: /^$/
|
||||
},
|
||||
{
|
||||
input: "",
|
||||
output: /^$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
|
||||
it("should NOT auto-link image reference URL", function () {
|
||||
var testPhrase = {input: "[1]: http://dsurl.stuff/something.jpg", output: /^$/},
|
||||
testPhrases.forEach(function (testPhrase) {
|
||||
processedMarkup = converter.makeHtml(testPhrase.input);
|
||||
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
it("should show placeholder for image markdown", function () {
|
||||
@ -276,8 +365,41 @@ describe("Showdown client side converter", function () {
|
||||
});
|
||||
});
|
||||
|
||||
it("should NOT auto-link image URL", function () {
|
||||
// it("should NOT auto-link URL in image", function () {
|
||||
// var testPhrases = [
|
||||
// {
|
||||
// input: "![http://google.co.uk/kitten.jpg](http://google.co.uk/kitten.jpg)",
|
||||
// output: /^<section.*?((?!<a href=\'http:\/\/google.co.uk\/kitten.jpg\').)*<\/section>$/
|
||||
// },
|
||||
// {
|
||||
// input: "![image stuff](http://dsurl.stuff/something)",
|
||||
// output: /^<section.*?((?!<a href=\'http:\/\/dsurl.stuff\/something\').)*<\/section>$/
|
||||
|
||||
// });
|
||||
//
|
||||
|
||||
it("should correctly output link and image markdown without autolinks", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
input: "[1](http://google.co.uk)",
|
||||
output: /^<p><a href="http:\/\/google.co.uk">1<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: " [1](http://google.co.uk)",
|
||||
output: /^<p><a href="http:\/\/google.co.uk">1<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "[http://google.co.uk](http://google.co.uk)",
|
||||
output: /^<p><a href="http:\/\/google.co.uk">http:\/\/google.co.uk<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "[http://google.co.uk][id]\n\n[id]: http://google.co.uk",
|
||||
output: /^<p><a href="http:\/\/google.co.uk">http:\/\/google.co.uk<\/a><\/p>$/
|
||||
},
|
||||
{
|
||||
input: "![http://google.co.uk/kitten.jpg](http://google.co.uk/kitten.jpg)",
|
||||
output: /^<section.*?((?!<a href=\'http:\/\/google.co.uk\/kitten.jpg\').)*<\/section>$/
|
||||
},
|
||||
{
|
||||
input: "![image stuff](http://dsurl.stuff/something)",
|
||||
output: /^<section.*?((?!<a href=\'http:\/\/dsurl.stuff\/something\').)*<\/section>$/
|
||||
@ -290,5 +412,4 @@ describe("Showdown client side converter", function () {
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -46,12 +46,67 @@ describe("Github showdown extensions", function () {
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
|
||||
it("should auto-link URL", function () {
|
||||
it("should auto-link URL in text with markdown syntax", function () {
|
||||
var testPhrases = [
|
||||
{input: "http://google.co.uk", output: /^<a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/},
|
||||
{
|
||||
input: "http://google.co.uk",
|
||||
output: /^<a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "https://atest.com/fizz/buzz?baz=fizzbuzz",
|
||||
output: /^<a href=\'https:\/\/atest.com\/fizz\/buzz\?baz=fizzbuzz\'>https:\/\/atest.com\/fizz\/buzz\?baz=fizzbuzz<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "Some text http://www.google.co.uk some other text",
|
||||
output: /^Some text <a href=\'http:\/\/www.google.co.uk\'>http:\/\/www.google.co.uk<\/a> some other text$/
|
||||
},
|
||||
{
|
||||
input: "Some [ text http://www.google.co.uk some other text",
|
||||
output: /^Some \[ text <a href=\'http:\/\/www.google.co.uk\'>http:\/\/www.google.co.uk<\/a> some other text$/
|
||||
},
|
||||
{
|
||||
input: "Some [ text (http://www.google.co.uk) some other text",
|
||||
output: /^Some \[ text \(<a href=\'http:\/\/www.google.co.uk\'>http:\/\/www.google.co.uk<\/a>\) some other text$/
|
||||
},
|
||||
{
|
||||
input: " http://google.co.uk ",
|
||||
output: /^ <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a> $/
|
||||
},
|
||||
{
|
||||
input: ">http://google.co.uk",
|
||||
output: /^><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "> http://google.co.uk",
|
||||
output: /^> <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "<>>> http://google.co.uk",
|
||||
output: /^<>>> <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "<>>>http://google.co.uk",
|
||||
output: /^<>>><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "<some text>>>http://google.co.uk",
|
||||
output: /^<some text>>><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "<strong>http://google.co.uk",
|
||||
output: /^<strong><a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "# http://google.co.uk",
|
||||
output: /^# <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "#http://google.co.uk",
|
||||
output: /^#<a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: "* http://google.co.uk",
|
||||
output: /^\* <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
@ -69,17 +124,129 @@ describe("Github showdown extensions", function () {
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
|
||||
it("should NOT auto-link URL in HTML", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
input: '<img src="http://placekitten.com/50">',
|
||||
output: /^<img src=\"http:\/\/placekitten.com\/50\">$/
|
||||
},
|
||||
{
|
||||
input: '<img src="http://placekitten.com/50" />',
|
||||
output: /^<img src=\"http:\/\/placekitten.com\/50\" \/>$/
|
||||
},
|
||||
{
|
||||
input: '<script type="text/javascript" src="http://google.co.uk"></script>',
|
||||
output: /^<script type=\"text\/javascript\" src=\"http:\/\/google.co.uk\"><\/script>$/
|
||||
},
|
||||
{
|
||||
input: '<a href="http://facebook.com">http://google.co.uk</a>',
|
||||
output: /^<a href=\"http:\/\/facebook.com\">http:\/\/google.co.uk<\/a>$/
|
||||
},
|
||||
{
|
||||
input: '<a href="http://facebook.com">test</a> http://google.co.uk',
|
||||
output: /^<a href=\"http:\/\/facebook.com\">test<\/a> <a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
|
||||
testPhrases.forEach(function (testPhrase) {
|
||||
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
it("should NOT auto-link reference URL", function () {
|
||||
var testPhrase = {input: "[1]: http://google.co.uk", output: /^\n\n\[1\]: http:\/\/google.co.uk$/},
|
||||
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||
var testPhrases = [
|
||||
{
|
||||
input: "[1]: http://www.google.co.uk",
|
||||
output: /^\n\n\[1\]: http:\/\/www.google.co.uk$/
|
||||
},
|
||||
{
|
||||
input: "[http://www.google.co.uk]: http://www.google.co.uk",
|
||||
output: /^\n\n\[http:\/\/www.google.co.uk]: http:\/\/www.google.co.uk$/
|
||||
},
|
||||
{
|
||||
input: "[1]: http://dsurl.stuff/something.jpg",
|
||||
output: /^\n\n\[1\]: http:\/\/dsurl.stuff\/something.jpg$/
|
||||
},
|
||||
{
|
||||
input: "[1]:http://www.google.co.uk",
|
||||
output: /^\n\n\[1\]:http:\/\/www.google.co.uk$/
|
||||
},
|
||||
{
|
||||
input: " [1]:http://www.google.co.uk",
|
||||
output: /^\n\n \[1\]:http:\/\/www.google.co.uk$/
|
||||
},
|
||||
{
|
||||
input: "[http://www.google.co.uk]: http://www.google.co.uk",
|
||||
output: /^\n\n\[http:\/\/www.google.co.uk\]: http:\/\/www.google.co.uk$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
testPhrases.forEach(function (testPhrase) {
|
||||
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
it("should NOT auto-link image URL", function () {
|
||||
var testPhrase = {input: "[1]: http://dsurl.stuff/something.jpg", output: /^\n\n\[1\]: http:\/\/dsurl.stuff\/something.jpg$/},
|
||||
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||
it("should NOT auto-link URL in link or image markdown", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
input: "[1](http://google.co.uk)",
|
||||
output: /^\[1\]\(http:\/\/google.co.uk\)$/
|
||||
},
|
||||
{
|
||||
input: " [1](http://google.co.uk)",
|
||||
output: /^ \[1\]\(http:\/\/google.co.uk\)$/
|
||||
},
|
||||
{
|
||||
input: "[http://google.co.uk](http://google.co.uk)",
|
||||
output: /^\[http:\/\/google.co.uk\]\(http:\/\/google.co.uk\)$/
|
||||
},
|
||||
{
|
||||
input: "[http://google.co.uk][id]",
|
||||
output: /^\[http:\/\/google.co.uk\]\[id\]$/
|
||||
},
|
||||
{
|
||||
input: "![1](http://google.co.uk/kitten.jpg)",
|
||||
output: /^!\[1\]\(http:\/\/google.co.uk\/kitten.jpg\)$/
|
||||
},
|
||||
{
|
||||
input: " ![1](http://google.co.uk/kitten.jpg)",
|
||||
output: /^ !\[1\]\(http:\/\/google.co.uk\/kitten.jpg\)$/
|
||||
},
|
||||
{
|
||||
input: "![http://google.co.uk/kitten.jpg](http://google.co.uk/kitten.jpg)",
|
||||
output: /^!\[http:\/\/google.co.uk\/kitten.jpg\]\(http:\/\/google.co.uk\/kitten.jpg\)$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
testPhrases.forEach(function (testPhrase) {
|
||||
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
// behaviour if you add a gap between [] and ()
|
||||
it("should auto-link if markdown is invalid", function () {
|
||||
var testPhrases = [
|
||||
{
|
||||
input: "[1] (http://google.co.uk)",
|
||||
output: /^\[1\] \(<a href=\'http:\/\/google.co.uk\'>http:\/\/google.co.uk<\/a>\)$/
|
||||
},
|
||||
{
|
||||
input: "![1] (http://google.co.uk/kitten.jpg)",
|
||||
output: /^!\[1\] \(<a href=\'http:\/\/google.co.uk\/kitten.jpg\'>http:\/\/google.co.uk\/kitten.jpg<\/a>\)$/
|
||||
}
|
||||
],
|
||||
processedMarkup;
|
||||
|
||||
testPhrases.forEach(function (testPhrase) {
|
||||
processedMarkup = _ConvertPhrase(testPhrase.input);
|
||||
processedMarkup.should.match(testPhrase.output);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue
Block a user