mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Use plist NPM instead of vendor/plist.js. Use new synch parsing api.
This also adds a `readObject` method to `fs-utils`, which loads the file as cson if it ends with json/cson, and otherwise tries to load it as a plist. For now, we're using my fork which is tolerant to a node environment with a `window` global and suppresses some logging of non-fatal errors. If the upstream author accepts my pull requests we can switch back.
This commit is contained in:
@@ -12,7 +12,8 @@
|
||||
"d3": "3.0.8",
|
||||
"coffee-cache": "0.1.0",
|
||||
"pegjs": "0.7.0",
|
||||
"async": "0.2.6"
|
||||
"async": "0.2.6",
|
||||
"plist": "git://github.com/nathansobo/node-plist.git"
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
|
||||
@@ -8,15 +8,7 @@ CSON = require 'cson'
|
||||
module.exports =
|
||||
class TextMateGrammar
|
||||
@readFromPath: (path) ->
|
||||
grammarContent = null
|
||||
if CSON.isObjectPath(path)
|
||||
grammarContent = CSON.readObject(path)
|
||||
else
|
||||
plist.parseString fs.read(path), (e, data) ->
|
||||
throw new Error(e) if e
|
||||
grammarContent = data[0]
|
||||
throw new Error("Failed to load grammar at path `#{path}`") unless grammarContent
|
||||
grammarContent
|
||||
fs.readObject(path)
|
||||
|
||||
name: null
|
||||
fileTypes: null
|
||||
|
||||
@@ -90,11 +90,10 @@ class TextMatePackage extends Package
|
||||
preferenceObjects = []
|
||||
if fs.exists(@preferencesPath)
|
||||
for preferencePath in fs.list(@preferencesPath)
|
||||
@readObjectFromPath preferencePath, (e, object) =>
|
||||
if e
|
||||
console.warn "Failed to parse preference at path '#{preferencePath}'", e.stack
|
||||
else
|
||||
preferenceObjects.push(object)
|
||||
try
|
||||
preferenceObjects.push(fs.readObject(preferencePath))
|
||||
catch e
|
||||
console.warn "Failed to parse preference at path '#{preferencePath}'", e.stack
|
||||
preferenceObjects
|
||||
|
||||
propertiesFromTextMateSettings: (textMateSettings) ->
|
||||
|
||||
@@ -268,21 +268,20 @@ module.exports =
|
||||
|
||||
readPlist: (path) ->
|
||||
plist = require 'plist'
|
||||
object = null
|
||||
plist.parseString @read(path), (e, data) ->
|
||||
throw new Error(e) if e
|
||||
object = data[0]
|
||||
object
|
||||
plist.parseStringSync(@read(path))
|
||||
|
||||
readPlistAsync: (path, done) ->
|
||||
plist = require 'plist'
|
||||
fs.readFile path, 'utf8', (err, contents) ->
|
||||
return done(err) if err
|
||||
[parseErr, object] = []
|
||||
# plist has an async api, but it isn't actually synchronous
|
||||
# and it doesn't ever call our callback if there's invalid input
|
||||
plist.parseString contents, (err, data) ->
|
||||
parseErr = err
|
||||
object = data[0] unless err
|
||||
parseErr = "Could not parse plist at path: '#{path}'" unless object
|
||||
done(parseErr, object)
|
||||
try
|
||||
done(null, plist.parseStringSync(contents))
|
||||
catch err
|
||||
done(err)
|
||||
|
||||
readObject: (path) ->
|
||||
cson = require 'cson'
|
||||
if cson.isObjectPath(path)
|
||||
cson.readObject(path)
|
||||
else
|
||||
@readPlist(path)
|
||||
|
||||
220
vendor/plist.js
vendored
220
vendor/plist.js
vendored
@@ -1,220 +0,0 @@
|
||||
;(function (exports, sax) {
|
||||
//Checks if running in a non-browser environment
|
||||
var inNode = typeof window === 'undefined' ? true : false;
|
||||
|
||||
function Parser() {
|
||||
sax.SAXParser.call(this, false, { lowercasetags: true, trim: false });
|
||||
}
|
||||
|
||||
var inherits = null;
|
||||
if (inNode) {
|
||||
var fs = require('fs');
|
||||
inherits = require('util').inherits; //use node provided function
|
||||
} else { //use in browser
|
||||
if ("create" in Object) {
|
||||
inherits = function(ctor, superCtor) {
|
||||
ctor.super_ = superCtor;
|
||||
ctor.prototype = Object.create(superCtor.prototype, {
|
||||
constructor: {
|
||||
value: ctor,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
};
|
||||
} else {
|
||||
var klass = function() {};
|
||||
inherits = function(ctor, superCtor) {
|
||||
klass.prototype = superCtor.prototype;
|
||||
ctor.prototype = new klass;
|
||||
ctor.prototype['constructor'] = ctor;
|
||||
}
|
||||
}
|
||||
}
|
||||
inherits(Parser, sax.SAXParser); //inherit from sax (browser-style or node-style)
|
||||
|
||||
Parser.prototype.getInteger = function (string) {
|
||||
this.value = parseInt(string, 10);
|
||||
}
|
||||
Parser.prototype.getReal = function (string) {
|
||||
this.value = parseFloat(string);
|
||||
}
|
||||
Parser.prototype.getString = function (string) {
|
||||
this.value += string;
|
||||
}
|
||||
Parser.prototype.getData = function(string) {
|
||||
// todo: parse base64 encoded data
|
||||
this.value += string;
|
||||
}
|
||||
Parser.prototype.getDate = function (string) {
|
||||
this.value = new Date(string);
|
||||
}
|
||||
|
||||
Parser.prototype.addToDict = function (value) {
|
||||
this.dict[this.key] = value;
|
||||
}
|
||||
Parser.prototype.addToArray = function (value) {
|
||||
this.array.push(value);
|
||||
}
|
||||
|
||||
Parser.prototype.onopentag = function (tag) {
|
||||
switch (tag.name) {
|
||||
case 'dict':
|
||||
this.stack.push(this.context);
|
||||
this.context = {
|
||||
value: function() {
|
||||
return this.dict;
|
||||
},
|
||||
dict: {},
|
||||
setKey: function(key) {
|
||||
this.key = key;
|
||||
},
|
||||
setValue: function(value) {
|
||||
this.dict[this.key] = value;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'plist':
|
||||
case 'array':
|
||||
this.stack.push(this.context);
|
||||
this.context = {
|
||||
value: function() {
|
||||
return this.array;
|
||||
},
|
||||
array: [],
|
||||
setKey: function(key) {
|
||||
console.log('unexpected <key> element in array');
|
||||
},
|
||||
setValue: function(value) {
|
||||
this.array.push(value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'key':
|
||||
this.ontext = function (text) {
|
||||
this.context.setKey(text);
|
||||
}
|
||||
break;
|
||||
case 'integer':
|
||||
this.ontext = this.getInteger;
|
||||
break;
|
||||
case 'real':
|
||||
this.ontext = this.getReal;
|
||||
break;
|
||||
case 'string':
|
||||
this.value = '';
|
||||
this.ontext = this.getString;
|
||||
this.oncdata = this.getString;
|
||||
break;
|
||||
case 'data':
|
||||
this.value = '';
|
||||
this.ontext = this.getData;
|
||||
this.oncdata = this.getData;
|
||||
break;
|
||||
case 'true':
|
||||
this.value = true;
|
||||
break;
|
||||
case 'false':
|
||||
this.value = false;
|
||||
break;
|
||||
case 'date':
|
||||
this.ontext = this.getDate;
|
||||
break;
|
||||
default:
|
||||
console.log('ignored tag', tag.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Parser.prototype.onclosetag = function (tag) {
|
||||
var value;
|
||||
switch (tag) {
|
||||
case 'dict':
|
||||
case 'array':
|
||||
case 'plist':
|
||||
var value = this.context.value();
|
||||
this.context = this.stack.pop();
|
||||
this.context.setValue(value);
|
||||
break;
|
||||
case 'true':
|
||||
case 'false':
|
||||
case 'string':
|
||||
case 'integer':
|
||||
case 'real':
|
||||
case 'date':
|
||||
case 'data':
|
||||
this.context.setValue(this.value);
|
||||
break;
|
||||
case 'key':
|
||||
break;
|
||||
default:
|
||||
console.log('closing', tag, 'tag ignored');
|
||||
}
|
||||
this.oncdata = this.ontext = this.checkWhitespace;
|
||||
}
|
||||
Parser.prototype.checkWhitespace = function (data) {
|
||||
if (!data.match(/^[ \t\r\n]*$/)) {
|
||||
console.log('unexpected non-whitespace data', data);
|
||||
}
|
||||
}
|
||||
Parser.prototype.oncomment = function (comment) {
|
||||
}
|
||||
Parser.prototype.onerror = function (error) {
|
||||
console.log('sax parser error:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (inNode) Parser.prototype.parseFile = function (xmlfile, callback) { //browsers aren't capable of opening files, instead use AJAX
|
||||
var parser = this;
|
||||
parser.stack = [ ];
|
||||
parser.context = {
|
||||
callback: callback,
|
||||
value: function() {},
|
||||
setKey: function(key) {},
|
||||
setValue: function(value) {
|
||||
callback(null, value);
|
||||
},
|
||||
}
|
||||
var rs = fs.createReadStream(xmlfile, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
rs.on('data', function(data) { parser.write(data); });
|
||||
rs.on('end', function() { parser.close(); });
|
||||
}
|
||||
|
||||
Parser.prototype.parseString = function (xml, callback) {
|
||||
var parser = this;
|
||||
parser.stack = [ ];
|
||||
parser.context = {
|
||||
callback: callback,
|
||||
value: function() {},
|
||||
setKey: function(key) {},
|
||||
setValue: function(value) {
|
||||
this.callback(null, value);
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
parser.write(xml);
|
||||
parser.close();
|
||||
}
|
||||
catch (e) {
|
||||
callback(e, {})
|
||||
}
|
||||
}
|
||||
|
||||
exports.Parser = Parser;
|
||||
|
||||
exports.parseString = function (xml, callback) {
|
||||
var parser = new Parser();
|
||||
parser.parseString(xml, callback);
|
||||
}
|
||||
|
||||
if (inNode) exports.parseFile = function (filename, callback) { //Do not expose no created method
|
||||
var parser = new Parser();
|
||||
parser.parseFile(filename, callback);
|
||||
}
|
||||
})(typeof exports === 'undefined' ? plist = {} : exports, require('sax')) // Changed by sobo to always `require` sax
|
||||
//the above line checks for exports (defined in node) and uses it, or creates a global variable and exports to that.
|
||||
//also, if in node, require sax node-style, in browser the developer must use a <script> tag to import sax
|
||||
// TODO: Implement detection of 'sax' in the Browser environment
|
||||
1011
vendor/sax.js
vendored
1011
vendor/sax.js
vendored
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user