I need a way to identify certain strings in HTML markup. I know what the strings are, but it is possible that they could be substrings of other strings in the document. To find them, I output a special delimiter character (currently using \032). On page load, we go through the HTML and record the location of the strings, and remove the delimiter.
Unfortunately, most browsers show the delimiter character until we can find and remove them all. I'd like to avoid that if possible. Is there a character or string that will be preserved in the HTML content (so a comment wont work) but wont be visible to the user? It also needs to be something that is fairly unlikely to appear next to a string, so something like wouldn't work either.
EDIT: Sorry, I forgot to mention that the strings will be in attributes, so any sort of tag wont work.
- zero-width non-joiner (see http://htmlhelp.org/reference/html40/entities/special.html)
On the off chance that this already appears in your text, double it up (eg: mytext
Edit in response to comment: works in Firefox 3. Note that you have to search for the Unicode value of the entity.
<html>
<body>
<div id="test">
This is a test
</div>
<script type="application/javascript">
var myDiv = document.getElementById("test");
var content = myDiv.innerHTML;
var pos = content.indexOf("\u200C");
alert(pos);
</script>
</body>
</html>
You could insert them into <span> elements. This will work only for in-page text (not attributes, or the like).
Otherwise, you could insert a whitespace character that your program doesn't already output as part of the HTML, like a tab character (\x09), a vertical tab (\x0b), a bare carriage return (\x0d) — without a newline beside it, ala Windows text encoding — or, just a null byte (\x00).
The best thing that I shall like to insert, which is not visible on the browser, will be a pair of tags with some special id, like <span id="delimiter" class="Delimiter"></span>. This will not show up on the content, while this can be present in the doc. You don't need to remove them.
You could use left-to-right (LTR) marks. Is this for some sort of XSS testing? If so, this might be of interest: Taint support for PHP
Related
My problem occurs when I try to use some data/strings in a p-element.
I start of with data like this:
data: function() {
return {
reportText: {
text1: "This is some subject text",
text2: "This is the conclusion",
}
}
}
I use this data as follows in my (vue-)html:
<p> {{ reportText.text1 }} </p>
<p> {{ reportText.text2 }} </p>
In my browser, when I inspect my elements I get to see the following results:
<p>This is some subject text</p>
<p>This is the conclusion</p>
As you can see, there is suddenly a difference, one p element uses and the other , even though I started of with both strings only using . I know and technically represent the same thingm, but the problem with the string is that it gets treated as a string with 1 large word instead of multiple separate words. This screws up my layout and I can't solve this by using certain css properties (word-wrap etc.)
Other things I have tried:
Tried sanitizing the strings by using .replace( , ), but that doesn't do anything. I assume this is because it basically is the same, so there is nothing to really replace. Same reason why I have to use blockcode on stackoverflow to make the destinction between and .
Logged the data from vue to see if there is any noticeable difference, but I can't see any. If I log the data/reportText I again only see string with 's
So I have the following questions:
Why does this happen? I can't seem to find any logical explanation why it sometimes uses 's and sometimes uses 's, it seems random, but I am sure I am missing something.
Any other things I could try to follow the path my string takes, so I can see where the transformation from to happens?
Per the comments, the solution devised ended up being a simple unicode character replacement targeting the \u00A0 unicode code point (i.e. replacing unicode non-breaking spaces with ordinary spaces):
str.replace(/[\\u00A0]/g, ' ')
Explanation:
JavaScript typically allows the use of unicode characters in two ways: you can input the rendered character directly, or you can use a unicode code point (i.e. in the case of JavaScript, a hexadecimal code prefixed with \u like \u00A0). It has no concept of an HTML entity (i.e. a character sequence between a & and ; like ).
The inspector tool for some browsers, however, utilizes the HTML concept of the HTML entity and will often display unicode characters using their corresponding HTML entities where applicable. If you check the same source code in Chrome's inspector vs. Firefox's inspector (as of writing this answer, anyway), you will see that Chrome uses HTML entities while Firefox uses the rendered character result. While it's a handy feature to be able to see non-printable unicode characters in the inspector, Chrome's use of HTML entities is only a convenience feature, not a reflection of the actual contents of your source code.
With that in mind, we can infer that your source code contains unicode characters in their fully rendered form. Regardless of the form of your unicode character, the fix is identical: you need to target these unicode space characters explicitly and replace them with ordinary spaces.
Below I have an HTML tag, and use JavaScript to extract the value of the widget attribute. This code will alert <test> instead of <test>, so the browser automatically unescapes attribute values:
alert(document.getElementById("hau").attributes[1].value)
<div id="hau" widget="<test>"></div>
My questions are:
Can this behavior be prevented in any way, besides doing a double escape of the attribute contents? (It would look like this: <test>)
Does anyone know why the browser behaves like this? Is there any place in the HTML specs that this behavior is mentioned explicitly?
1) It can be done without doing a double escape
Looks like yours is closer to htmlEncode().
If you don't mind using jQuery
alert(htmlEncode($('#hau').attr('widget')))
function htmlEncode(value){
//create a in-memory div, set it's inner text(which jQuery automatically encodes)
//then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="hau" widget="<test>"></div>
If you're interested in a pure vanilla js solution
alert(htmlEncode(document.getElementById("hau").attributes[1].value))
function htmlEncode( html ) {
return document.createElement( 'a' ).appendChild(
document.createTextNode( html ) ).parentNode.innerHTML;
};
<div id="hau" widget="<test>"></div>
2) Why does the browser behave like this?
Only because of this behaviour, we are able to do a few specific things, such as including quotes inside of a pre-filled input field as shown below, which would not have been possible if the only way to insert " is by adding itself which again would require escaping with another char like \
<input type='text' value=""You 'should' see the double quotes here"" />
The browser unescapes the attribute value as soon as it parses the document (mentioned here). One of the reasons might be that it would otherwise be impossible to include, for example, double quotes in your attribute value (well, technically it would if you put the value in single quotes instead, but then you wouldn't be able to include single quotes in the value).
That said, the behavior cannot be prevented, although if you really must use the value with the HTML entities being part of it, you could simply turn your special characters back into the codes (I recommend Underscore's escape for such task).
I want a page break inside the title attribute of a link, but when I put one in, it appears correct in a browser, but returns 7 errors when I validate it.
This is the code.
<a href="images/Bosses/Lord Yarkan Large.jpg" class="hastipz" target="_blank" title="Lord Yarkan, a level 80 Unique from Silkroad Online -- Click for a Larger Image">
<img class="bosspic" src="images/Bosses/Lord Yarkan.jpg" style="float:right; position:relative;" alt="Lord Yarkon; Silkroad Unique"/>
</a>
The reason is because the title attribute appears in a tooltip, and I need a page break inside that tooltip. How can I add a page break inside the quotes without returning errors?
I found this forum post:
There are two approaches:
1) Use the character entity for a carriage return, which is
Thus:
<...title="Exemplary
website">
(For a full list of character entities, try Googling "HTML Character Codes".)
2) to do any additional styling to your "tooltips", Google "CSS tooltips"
1) is Non-standard though. Works on IE/Chrome, not with Firefox. The new spec appears to recommend
(newline) instead.
Do you need to validate for work?
If not, do not worry about the errors if it works as you want it.
Validation is not the goal. It is a tool to help build better Web sites. which is the goal. ;-)
If you must have it validate, you could try to use some script to switch out a specific keyword / set of characters for a <br /> at dom ready. Although this is untested and I am not sure it wouldn't throw errors, too.
EDIT
As requested, a little jQuery to switch out a word:
$('a').each(function(){
var a = $(this).attr('title');
var b = a.replace('lineBreak','\n');
$(this).attr('title', b);
});
Example: http://jsfiddle.net/jasongennaro/qRQaq/1/
Nb:
I used "lineBreak" as the keyword, as this is unlikely to be matched. "br" might be
I replaced it with the \n line break character.
You should try the \n line break character on its own... might work without needing to replace anything.
From wikipedia:
Cursive (from Latin curro, currere, cucurri, cursum, to run, hasten) is any style of handwriting that is designed for writing notes and letters quickly by hand. In the Arabic, Latin, and Cyrillic writing systems, the letters in a word are connected, making a word one single complex stroke.
In the above languages when we want to format one single word with e.g. <span> tag to apply custom css style it breaks word conection, so is there any solution for this.
example this is for example normal arabic word: كتب
but when we want to color last letter in other color using the span tag get this:
because first two letter are in one tag and last is in other to color it.
Is there something I can do to avoid word breaks.
Here is the full html:
<p>كت<span style="color: Red;">ب</span></p>
I'm not sure if there's any HTML way to do it, but you can fix it by adding a zero-width joiner Unicode character before the opening span tag:
<p>كت<span style="color: Red;">ب</span></p>
You can use the actual Unicode character instead of the HTML character entity, of course, but that wouldn't be visible here. Or you can use the prettier entity.
Here it is in action (using an invisible <b> tag, since I can't do color here), without the joiner:
كتب
and with the joiner:
كتب
It's supposed to work without the joiner as far as I understand it, though, and it does in some browsers, but clearly not all of them.
Update 2020/5
Google Chrome (Checked version 81.0.4044.138) and Firefox (76.0.1) have solved this issue when rendreing Arabic and Farsi words and there is no more need to handle the situation manually. Simply wrap the keyword with <span style="color:red">Keyword</span> works fine with both connecting and non-connecting characters.
For this reason, you probably can not see the difference between Correct and Wrong examples below:
Main post:
After 7 years of accepted answer I would like to add a new answer with more practical details as my native language is Farsi. I assume that we want to replace a keyword within a long word. This answer considers the following details:
1- Sometimes it is not enough to add only to the previous character becase next character should also has a tail to complete the connection.
body{font-size:36pt;}
span{color:red}
Wrong: مک<span>انیک</span>
<br>
Correct: مک<span>انیک</span>
2- We may also need to add after the keyword to connect it to next character.
body{font-size:36pt;}
span{color:red}
Wrong: مک<span>انیک</span>ی
<br>
Correct: مک<span>انیک</span>ی
3- There are some characters that accept tail before but not after. So we have to exclude them from accepting tail after them. This is the list of non-connecting characters to next characters: ا آ د ذ ر ز ژ و
4- Finally to respect search engines and scrappers, I recommend using javascript (jquery) to replace keywords after DOM ready to keep the page source clean.
This is my final code with regards to all details above:
$(document).ready(function(){
var tail="\u200D";
var keyword="ستر";
$(".searchableContent").each(function(){
var htm=$(this).html();
/*
preserve keywords which have space both before and after
with a temp sign say #fullHolder#
*/
htm=htm.split(' '+keyword+' ').join(' #fullHolder# ');
/*
preserve keywords which have only space after
with a temp sign say #preHolder#
*/
htm=htm.split(keyword+' ').join('#preHolder#'+' ');
/*
preserve keywords which have only space before
with a temp sign say #nextHolder#
*/
htm=htm.split(' '+keyword).join(' '+'#nextHolder#');
/*
replace remaining keywords with marked up span.
Add tail to both side of span to make sure it is
connected to both letters before and after
*/
htm=htm.split(keyword).join(tail+'<span style="color:#ff0000">'+tail+keyword+tail+'</span>'+tail);
//Deal #preHolder# by adding tail only before the keyword
htm=htm.split('#preHolder#'+' ').join(tail+'<span style="color:#ff0000">'+tail+keyword+'</span>'+' ');
//Deal #nextHolder# by adding tail only after the keyword
htm=htm.split(' '+'#nextHolder#').join(' '+'<span style="color:#ff0000">'+keyword+tail+'</span>'+tail);
//Deal #fullHolder# by adding markup only without tail
htm=htm.split(' '+'#fullHolder#'+' ').join(' '+'<span style="color:#ff0000">'+keyword+'</span>'+' ');
//Remove all possible combination of added tails to non-connecting characters
var nonConnectings=['ا','آ','د','ذ','ر','ز','ژ','و'];
for (x = 0; x < nonConnectings.length; x++) {
htm=htm.split(nonConnectings[x]+tail).join(nonConnectings[x]);
htm=htm.split(nonConnectings[x]+'<span style="color:#ff0000">'+tail).join(nonConnectings[x]+'<span style="color:#ff0000">');
htm=htm.split(nonConnectings[x]+'</span>'+tail).join(nonConnectings[x]+'</span>');
}
$(this).html(htm);
})
})
div{font-size:26pt}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="searchableContent">
سترون - بستری - آستر - بستر - استراحت
</div>
escaping html is fine - it will remove <'s and >'s etc.
ive run into a problem where i am outputting a filename inside a comment tag eg. <!-- ${filename} -->
of course things can be bad if you dont escape, so it becomes:
<!-- <c:out value="${filename}"/> -->
the problem is that if the file has "--" in the name, all the html gets screwed, since youre not allowed to have <!-- -- -->.
the standard html escape doesnt escape these dashes, and i was wondering if anyone is familiar with a simple / standard way to escape them.
Definition of a HTML comment:
A comment declaration starts with <!, followed by zero or more comments, followed by >. A comment starts and ends with "--", and does not contain any occurrence of "--".
Of course the parsing of a comment is up to the browser.
Nothing strikes me as an obvious solution here, so I'd suggest you str_replace those double dashes out.
There is no good way to solve this. You can't just escape them because comments are read in plaintext. You will have to do something like put a space between the hyphens, or use some sort of code for hyphens (like [HYPHEN]).
Since it is obvoius that you cannnot directly display the '--'s you can either encode them or use the fn:escapeXml or fn:replace tags for appropriate replacements.
JSTL documentation
There's no universal working way to escape those characters in html unless the - characters are in multiples of four so if you do -- it wont work in firefox but ---- will work. So it all depends on the browser. For Example, looking at Internet Explorer 8, it is not a problem, those characters are escaped properly. The same goes for Googles Chrome... However Firefox even the latest browser (3.0.4), it doesn't handle escaping of these characters well.
You shouldn't be trying to HTML-escape, the contents of comments are not escapable and it's fine to have a bare ‘>’ or ‘&’ inside.
‘--’ is its own, unrelated problem and is not really fixable. If you don't need to recover the exact string, just do a replacement to get rid of them (eg. replace with ‘__’).
If you do need to get a string through completely unmolested to a JavaScript that will be reading the contents of the comment, use a string literal:
<!-- 'my-string' -->
which the script can then read using eval(commentnode.data). (Yes, a valid use for eval() at last!)
Then your escaping problem becomes how to put things in JS string literals, which is fairly easily solvable by escaping the ‘'’ and ‘-’ characters:
<!-- 'Bob\x27s\x2D\x2Dstring' -->
(You should probably also escape ‘<’, ‘&’ and ‘"’, in case you ever want to use the same escaping scheme to put a JS string literal inside a <script> block or inline handler.)