forked from hermwong/Wikipedia
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add stub .properties file parser/reader, QUnit tests for it.
- Loading branch information
Showing
5 changed files
with
2,174 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/** | ||
* Copyright (c) Brion Vibber 2011 | ||
* Written initially for Wikipedia Mobile app | ||
* | ||
* Reader for Java-style .properties files to be used for | ||
* l10n message files. | ||
* | ||
* http://download.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 | ||
*/ | ||
|
||
propertiesFileReader = window.propertiesFileReader = { | ||
/** | ||
* @param string data: full string of source file | ||
* @return Object: map of keys to strings | ||
* @throws Error on invalid input format | ||
*/ | ||
parse: function(text) { | ||
if (typeof text !== "string") { | ||
throw new Error("Non-string passed to propertiesFileReader.parse"); | ||
} | ||
var data = {}, | ||
lines = text.split(/\r?\n/), | ||
blank = /^\s*$/, | ||
comment = /^\s*[#!]/, | ||
keyonly = /^\s*([^=:\s]+)\s*()$/, | ||
keyval = /^\s*([^=:\s]+)(?:\s*[=:]\s*|\s+)(.*)$/, | ||
continued = /^\s*(.*)$/; | ||
for (var i = 0; i < lines.length; i++) { | ||
var line = lines[i]; | ||
if (line.match(blank)) { | ||
continue; | ||
} | ||
if (line.match(comment)) { | ||
continue; | ||
} | ||
var matches = line.match(keyonly) || line.match(keyval); | ||
if (matches) { | ||
var key = matches[1], | ||
val = matches[2]; | ||
|
||
while (val.substr(-1, 1) == "\\") { | ||
// Line continuation | ||
i++; | ||
if (i >= lines.length) { | ||
throw new Error("Line continuation at end of file at line " + i); | ||
} | ||
line = lines[i]; | ||
if (matches = line.match(continued)) { | ||
val = val.substr(0, val.length - 1) + matches[1]; | ||
} else { | ||
throw new Error("Invalid line after line continuation at line " + i); | ||
} | ||
} | ||
|
||
data[key] = propertiesFileReader.unescape(val); | ||
|
||
continue; | ||
} | ||
throw new Error("Invalid .properties format at line " + (i + 1) + ": " + line); | ||
} | ||
return data; | ||
}, | ||
|
||
unescape: function(str) { | ||
// @fixme add \u escapes -- won't be used in our files though | ||
str = str.replace(/\\n/g, "\n"); | ||
str = str.replace(/\\t/g, "\t"); | ||
str = str.replace(/\\(.)/g, "$1"); | ||
return str; | ||
} | ||
}; | ||
|
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<title>QUnit Test Suite</title> | ||
|
||
<!-- QUnit libs --> | ||
<link rel="stylesheet" href="qunit.css" type="text/css" media="screen"> | ||
<script type="text/javascript" src="qunit.js"></script> | ||
|
||
<!-- Modules to test... --> | ||
<script type="text/javascript" src="../../assets/www/js/propertiesFileReader.js"></script> | ||
|
||
<!-- Test cases --> | ||
<script type="text/javascript" src="propertiesFileReader-test.js"></script> | ||
|
||
</head> | ||
<body> | ||
<h1 id="qunit-header">QUnit Test Suite</h1> | ||
<h2 id="qunit-banner"></h2> | ||
<div id="qunit-testrunner-toolbar"></div> | ||
<h2 id="qunit-userAgent"></h2> | ||
<ol id="qunit-tests"></ol> | ||
<div id="qunit-fixture">test markup</div> | ||
</body> | ||
</html> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
test('Is module obj defined?', function() { | ||
expect(1); | ||
ok(typeof propertiesFileReader === "object"); | ||
}); | ||
|
||
function parseEqual(message, input, expected) { | ||
deepEqual(propertiesFileReader.parse(input), expected, message); | ||
} | ||
|
||
test('Can parse very simple input?', function() { | ||
parseEqual( | ||
"Single line, no newline", | ||
"key=value", | ||
{ | ||
key: "value" | ||
} | ||
); | ||
parseEqual( | ||
"Three simple lines, no final newline", | ||
"key=value\nkey2=value2\nkey3=value3", | ||
{ | ||
key: "value", | ||
key2: "value2", | ||
key3: "value3" | ||
} | ||
); | ||
}); | ||
|
||
test('Can ignore blank/empty lines?', function() { | ||
parseEqual( | ||
"Single line with newline", | ||
"key=value\n", | ||
{ | ||
key: "value" | ||
} | ||
); | ||
parseEqual( | ||
"Three simple lines, some extra newlines", | ||
"\n\nkey=value\nkey2=value2\n\nkey3=value3\n", | ||
{ | ||
key: "value", | ||
key2: "value2", | ||
key3: "value3" | ||
} | ||
); | ||
parseEqual( | ||
"Real lines around a blank empty line", | ||
"key=value\n\nkey2=value2", | ||
{ | ||
key: "value", | ||
key2: "value2", | ||
} | ||
); | ||
parseEqual( | ||
"Real lines around a line of spaces", | ||
"key=value\n \nkey2=value2", | ||
{ | ||
key: "value", | ||
key2: "value2", | ||
} | ||
); | ||
parseEqual( | ||
"Real lines around a line of tabs", | ||
"key=value\n\t\t\t\nkey2=value2", | ||
{ | ||
key: "value", | ||
key2: "value2", | ||
} | ||
); | ||
parseEqual( | ||
"Real lines around a line of form feeds", | ||
"key=value\n\f\f\f\nkey2=value2", | ||
{ | ||
key: "value", | ||
key2: "value2", | ||
} | ||
); | ||
}); | ||
|
||
test('Can ignore comment lines?', function() { | ||
parseEqual( | ||
"Three simple lines, one commented out with #", | ||
"#key=value\nkey2=value2\nkey3=value3", | ||
{ | ||
key2: "value2", | ||
key3: "value3" | ||
} | ||
); | ||
parseEqual( | ||
"Three simple lines, one commented out with !", | ||
"key=value\n!key2=value2\nkey3=value3", | ||
{ | ||
key: "value", | ||
key3: "value3" | ||
} | ||
); | ||
parseEqual( | ||
"Three simple lines, one commented out with # after spaces", | ||
" #key=value\nkey2=value2\nkey3=value3", | ||
{ | ||
key2: "value2", | ||
key3: "value3" | ||
} | ||
); | ||
parseEqual( | ||
"Three simple lines, one commented out with ! after spaces", | ||
"key=value\n !key2=value2\nkey3=value3", | ||
{ | ||
key: "value", | ||
key3: "value3" | ||
} | ||
); | ||
}); | ||
|
||
test('Key format', function() { | ||
var keyEqual = function(message, input) { | ||
// All these tests end the same. :) | ||
parseEqual(message, input, { key: "value" }); | ||
}; | ||
keyEqual( | ||
"Simple key", | ||
"key=value" | ||
); | ||
keyEqual( | ||
"Simple key with preceding whitespace", | ||
" key=value" | ||
); | ||
keyEqual( | ||
"Simple key with preceding whitespace (tab)", | ||
"\tkey=value" | ||
); | ||
keyEqual( | ||
"Simple key with following whitespace", | ||
"key =value" | ||
); | ||
keyEqual( | ||
"Simple key with preceding and following whitespace", | ||
" key =value" | ||
); | ||
keyEqual( | ||
"Key with : as sep", | ||
"key:value" | ||
); | ||
keyEqual( | ||
"Key with space as sep", | ||
"key value" | ||
); | ||
}); | ||
|
||
test('Whitespace examples from doc', function() { | ||
// http://download.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 | ||
var keyEqual = function(input) { | ||
// All these tests end the same. :) | ||
parseEqual(input, input, { Truth: "Beauty" }); | ||
}; | ||
keyEqual("Truth = Beauty"); | ||
keyEqual(" Truth:Beauty"); | ||
keyEqual("Truth :Beauty"); | ||
}); | ||
|
||
test('Line extension and whitespace example from doc', function() { | ||
// http://download.oracle.com/javase/7/docs/api/java/util/Properties.html#load%28java.io.Reader%29 | ||
parseEqual( | ||
"Line extension & ignore initial whitespace on following lines", | ||
"fruits apple, banana, pear, \\\n" + | ||
" cantaloupe, watermelon, \\\n" + | ||
" kiwi, mango", | ||
{ | ||
fruits: "apple, banana, pear, cantaloupe, watermelon, kiwi, mango" | ||
} | ||
); | ||
}); | ||
|
||
test('Empty value with no separator; doc example', function() { | ||
parseEqual( | ||
"Line with no value & no separator", | ||
"cheeses", | ||
{ | ||
cheeses: "" | ||
} | ||
); | ||
}); | ||
|
||
test('Escapes', function() { | ||
parseEqual( | ||
"\\n", | ||
"key=Foo\\nbar", | ||
{ | ||
key: "Foo\nbar" | ||
} | ||
); | ||
parseEqual( | ||
"\\t", | ||
"key=Foo\\tbar", | ||
{ | ||
key: "Foo\tbar" | ||
} | ||
); | ||
parseEqual( | ||
"\\\\", | ||
"key=Foo\\\\bar", | ||
{ | ||
key: "Foo\\bar" | ||
} | ||
); | ||
parseEqual( | ||
"\\b (b, not backspace)", | ||
"key=Foo\\bbar", | ||
{ | ||
key: "Foobbar" | ||
} | ||
); | ||
parseEqual( | ||
"\\z (z, not ctrl+z)", | ||
"key=Foo\\zbar", | ||
{ | ||
key: "Foozbar" | ||
} | ||
); | ||
parseEqual( | ||
"\\n (multiple)", | ||
"key=Foo\\nbar\\nbaz\\nbing", | ||
{ | ||
key: "Foo\nbar\nbaz\nbing" | ||
} | ||
); | ||
}); | ||
|
||
test('Small sample file', function() { | ||
parseEqual('Small sample file', | ||
"# English-language messages for Wikipedia Mobile app\n" + | ||
"sitename = Wikipedia\n" + | ||
"spinner-loading = Loading\n" + | ||
"spinner-retrieving = Retrieving content from $1\n" + | ||
"bookmarks-max-warning = You've reached the maximum number of bookmarks.\n" + | ||
"bookmark-added = $1 added to bookmarks.\n" + | ||
"bookmark-exists $1 already exists in bookmarks.\n" + | ||
"bookmark-remove-prompt = Remove $1 from bookmarks?\n" + | ||
"bookmark-removed = $1 has been removed.\n", | ||
{ | ||
'sitename': 'Wikipedia', | ||
'spinner-loading': 'Loading', | ||
'spinner-retrieving': 'Retrieving content from $1', | ||
'bookmarks-max-warning': "You've reached the maximum number of bookmarks.", | ||
'bookmark-added': "$1 added to bookmarks.", | ||
'bookmark-exists': "$1 already exists in bookmarks.", | ||
'bookmark-remove-prompt': "Remove $1 from bookmarks?", | ||
'bookmark-removed': "$1 has been removed." | ||
} | ||
); | ||
}); | ||
|
||
|
Oops, something went wrong.