Userscripts Code Block Fix

in Script development
Subscribe to Userscripts Code Block Fix 11 posts, 4 voices



sizzlemctwizzle Scriptwright

// ==UserScript==
// @name             Userscripts.org code block fix
// @namespace        sizzlemctwizzle
// @description      Automatically replaces < and > with &lt; and &gt; in code blocks
// @include          http://userscripts.org/forums/*/topics/*
// @include          http://userscripts.org/scripts/show/*
// @include          http://userscripts.org/scripts/edit/*
// ==/UserScript==
var forms = document.evaluate('//form', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0; i < forms.snapshotLength; i ++) {
forms.snapshotItem(i).addEventListener('submit', function() {
text = this.getElementsByTagName('textarea');
for (var x = 0; x < text.length; x ++) {
text[x].value = text[x].value.replace(/</g,'&lt;').replace(/>/g,'&gt;');
}
}, true);
}

How do I get this code to only replace < and > inside code blocks?

 
dob Scriptwright

I'm so sick and tired of this shitty text fomatting.
Seriously, just freaking htmlentities() all of it, PLEASE!

 
dob Scriptwright

Here's your script: http://nopaste.voric.com/paste.php?f=65y61v

 
sizzlemctwizzle Scriptwright

Yeah that script is not going to work at all. document.getElementsByTagName("code") is not going to work because the code tag is inside the value attribute of the textarea not the document. I'm thinking that the only way to get this to work would be with some Regexp. Unfortunately I'm terrible at Regexp.

 
Aquilax Scriptwright

I can give you some code, but I'm writing it on the fly, don't expect to be bugs free


var text1=mytextarea.value;
var regexp1=new Regexp("<code>(.|\\s)*?</code>","gmi");
var match1=regexp1.exec(text1);
while(match1)
{
    var num1=match1.index+6;
    var num2=match1[1].length;
    var text2=text1.substring(0,num1); //everything till ...<code>
    var text3=text1.substring(num1+1,num2); //everything inside <code>...</code>
    var text3=text1.substring(num1+num2+1); //everything after </code>...
    text2=text2.replace(/</gmi,"&lt;").replace(/>/gmi,"&gt;");
    text1=text2+text3+text4;
    match1=regexp1.exec(text1);
}

 
Descriptor Scriptwright

@dob
turn off Greasemonkey and reload the page, there's nothing wrong with the post - my syntax highlighter is doing the same thing.

@Aquilax
You can use a function in replace, so I think there's a shorter way to do that (no time, but intriguing).

 
Aquilax Scriptwright

Wow, I was used with others languages where you could pass a function (lambda expression) to make the replace but not with javascript, this is really nice :), this means that it can be done like this:

mytextarea.value.replace(/<code>((?:.|\s)*?)<\/code>/gmi, function(str,p1,offset,s){ return "<code>"+p1.replace(/</gm,"&lt;").replace(/>/gm,"&gt;")+"</code>";})

Now I'm waiting for the named captures :)

 
Aquilax Scriptwright

Here a source script, I'm doing it to test the it :)
It seems to work, but if I use the < code > and < / code > inside the regexp, they create some confusion to the forum engine :)
To use it you have to replace the [code] and [/code] with the reals < code > and < / code >


// ==UserScript==
// @name           Userscripts
// @namespace      Replace inside code block
// @include        http://userscripts.org/forums/*/topics/*
// @include        http://userscripts.org/scripts/show/*
// @include        http://userscripts.org/scripts/edit/*
// ==/UserScript==

init();

function init()
{
	addFormsSubmissionEventListener(document);
	window.addEventListener("unload",revertTextAreas,false);
	document.addEventListener("DOMNodeInserted",function(e){addFormsSubmissionEventListener(e.relatedNode);},false);
	unsafeWindow.revertTextAreas=revertTextAreas;
}

function addFormsSubmissionEventListener(node)
{
	var array1=node.getElementsByTagName("FORM");
	for(var num1=0;num1<array1.length;num1++) 
	{
		var form1=array1[num1];
		var text1=form1.getAttribute("onsubmit");
		if (text1==null) text1="";
		if (text1.indexOf("replaceCodeBlocks")==-1) 
		{
			var text2=text1.indexOf("Ajax")!=1?"; revertTextAreas();":"";
			form1.setAttribute("onsubmit","replaceCodeBlocks(this); "+text1+text2);
		}
		

		var array2=form1.getElementsByTagName("TEXTAREA");
		var replacer=function(str,p1){return "[code]+p1.replace(/&lt;/gm,"<").replace(/&gt;/gm,">").replace(/&amp;/gm,"&")+"[/code]";}
		for(var num2=0;num2<array2.length;num2++) 
		{
			var textarea1=array2[num2];
			if (textarea1.originalValue==null)
			{
				var text2=textarea1.value.replace(/[code]((?:.|\s)*?)[\/code]/gmi,replacer);
				textarea1.value=text2;
				textarea1.originalValue=text2;
				GM_log(text2);
			}
		}
	}
}

unsafeWindow.replaceCodeBlocks=function(form)
{
	var array1=form.getElementsByTagName("TEXTAREA");
	var replacer=function(str,p1){return "[code]"+p1.replace(/&/gm,"&amp;").replace(/</gm,"&lt;").replace(/>/gm,"&gt;")+"[/code]";}
	for(var num1=0;num1<array1.length;num1++) 
	{
		var textarea1=array1[num1];
		var text1=textarea1.value;
		textarea1.originalValue=text1;
		textarea1.value=text1.replace(/[code]((?:.|\s)*?)[\/code]/gmi,replacer);
	}
}

function revertTextAreas(e)
{
	var array1=document.getElementsByTagName("TEXTAREA");
	for(var num1=0;num1<array1.length;num1++) 
	{
		var textarea1=array1[num1];
		if (textarea1.originalValue) textarea1.value=textarea1.originalValue;
	}
}

 
dob Scriptwright

Descriptor wrote:

@dob turn off Greasemonkey and reload the page, there's nothing wrong with the post - my syntax highlighter is doing the same thing.

@Aquilax You can use a function in replace, so I think there's a shorter way to do that (no time, but intriguing).

I edited my post, because it was killed by the formatting. It just closes tags that I intentionally leave open, even if they're htmlentities.
 
sizzlemctwizzle Scriptwright

<div id="test">I'm testing <span>this</span> script.</div>

Yep. Aquilax's script works. I posted it and gave you credit.

 
Descriptor Scriptwright


dob wrote:
I edited my post, because it was killed by the formatting. It just closes tags that I intentionally leave open, even if they're htmlentities.

Ahh, I see, but put them in <code> tags and it should work. test <input>, but I agree it should at least ignore tags that aren't accepted as markup code. Use &amp;lt; for entities &lt;