Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Commit 6c38b86

Browse files
author
mikesamuel
committed
fixes for Safari 2.0
1 parent 3b9588d commit 6c38b86

File tree

2 files changed

+90
-48
lines changed

2 files changed

+90
-48
lines changed

src/prettify.js

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ var PR_keywords = new Object();
7575
var PERL_KEYWORDS = (
7676
"foreach require sub unless until use elsif BEGIN END");
7777
var SH_KEYWORDS = (
78-
"if then do else fi end");
78+
"if then do done else fi end");
7979
var RUBY_KEYWORDS = (
8080
"if then elsif else end begin do rescue ensure while for class module " +
8181
"def yield raise until unless and or not when case super undef break " +
@@ -240,9 +240,85 @@ function PR_prefixMatch(chars, len, prefix) {
240240
return true;
241241
}
242242

243-
/** used to convert html special characters embedded in XMP tags into html. */
243+
/** like textToHtml but escapes double quotes to be attribute safe. */
244+
function PR_attribToHtml(str) {
245+
return str.replace(/&/g, '&')
246+
.replace(/</g, '&lt;')
247+
.replace(/>/g, '&gt;')
248+
.replace(/"/g, '&quot;')
249+
.replace(/\xa0/, '&nbsp;');
250+
}
251+
252+
/** escapest html special characters to html. */
244253
function PR_textToHtml(str) {
245-
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
254+
return str.replace(/&/g, '&amp;')
255+
.replace(/</g, '&lt;')
256+
.replace(/>/g, '&gt;')
257+
.replace(/\xa0/g, '&nbsp;');
258+
}
259+
260+
/** is the given node's innerHTML normally unescaped? */
261+
function PR_isRawContent(node) {
262+
return 'XMP' == node.tagName;
263+
}
264+
265+
var PR_innerHtmlWorks = null;
266+
function PR_getInnerHtml(node) {
267+
// inner html is hopelessly broken in Safari 2.0.4 when the content is
268+
// an html description of well formed XML and the containing tag is a PRE
269+
// tag, so we detect that case and emulate innerHTML.
270+
if (null == PR_innerHtmlWorks) {
271+
var testNode = document.createElement('PRE');
272+
testNode.appendChild(
273+
document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />'));
274+
PR_innerHtmlWorks = !/</.test(testNode.innerHTML);
275+
}
276+
277+
if (PR_innerHtmlWorks) {
278+
var content = node.innerHTML;
279+
// XMP tags contain unescaped entities so require special handling.
280+
if (PR_isRawContent(node)) {
281+
content = PR_textToHtml(html);
282+
}
283+
return content;
284+
}
285+
286+
var out = [];
287+
for (var child = node.firstChild; child; child = child.nextSibling) {
288+
PR_normalizedHtml(child, out);
289+
}
290+
return out.join('');
291+
}
292+
293+
/**
294+
* walks the DOM returning a properly escaped version of innerHTML.
295+
*/
296+
function PR_normalizedHtml(node, out) {
297+
switch (node.nodeType) {
298+
case 1: // an element
299+
var name = node.tagName.toLowerCase();
300+
out.push('\074', name);
301+
for (var i = 0; i < node.attributes.length; ++i) {
302+
var attr = node.attributes[i];
303+
if (!attr.specified) { continue; }
304+
out.push(' ');
305+
PR_normalizedHtml(attr, out);
306+
}
307+
out.push('>');
308+
for (var child = node.firstChild; child; child = child.nextSibling) {
309+
PR_normalizedHtml(child, out);
310+
}
311+
if (node.firstChild || !/^(?:br|link|img)$/.test(name)) {
312+
out.push('<\/', name, '>');
313+
}
314+
break;
315+
case 2: // an attribute
316+
out.push(node.name.toLowerCase(), '="', PR_attribToHtml(node.value), '"');
317+
break;
318+
case 3: case 4: // text
319+
out.push(PR_textToHtml(node.nodeValue));
320+
break;
321+
}
246322
}
247323

248324

@@ -1302,22 +1378,17 @@ function prettyPrint() {
13021378
}
13031379
}
13041380
if (!nested) {
1305-
// XMP tags contain unescaped entities so require special handling.
1306-
var isRawContent = 'XMP' == cs.tagName;
1307-
13081381
// fetch the content as a snippet of properly escaped HTML.
13091382
// Firefox adds newlines at the end.
1310-
var content = cs.innerHTML.replace(/(?:\r\n?|\n)$/, '');
1383+
var content = PR_getInnerHtml(cs);
1384+
content = content.replace(/(?:\r\n?|\n)$/, '');
13111385
if (!content) { continue; }
1312-
if (isRawContent) {
1313-
content = PR_textToHtml(content);
1314-
}
13151386

13161387
// do the pretty printing
13171388
var newContent = prettyPrintOne(content);
13181389

13191390
// push the prettified html back into the tag.
1320-
if (!isRawContent) {
1391+
if (PR_isRawContent(cs)) {
13211392
// just replace the old html with the new
13221393
cs.innerHTML = newContent;
13231394
} else {

tests/prettify_test.html

Lines changed: 8 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ <h1>Whitespace</h1>
316316
'&nbsp; &nbsp; a`END`PUN=`END`PLN$`END`PUN((`END`PLN $a `END`PUN+`END' +
317317
'`PLN $b `END`PUN))`END`PLN<br>' +
318318
'&nbsp; &nbsp; b`END`PUN=`END`PLN$tmp<br>' +
319-
'&nbsp; done<br>' +
319+
'&nbsp; `END`KWDdone`END`PLN<br>' +
320320
'`END`PUN}`END`PLN<br>' +
321321
'<br>' +
322322
'`END`COM# output the 10th element of the series and halt`END`PLN<br>' +
@@ -696,51 +696,22 @@ <h1>Whitespace</h1>
696696
.replace(/\xa0/g, '&nbsp;');
697697
}
698698

699-
/** convert a plain text string to html by escaping html special chars. */
700-
function htmlDQSafe(plainText) {
701-
return plainText.replace(/\046/g, '&amp;')
702-
.replace(/\074/g, '&lt;')
703-
.replace(/\076/g, '&gt;')
704-
.replace(/\xa0/g, '&nbsp;');
705-
}
706-
707699
/**
708700
* get normalized markup. innerHTML varies enough across browsers that we
709701
* can't use it.
710702
*/
711703
function normalizedInnerHtml(node, opt_out) {
712704
var out = [];
713705
for (var child = node.firstChild; child; child = child.nextSibling) {
714-
normalizedHtml(child, out);
706+
PR_normalizedHtml(child, out);
715707
}
716-
return out.join('');
717-
}
718-
function normalizedHtml(node, out) {
719-
switch (node.nodeType) {
720-
case 1: // an element
721-
var name = node.tagName.toLowerCase();
722-
out.push('\074', name);
723-
for (var i = 0; i < node.attributes.length; ++i) {
724-
var attr = node.attributes[i];
725-
if (!attr.specified) { continue; }
726-
out.push(' ');
727-
normalizedHtml(attr, out);
728-
}
729-
out.push('>');
730-
for (var child = node.firstChild; child; child = child.nextSibling) {
731-
normalizedHtml(child, out);
732-
}
733-
if (node.firstChild || !/^(?:br|link|img)$/.test(name)) {
734-
out.push('<\/', name, '>');
735-
}
736-
break;
737-
case 2: // an attribute
738-
out.push(node.name.toLowerCase(), '="', htmlDQSafe(node.value), '"');
739-
break;
740-
case 3: case 4: // text
741-
out.push(htmlDQSafe(node.nodeValue));
742-
break;
708+
out = out.join('');
709+
// more normalization to work around problems with non-ascii chars in
710+
// regexps in Safari
711+
for (var i = 0; (i = out.indexOf('\xa0')) >= 0;) {
712+
out = out.substring(0, i) + '&nbsp;' + out.substring(i + 1);
743713
}
714+
return out;
744715
}
745716

746717
var htmlOut = [];

0 commit comments

Comments
 (0)