UNPKG

pbxproj-dom

Version:
431 lines 14.3 kB
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