Inital Commit

This commit is contained in:
Zeke Sonxx 2014-09-29 19:40:13 -04:00
commit f8c7ae5776
13 changed files with 376 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
npm-debug.log

8
.jshintrc Normal file
View File

@ -0,0 +1,8 @@
{
"globalstrict": true,
"node": true,
"undef": true,
"indent": 2,
"quotmark": "single",
"predef": ["describe", "it", "before", "beforeEach", "after", "afterEach"]
}

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Zeke Sonxx <github.com/zekesonxx>
Permission is hereby granted, free of charge, to any pony obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit ponies to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# wow-toc
World Of Warcraft addon `.toc` file parser. Written in Node.js.
Built on the documentation at [Wowpedia](http://wowpedia.org/TOC_format).
## Usage
`$ npm install wow-toc`
````js
var wowtoc = require('wow-toc');
var k = wowtoc.parse(fs.readFileSync('somefile.toc'));
wowtoc.stringify(k);
````
## Notes / Caveats
* Does not acknowledge `#@no-lib-strip@`/`#@end-no-lib-strip@`
* `Dependencies`/`OptionalDeps`/etc remain strings (easy to convert to arrays anyways)
* Doesn't validate tag names (`## Bacon: Strip` is valid to it but not to WoW)
## License
MIT. See `LICENSE`

62
lib/index.js Normal file
View File

@ -0,0 +1,62 @@
/**
* World Of Warcraft Addon .toc file parser
* Based on the documentation at http://wowpedia.org/TOC_format
* @author Zeke Sonxx <github.com/zekesonxx>
* @license MIT
*/
'use strict';
var debug = require('debug')('wow-toc');
exports.parse = function(input) {
if (typeof input !== 'string') {
throw new Error('wowtoc.parse input must be a string, got '+typeof input);
}
var lines = input.split(/\r*\n/); //allow Windows newlines
debug('Got input, '+lines.length+' lines');
var out = {
tags: {},
files: []
};
lines.forEach(function(line) {
if (line.length > 1024) {
//WoW only reads the first 1024 lines
debug('Line is longer than 1024 characters, trunicating to be like WoW');
line = line.substr(0, 1024);
}
if (line.substr(0, 2) === '##') { //## Title: Recount
debug('Line is tag: '+line);
var tag = line.substr(2, line.indexOf(':')).trim().replace(':', '');
var value = line.substr(line.indexOf(':')+1, line.length).trim();
debug('`'+tag+'` : `'+value+'`');
out.tags[tag] = value;
} else if (line.substr(0, 1) === '#') { //#bug not feature
debug('Line is comment: '+line);
} else { // recount.lua
//file loading
debug('Line is file: '+line);
if (line.trim() !== '') {
out.files.push(line.trim());
}
}
});
return out;
};
exports.stringify = function(input) {
if (typeof input !== 'object') {
throw new TypeError('wowtoc.stringify input must be an object, got '+typeof input);
}
var out = [];
for(var tag in input.tags) {
if(input.tags.hasOwnProperty(tag)) {
out.push('## '+tag+': '+input.tags[tag]);
}
}
(input.files || []).forEach(function(file) {
out.push(file);
});
return out.join('\n');
};

31
package.json Normal file
View File

@ -0,0 +1,31 @@
{
"name": "wow-toc",
"version": "0.1.0",
"description": "World Of Warcraft addon toc file parser",
"main": "lib/index.js",
"scripts": {
"test": "node node_modules/mocha/bin/_mocha -R spec"
},
"repository": {
"type": "git",
"url": "https://github.com/zekesonxx/wow-toc"
},
"keywords": [
"wow",
"toc",
"parser"
],
"author": "Zeke Sonxx <github.com/zekesonxx>",
"license": "MIT",
"bugs": {
"url": "https://github.com/zekesonxx/wow-toc/issues"
},
"homepage": "https://github.com/zekesonxx/wow-toc",
"dependencies": {
"debug": "^2.0.0"
},
"devDependencies": {
"mocha": "^1.21.4",
"should": "^4.0.4"
}
}

58
test/fixtures/Recount.json vendored Normal file
View File

@ -0,0 +1,58 @@
{
"files" : [
"embeds.xml",
"locales\\Recount-enUS.lua",
"locales\\Recount-deDE.lua",
"locales\\Recount-esES.lua",
"locales\\Recount-esMX.lua",
"locales\\Recount-frFR.lua",
"locales\\Recount-ptBR.lua",
"locales\\Recount-ruRU.lua",
"locales\\Recount-koKR.lua",
"locales\\Recount-zhTW.lua",
"locales\\Recount-zhCN.lua",
"Recount.lua",
"Fonts.lua",
"colors.lua",
"Widgets.lua",
"WindowOrder.lua",
"Fights.lua",
"Recount_Modes.lua",
"TrackerModules\\TrackerModule_Dispels.lua",
"TrackerModules\\TrackerModule_Interrupts.lua",
"TrackerModules\\TrackerModule_Resurrection.lua",
"TrackerModules\\TrackerModule_CCBreakers.lua",
"TrackerModules\\TrackerModule_PowerGains.lua",
"Tracker.lua",
"roster.lua",
"LazySync.lua",
"deletion.lua",
"zonefilters.lua",
"debug.lua",
"GUI_Main.lua",
"GUI_Detail.lua",
"GUI_DeathGraph.lua",
"GUI_Graph.lua",
"GUI_Reset.lua",
"GUI_Report.lua",
"GUI_Config.lua",
"GUI_Realtime.lua"
],
"tags" : {
"Author" : "Cryect, ported to 2.4 by Elsia, maintained by Resike from 5.4",
"Interface" : "50400",
"Notes" : "Records Damage and Healing for Graph Based Display.",
"Notes-ruRU" : "Записывает урон и исцеления и отоброжает различные графики.",
"Notes-zhCN" : "基于 Graph 裤开发的伤害/治疗统计插件.",
"Notes-zhTW" : "圖形化顯示的傷害/治療統計插件.",
"OptionalDeps" : "Ace3, LibDropdown-1.0, LibSharedMedia-3.0, LibBossIDs-1.0, LibGraph-2.0",
"SavedVariables" : "RecountDB",
"SavedVariablesPerCharacter" : "RecountPerCharDB",
"Title" : "Recount",
"Version" : "r1269",
"X-Curse-Packaged-Version" : "r1269",
"X-Curse-Project-ID" : "recount",
"X-Curse-Project-Name" : "Recount",
"X-Curse-Repository-ID" : "wow/recount/mainline"
}
}

60
test/fixtures/Recount.toc vendored Normal file
View File

@ -0,0 +1,60 @@
## Interface: 50400
## Version: r1269
## Title: Recount
## Notes: Records Damage and Healing for Graph Based Display.
## Notes-ruRU: Записывает урон и исцеления и отоброжает различные графики.
## Notes-zhCN: 基于 Graph 裤开发的伤害/治疗统计插件.
## Notes-zhTW: 圖形化顯示的傷害/治療統計插件.
## Author: Cryect, ported to 2.4 by Elsia, maintained by Resike from 5.4
## OptionalDeps: Ace3, LibDropdown-1.0, LibSharedMedia-3.0, LibBossIDs-1.0, LibGraph-2.0
## SavedVariables: RecountDB
## SavedVariablesPerCharacter: RecountPerCharDB
## X-Curse-Packaged-Version: r1269
## X-Curse-Project-Name: Recount
## X-Curse-Project-ID: recount
## X-Curse-Repository-ID: wow/recount/mainline
#@no-lib-strip@
embeds.xml
#@end-no-lib-strip@
locales\Recount-enUS.lua
locales\Recount-deDE.lua
locales\Recount-esES.lua
locales\Recount-esMX.lua
locales\Recount-frFR.lua
locales\Recount-ptBR.lua
locales\Recount-ruRU.lua
locales\Recount-koKR.lua
locales\Recount-zhTW.lua
locales\Recount-zhCN.lua
Recount.lua
Fonts.lua
colors.lua
Widgets.lua
WindowOrder.lua
Fights.lua
Recount_Modes.lua
TrackerModules\TrackerModule_Dispels.lua
TrackerModules\TrackerModule_Interrupts.lua
TrackerModules\TrackerModule_Resurrection.lua
TrackerModules\TrackerModule_CCBreakers.lua
TrackerModules\TrackerModule_PowerGains.lua
Tracker.lua
roster.lua
LazySync.lua
deletion.lua
zonefilters.lua
debug.lua
GUI_Main.lua
GUI_Detail.lua
GUI_DeathGraph.lua
GUI_Graph.lua
GUI_Reset.lua
GUI_Report.lua
GUI_Config.lua
GUI_Realtime.lua

7
test/fixtures/basic-file.toc vendored Normal file
View File

@ -0,0 +1,7 @@
## Interface: 50400
## Title: Waiting for Godot
## Notes: "Nothing to be done."
## Version: 4.2
#Comment
Vladimir.xml
Estragon.lua

6
test/fixtures/basic-output.toc vendored Normal file
View File

@ -0,0 +1,6 @@
## Title: Bacon
## Interface: 50400
## Notes: I hate everyone
## Version: 4.3.2.1
load.xml
bacon.lua

3
test/fixtures/trunicate.toc vendored Normal file
View File

@ -0,0 +1,3 @@
## Title: Trunicate Me
## X-Long: dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd
somefile.lua

75
test/parse_spec.js Normal file
View File

@ -0,0 +1,75 @@
'use strict';
var fs = require('fs');
var path = require('path');
var should = require('should');
var wowtoc = require('../lib');
describe('wow-toc.parse', function() {
it ('should work on a basic file', function () {
var fixture = fs.readFileSync(path.join(__dirname, 'fixtures', 'basic-file.toc'), { encoding: 'utf8' });
wowtoc.parse(fixture).should.eql({
tags: {
'Interface': '50400',
'Title': 'Waiting for Godot',
'Notes': '"Nothing to be done."',
'Version': '4.2'
},
files: [
'Vladimir.xml',
'Estragon.lua'
]
});
});
it ('should trunicate lines over 1024', function() {
var fixture = fs.readFileSync(path.join(__dirname, 'fixtures', 'trunicate.toc'), { encoding: 'utf8' });
wowtoc.parse(fixture).tags['X-Long'].should.equal('d'.repeat(1024-11));
});
it ('should correctly parse Recount.toc', function() {
/**
* Recount was selected because it's well known has a fairly large toc,
* and it has non-latin characters in some translations.
* I can't find any data on the Recount license, so I'm attributing it
* and leaving it unmodified in test/fixtures/Recount.toc
*/
var fixture = fs.readFileSync(path.join(__dirname, 'fixtures', 'Recount.toc'), { encoding: 'utf8' });
var correct = fs.readFileSync(path.join(__dirname, 'fixtures', 'Recount.json'), { encoding: 'utf8' });
wowtoc.parse(fixture).should.eql(JSON.parse(correct));
});
});
//polyfill from MDN
if (!String.prototype.repeat) {
// jshint ignore:start
String.prototype.repeat = function (count) {
"use strict";
if (this == null)
throw new TypeError("can't convert " + this + " to object");
var str = "" + this;
count = +count;
if (count != count)
count = 0;
if (count < 0)
throw new RangeError("repeat count must be non-negative");
if (count == Infinity)
throw new RangeError("repeat count must be less than infinity");
count = Math.floor(count);
if (str.length == 0 || count == 0)
return "";
// Ensuring count is a 31-bit integer allows us to heavily optimize the
// main part. But anyway, most current (august 2014) browsers can't handle
// strings 1 << 28 chars or longer, so :
if (str.length * count >= 1 << 28)
throw new RangeError("repeat count must not overflow maximum string size");
var rpt = "";
for (;;) {
if ((count & 1) == 1)
rpt += str;
count >>>= 1;
if (count == 0)
break;
str += str;
}
return rpt;
}
// jshint ignore:end
}

20
test/stringify_spec.js Normal file
View File

@ -0,0 +1,20 @@
'use strict';
var fs = require('fs');
var path = require('path');
var should = require('should');
var wowtoc = require('../lib');
describe('wow-toc.stringify', function() {
it ('should work with basic data', function() {
var fixture = fs.readFileSync(path.join(__dirname, 'fixtures', 'basic-output.toc'), { encoding: 'utf8' });
wowtoc.stringify({
tags: {
'Title': 'Bacon',
'Interface': '50400',
'Notes': 'I hate everyone',
'Version': '4.3.2.1'
},
files: ['load.xml', 'bacon.lua']
}).should.equal(fixture);
});
});