pbxproj-dom
Version:
Parser and DOM over the xcode pbxproj
431 lines • 14.3 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
function isJSONNull(json) {
return typeof json === "undefined";
}
function isJSONList(json) {
return json instanceof Array;
}
function isJSONDictionary(json) {
return typeof json === "object";
}
function isJSONIdentifier(json) {
return isJSONKey(json) && canBeIdentifier(json.toString());
}
function isJSONStringBlock(json) {
return isJSONKey(json) && !canBeIdentifier(json.toString());
}
function isJSONKey(json) {
return typeof json === "number" || typeof json === "string";
}
function canBeIdentifier(text) {
return /^[0-9a-zA-Z][0-9a-zA-Z_]*$/.test(text);
}
function makeKey(space, json) {
var text = json.toString();
if (canBeIdentifier(text)) {
return new Identifier(space, text);
}
else {
return new StringBlock(space, text);
}
}
function isKVPDictionary(kvp) {
return isDictionary(kvp.value);
}
exports.isKVPDictionary = isKVPDictionary;
function isDictionary(node) {
return node.kind === "Dictionary";
}
exports.isDictionary = isDictionary;
function isList(node) {
return node.kind === "List";
}
exports.isList = isList;
function isIdentifier(node) {
return node.kind === "Identifier";
}
exports.isIdentifier = isIdentifier;
function isStringBlock(node) {
return node.kind === "StringBlock";
}
exports.isStringBlock = isStringBlock;
function isNull(node) {
return node.kind === "Null";
}
exports.isNull = isNull;
var Node = /** @class */ (function () {
function Node() {
var children = [];
for (var _i = 0; _i < arguments.length; _i++) {
children[_i] = arguments[_i];
}
var _this = this;
children.forEach(function (child) { return child.parent = _this; });
}
Object.defineProperty(Node.prototype, "kvps", {
/**
* If the node is Dictionary, returns array with its KeyValuePair items. Returns empty array otherwise.
*/
get: function () { return []; },
enumerable: true,
configurable: true
});
Object.defineProperty(Node.prototype, "items", {
/**
* If the node is List, returns array with its Value nodes. Returns empty array otherwise.
*/
get: function () { return []; },
enumerable: true,
configurable: true
});
Object.defineProperty(Node.prototype, "json", {
/**
* Returns JSON object matching the AST.
*/
get: function () { return undefined; },
enumerable: true,
configurable: true
});
Object.defineProperty(Node.prototype, "indent", {
/**
* Get the indentation that should be used for the children of this Node.
* For example the indent property of a List will be used when new items are added, and applied to preserve good formatting.
*/
get: function () { return this.parent ? this.parent.indent : ""; },
enumerable: true,
configurable: true
});
Node.prototype.get = function (key) {
return Null.instance;
};
return Node;
}());
exports.Node = Node;
var Null = /** @class */ (function (_super) {
__extends(Null, _super);
function Null() {
return _super !== null && _super.apply(this, arguments) || this;
}
Null.instance = new Null();
return Null;
}(Node));
exports.Null = Null;
var Document = /** @class */ (function (_super) {
__extends(Document, _super);
function Document(root, _s1) {
var _this = _super.call(this, root, _s1) || this;
_this.root = root;
_this._s1 = _s1;
return _this;
}
Object.defineProperty(Document.prototype, "json", {
get: function () {
return this.root.json;
},
enumerable: true,
configurable: true
});
Document.prototype.get = function (key) {
return this.root.get(key);
};
Document.prototype.forEach = function (cb) {
this.root.kvps.forEach(cb);
};
Document.prototype.toString = function () {
return "// !$*UTF8*$!" + this.root + this._s1;
};
return Document;
}(Node));
exports.Document = Document;
Document.prototype.kind = "Document";
var Dictionary = /** @class */ (function (_super) {
__extends(Dictionary, _super);
function Dictionary(_s1, _content, _s2) {
var _this = _super.apply(this, [_s1].concat(_content, [_s2])) || this;
_this._s1 = _s1;
_this._content = _content;
_this._s2 = _s2;
return _this;
}
Object.defineProperty(Dictionary.prototype, "indent", {
get: function () {
return this.parent.indent + "\t";
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dictionary.prototype, "kvps", {
get: function () {
return this._content;
},
enumerable: true,
configurable: true
});
Object.defineProperty(Dictionary.prototype, "json", {
get: function () {
return this._content.reduce(function (acc, kvp) {
acc[kvp.key.json] = kvp.value.json;
return acc;
}, {});
},
enumerable: true,
configurable: true
});
Dictionary.prototype.get = function (key) {
var kvp = this.kvps.find(function (kvp) {
return kvp.key.json == key;
});
return kvp ? kvp.value : Null.instance;
};
/**
* Perform "RFC 7386 - JSON Merge Patch" on the json version of the AST
* and tries to propagate the changes back to the AST.
*
* A Node can not change its own type based on the merge.
* Arrays are completely overwritten.
*/
Dictionary.prototype.patch = function (json) {
for (var key in json) {
var value = json[key];
var current = this.get(key);
if (isJSONNull(value)) {
this.delete(key);
}
else if (isJSONList(value) && isList(current)) {
// TODO:
throw new Error("Not implemented setting List from Array");
}
else if (isJSONDictionary(value) && isDictionary(current)) {
current.patch(value);
}
else if (isJSONIdentifier(value) && isIdentifier(current)) {
current.text = value.toString();
}
else if (isJSONStringBlock(value) && isStringBlock(current)) {
current.text = value.toString();
}
else {
if (isJSONKey(value)) {
var astValue = makeKey(new Space([new WhiteSpace(" ")]), value);
this.set(key, astValue);
}
else if (isJSONDictionary(value)) {
var astValue = new Dictionary(new Space([new WhiteSpace(" ")]), [], new Space([new WhiteSpace("\n" + this.indent)]));
this.set(key, astValue);
astValue.patch(value);
}
else if (isJSONList(value)) {
// TODO:
throw new Error("Not implemented making dictionary from json Array");
}
else {
// TODO:
throw new Error("Not implemented making ast from json " + value);
}
}
}
};
Dictionary.prototype.set = function (key, value) {
var kvp = this._content.find(function (kvp) { return kvp.key.text === key; });
if (kvp) {
kvp.value = value;
}
else {
var space = new Space([new WhiteSpace(this.indent ? "\n" + this.indent : " ")]);
kvp = new KeyValuePair(makeKey(space, key), new Space([new WhiteSpace(" ")]), value, new Space([]));
var index = this._content.findIndex(function (p) { return p.key.text > key; });
if (index === -1) {
this._content.push(kvp);
}
else {
this._content.splice(index, 0, kvp);
}
kvp.parent = this;
}
};
Dictionary.prototype.delete = function (key) {
for (var i = this._content.length - 1; i >= 0; i--) {
if (this._content[i].key.text === key) {
this._content.splice(i, 1);
return;
}
}
};
Dictionary.prototype.toString = function () {
return this._s1 + "{" + this._content.join("") + this._s2 + "}";
};
return Dictionary;
}(Node));
exports.Dictionary = Dictionary;
Dictionary.prototype.kind = "Dictionary";
var KeyValuePair = /** @class */ (function (_super) {
__extends(KeyValuePair, _super);
function KeyValuePair(_key, _s2, value, _s3) {
var _this = _super.call(this, _key, _s2, value, _s3) || this;
_this._key = _key;
_this._s2 = _s2;
_this.value = value;
_this._s3 = _s3;
return _this;
}
Object.defineProperty(KeyValuePair.prototype, "key", {
get: function () { return this._key; },
enumerable: true,
configurable: true
});
KeyValuePair.prototype.toString = function () {
return "" + this._key + this._s2 + "=" + this.value + this._s3 + ";";
};
KeyValuePair.prototype.get = function (key) {
return this.value ? this.value.get(key) : Null.instance;
};
return KeyValuePair;
}(Node));
exports.KeyValuePair = KeyValuePair;
KeyValuePair.prototype.kind = "KeyValuePair";
var StringBlock = /** @class */ (function (_super) {
__extends(StringBlock, _super);
function StringBlock(_s1, text) {
var _this =
// TODO: Escape the text.
_super.call(this, _s1) || this;
_this._s1 = _s1;
_this.text = text;
return _this;
}
Object.defineProperty(StringBlock.prototype, "json", {
get: function () { return this.text; },
enumerable: true,
configurable: true
});
StringBlock.prototype.toString = function () {
// TODO: Unescape the text.
return this._s1 + '"' + this.text + '"';
};
return StringBlock;
}(Node));
exports.StringBlock = StringBlock;
StringBlock.prototype.kind = "StringBlock";
var CommentBlock = /** @class */ (function (_super) {
__extends(CommentBlock, _super);
function CommentBlock(_text) {
var _this = _super.call(this) || this;
_this._text = _text;
return _this;
}
Object.defineProperty(CommentBlock.prototype, "text", {
get: function () { return this._text; },
enumerable: true,
configurable: true
});
CommentBlock.prototype.toString = function () {
return "/*" + this._text + "*/";
};
return CommentBlock;
}(Node));
exports.CommentBlock = CommentBlock;
CommentBlock.prototype.kind = "CommentBlock";
var List = /** @class */ (function (_super) {
__extends(List, _super);
function List(_s1, _content, _s2) {
var _this = _super.apply(this, [_s1].concat(List.flatten(_content), [_s2])) || this;
_this._s1 = _s1;
_this._content = _content;
_this._s2 = _s2;
return _this;
}
Object.defineProperty(List.prototype, "indent", {
get: function () {
return this.parent.indent + "\t";
},
enumerable: true,
configurable: true
});
Object.defineProperty(List.prototype, "items", {
get: function () {
return this._content.map(function (e) { return e[0]; });
},
enumerable: true,
configurable: true
});
Object.defineProperty(List.prototype, "json", {
get: function () {
return this._content.map(function (e) { return e[0].json; });
},
enumerable: true,
configurable: true
});
List.prototype.toString = function () {
return this._s1 + "(" + this._content.map(function (l) { return l.join(""); }).join("") + this._s2 + ")";
};
List.flatten = function (arr) {
return arr.reduce(function (acc, child) {
acc.push(child[0]);
acc.push(child[1]);
return acc;
}, []);
};
return List;
}(Node));
exports.List = List;
List.prototype.kind = "List";
var Identifier = /** @class */ (function (_super) {
__extends(Identifier, _super);
function Identifier(_s1, text) {
var _this = _super.call(this, _s1) || this;
_this._s1 = _s1;
_this.text = text;
return _this;
}
Object.defineProperty(Identifier.prototype, "json", {
get: function () { return this.text; },
enumerable: true,
configurable: true
});
Identifier.prototype.toString = function () { return this._s1 + this.text; };
return Identifier;
}(Node));
exports.Identifier = Identifier;
Identifier.prototype.kind = "Identifier";
var WhiteSpace = /** @class */ (function (_super) {
__extends(WhiteSpace, _super);
function WhiteSpace(text) {
var _this =
// TODO: Unescape the text
_super.call(this) || this;
_this.text = text;
return _this;
}
WhiteSpace.prototype.toString = function () {
// TODO: Escape the text
return this.text;
};
return WhiteSpace;
}(Node));
exports.WhiteSpace = WhiteSpace;
WhiteSpace.prototype.kind = "WhiteSpace";
var Space = /** @class */ (function (_super) {
__extends(Space, _super);
function Space(_content) {
var _this = _super.apply(this, _content) || this;
_this._content = _content;
return _this;
}
Space.prototype.toString = function () {
return this._content.join("");
};
return Space;
}(Node));
exports.Space = Space;
Space.prototype.kind = "Space";
//# sourceMappingURL=ast.js.map