Created
October 20, 2015 08:31
-
-
Save zcorpan/17ab08f86cdbf6c0d531 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<meta charset=utf-8> | |
<script src=https://w3c-test.org/resources/testharness.js></script> | |
<script> | |
function collectCharacters(input, pos, chars) { | |
var startPos = pos; | |
while (chars.indexOf(input[pos]) != -1) { | |
pos++; | |
if (input[pos] === undefined) { | |
break; | |
} | |
} | |
return [input.substr(startPos, pos), pos]; | |
} | |
var spaceCharacters = [' ', '\t', '\n', '\f', '\r']; | |
var asciiDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']; | |
function skipWhitespace(input, pos) { | |
return collectCharacters(input, pos, spaceCharacters); | |
} | |
function parseMetaRefresh(input) { | |
var time = 0; | |
var url = ''; | |
// If another meta element with an http-equiv attribute in the Refresh state has | |
// already been successfully processed (i.e. when it was inserted the user agent | |
// processed it and reached the last step of this list of steps), then abort these | |
// steps. | |
// | |
// If the meta element has no content attribute, or if that attribute's value is | |
// the empty string, then abort these steps. | |
if (input === '') { | |
return []; | |
} | |
// Let input be the value of the element's content attribute. | |
// | |
// Let position point at the first character of input. | |
var pos = 0; | |
// Skip whitespace. | |
[, pos] = skipWhitespace(input, pos); | |
// Collect a sequence of characters that are ASCII digits, and parse the resulting | |
// string using the rules for parsing non-negative integers. If the sequence of | |
// characters collected is the empty string, then no number will have been parsed; | |
// abort these steps. Otherwise, let time be the parsed number. | |
var digits; | |
[digits, pos] = collectCharacters(input, pos, asciiDigits); | |
if (digits === '') { | |
return []; | |
} | |
var time = parseInt(digits, 10); | |
// Collect a sequence of characters that are ASCII digits and U+002E FULL STOP | |
// characters (.). Ignore any collected characters. | |
[, pos] = collectCharacters(input, pos, [...asciiDigits, '.']); | |
// Let url be the address of the current page. | |
url = null; | |
// If position is past the end of input, jump to the last step. | |
lastStep: { | |
if (input[pos] === undefined) { | |
break lastStep; | |
} | |
// If the character in input pointed to by position is not a U+003B SEMICOLON | |
// character (;), a U+002C COMMA character (,), or a space character, then abort | |
// these steps. | |
if ([';', ',', ...spaceCharacters].indexOf(input[pos]) == -1) { | |
return []; | |
} | |
// Skip whitespace. | |
[, pos] = skipWhitespace(input, pos); | |
// If the character in input pointed to by position is a U+003B SEMICOLON character | |
// (;), a U+002C COMMA character (,), then advance position to the next character. | |
if ([';', ','].indexOf(input[pos]) != -1) { | |
pos++; | |
} | |
// Skip whitespace. | |
[, pos] = skipWhitespace(input, pos); | |
// If position is past the end of input, jump to the last step. | |
if (input[pos] === undefined) { | |
break lastStep; | |
} | |
// Let url be equal to the substring of input from the character at position to the | |
// end of the string. | |
url = input.substr(pos); | |
trim : { | |
skipQuotes : { | |
// If the character in input pointed to by position is a U+0055 LATIN CAPITAL | |
// LETTER U character (U) or a U+0075 LATIN SMALL LETTER U character (u), then | |
// advance position to the next character. Otherwise, jump to the step labeled skip | |
// quotes. | |
if (['U', 'u'].indexOf(input[pos]) != -1) { | |
pos++; | |
} else { | |
break skipQuotes; | |
} | |
// If the character in input pointed to by position is a U+0052 LATIN CAPITAL | |
// LETTER R character (R) or a U+0072 LATIN SMALL LETTER R character (r), then | |
// advance position to the next character. Otherwise, jump to the step labeled | |
// trim. | |
if (['R', 'r'].indexOf(input[pos]) != -1) { | |
pos++; | |
} else { | |
break trim; | |
} | |
// If the character in input pointed to by position is s U+004C LATIN CAPITAL | |
// LETTER L character (L) or a U+006C LATIN SMALL LETTER L character (l), then | |
// advance position to the next character. Otherwise, jump to the step labeled | |
// trim. | |
if (['L', 'l'].indexOf(input[pos]) != -1) { | |
pos++; | |
} else { | |
break trim; | |
} | |
// Skip whitespace. | |
[, pos] = skipWhitespace(input, pos); | |
// If the character in input pointed to by position is a U+003D EQUALS SIGN (=), | |
// then advance position to the next character. Otherwise, jump to the step labeled | |
// trim. | |
if (input[pos] === '=') { | |
pos++; | |
} else { | |
break trim; | |
} | |
// Skip whitespace. | |
[, pos] = skipWhitespace(input, pos); | |
} // end label skipQuotes | |
// Skip quotes: If the character in input pointed to by position is either a U+0027 | |
// APOSTROPHE character (') or U+0022 QUOTATION MARK character ("), then let quote | |
// be that character, and advance position to the next character. Otherwise, let | |
// quote be the empty string. | |
var quote = ''; | |
if (['\'', '"'].indexOf(input[pos]) != -1) { | |
quote = input[pos]; | |
pos++; | |
} | |
// Let url be equal to the substring of input from the character at position to the | |
// end of the string. | |
url = input.substr(pos); | |
// If quote is not the empty string, and there is a character in url equal to | |
// quote, then truncate url at that character, so that it and all subsequent | |
// characters are removed. | |
if (quote !== '' && url.indexOf(quote) != -1) { | |
url = url.substr(0, url.indexOf(quote)); | |
} | |
} // end label trim | |
// Trim: Strip any trailing space characters from the end of url. | |
url = url.replace(new RegExp('[' + spaceCharacters.join('') + ']+$'), ''); | |
// Strip any U+0009 CHARACTER TABULATION (tab), U+000A LINE FEED (LF), and U+000D | |
// CARRIAGE RETURN (CR) characters from url. | |
url = url.replace(/[\t\n\r]/g, ''); | |
// Resolve the url value to an absolute URL, relative to the meta element. If this | |
// fails, abort these steps. | |
} // end label lastStep | |
// Perform one or more of the following steps: | |
// | |
// ... | |
return [time, url]; | |
} | |
// failure is [] | |
// success is [time, url] where url is unresolved, and null means document's current address | |
var tests = [ | |
{input: '', expected: []}, | |
{input: '1', expected: [1, null]}, | |
{input: '1;', expected: [1, null]}, | |
{input: '1,', expected: [1, null]}, | |
{input: '1; url=foo', expected: [1, 'foo']}, | |
{input: '1, url=foo', expected: [1, 'foo']}, | |
{input: '1 url=foo', expected: [1, 'foo']}, | |
{input: '1url=foo', expected: []}, | |
{input: '1x;url=foo', expected: []}, | |
{input: '1 x;url=foo', expected: [1, 'x;url=foo']}, | |
{input: '1;;url=foo', expected: [1, ';url=foo']}, | |
{input: ' 1 ; url = foo', expected: [1, 'foo']}, | |
{input: '1; url=foo ', expected: [1, 'foo']}, | |
{input: '1; url=f\to\no', expected: [1, 'foo']}, | |
{input: '1; url="foo"bar', expected: [1, 'foo']}, | |
{input: '1; url=\'foo\'bar', expected: [1, 'foo']}, | |
{input: '1; url="foo\'bar', expected: [1, 'foo\'bar']}, | |
{input: '1; url foo', expected: [1, 'url foo']}, | |
{input: '1; urlfoo', expected: [1, 'urlfoo']}, | |
{input: '1; urfoo', expected: [1, 'urfoo']}, | |
{input: '1; ufoo', expected: [1, 'ufoo']}, | |
{input: '1; "foo"bar', expected: [1, 'foo']}, | |
{input: '; foo', expected: []}, | |
{input: ', foo', expected: []}, | |
{input: 'foo', expected: []}, | |
{input: '+1; url=foo', expected: []}, | |
{input: '-1; url=foo', expected: []}, | |
{input: '-0; url=foo', expected: []}, | |
{input: '1.9; url=foo', expected: [1, 'foo']}, | |
{input: '1.9..5.; url=foo', expected: [1, 'foo']}, | |
{input: '.9; url=foo', expected: []}, | |
]; | |
tests.forEach(function(t) { | |
test(function() { | |
assert_array_equals(parseMetaRefresh(t.input), t.expected); | |
}, format_value(t.input)); | |
}); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment