tns-core-modules
Version:
Telerik NativeScript Core Modules
426 lines (425 loc) • 18.1 kB
JavaScript
var debug_1 = require("utils/debug");
var xml = require("xml");
var view_1 = require("ui/core/view");
var file_system_1 = require("file-system");
var types_1 = require("utils/types");
var component_builder_1 = require("ui/builder/component-builder");
var platform_1 = require("platform");
var page_1 = require("ui/page");
var file_name_resolver_1 = require("file-system/file-name-resolver");
var defaultNameSpaceMatcher = /tns\.xsd$/i;
var trace;
function ensureTrace() {
if (!trace) {
trace = require("trace");
}
}
function parse(value, context) {
if (types_1.isString(value)) {
var viewToReturn;
if (context instanceof view_1.View) {
context = getExports(context);
}
var componentModule = parseInternal(value, context);
if (componentModule) {
viewToReturn = componentModule.component;
}
return viewToReturn;
}
else if (types_1.isFunction(value)) {
return value();
}
}
exports.parse = parse;
function parseInternal(value, context, uri) {
var start;
var ui;
var errorFormat = (debug_1.debug && uri) ? xml2ui.SourceErrorFormat(uri) : xml2ui.PositionErrorFormat;
(start = new xml2ui.XmlStringParser(errorFormat))
.pipe(new xml2ui.PlatformFilter())
.pipe(new xml2ui.XmlStateParser(ui = new xml2ui.ComponentParser(context, errorFormat)));
start.parse(value);
return ui.rootComponentModule;
}
function loadCustomComponent(componentPath, componentName, attributes, context, parentPage) {
var result;
componentPath = componentPath.replace("~/", "");
var fullComponentPathFilePathWithoutExt = componentPath;
if (!file_system_1.File.exists(componentPath) || componentPath === "." || componentPath === "./") {
fullComponentPathFilePathWithoutExt = file_system_1.path.join(file_system_1.knownFolders.currentApp().path, componentPath, componentName);
}
var xmlFilePath = file_name_resolver_1.resolveFileName(fullComponentPathFilePathWithoutExt, "xml");
if (xmlFilePath) {
var jsFilePath = file_name_resolver_1.resolveFileName(fullComponentPathFilePathWithoutExt, "js");
var subExports = context;
if (jsFilePath) {
subExports = global.loadModule(jsFilePath);
}
result = loadInternal(xmlFilePath, subExports);
if (types_1.isDefined(result) && types_1.isDefined(result.component) && types_1.isDefined(attributes)) {
var attr;
for (attr in attributes) {
component_builder_1.setPropertyValue(result.component, subExports, context, attr, attributes[attr]);
}
}
}
else {
result = component_builder_1.getComponentModule(componentName, componentPath, attributes, context);
}
var cssFilePath = file_name_resolver_1.resolveFileName(fullComponentPathFilePathWithoutExt, "css");
if (cssFilePath) {
if (parentPage) {
parentPage.addCssFile(cssFilePath);
}
else {
ensureTrace();
trace.write("CSS file found but no page specified. Please specify page in the options!", trace.categories.Error, trace.messageType.error);
}
}
return result;
}
function load(pathOrOptions, context) {
var viewToReturn;
var componentModule;
if (!context) {
if (!types_1.isString(pathOrOptions)) {
var options = pathOrOptions;
componentModule = loadCustomComponent(options.path, options.name, undefined, options.exports, options.page);
}
else {
var path_1 = pathOrOptions;
componentModule = loadInternal(path_1);
}
}
else {
var path_2 = pathOrOptions;
componentModule = loadInternal(path_2, context);
}
if (componentModule) {
viewToReturn = componentModule.component;
}
return viewToReturn;
}
exports.load = load;
function loadInternal(fileName, context) {
var componentModule;
if (file_system_1.File.exists(fileName)) {
var file = file_system_1.File.fromPath(fileName);
var onError = function (error) {
throw new Error("Error loading file " + fileName + " :" + error.message);
};
var text = file.readTextSync(onError);
componentModule = parseInternal(text, context, fileName);
}
if (componentModule && componentModule.component) {
componentModule.component.exports = context;
}
return componentModule;
}
function getExports(instance) {
var parent = instance.parent;
while (parent && parent.exports === undefined) {
parent = parent.parent;
}
return parent ? parent.exports : undefined;
}
var xml2ui;
(function (xml2ui) {
var XmlProducerBase = (function () {
function XmlProducerBase() {
}
XmlProducerBase.prototype.pipe = function (next) {
this._next = next;
return next;
};
XmlProducerBase.prototype.next = function (args) {
this._next.parse(args);
};
return XmlProducerBase;
}());
xml2ui.XmlProducerBase = XmlProducerBase;
var XmlStringParser = (function (_super) {
__extends(XmlStringParser, _super);
function XmlStringParser(error) {
_super.call(this);
this.error = error || PositionErrorFormat;
}
XmlStringParser.prototype.parse = function (value) {
var _this = this;
var xmlParser = new xml.XmlParser(function (args) {
try {
_this.next(args);
}
catch (e) {
throw _this.error(e, args.position);
}
}, function (e, p) {
throw _this.error(e, p);
}, true);
if (types_1.isString(value)) {
xmlParser.parse(value);
}
};
return XmlStringParser;
}(XmlProducerBase));
xml2ui.XmlStringParser = XmlStringParser;
function PositionErrorFormat(e, p) {
return new debug_1.ScopeError(e, "Parsing XML at " + p.line + ":" + p.column);
}
xml2ui.PositionErrorFormat = PositionErrorFormat;
function SourceErrorFormat(uri) {
return function (e, p) {
var source = p ? new debug_1.Source(uri, p.line, p.column) : new debug_1.Source(uri, -1, -1);
e = new debug_1.SourceError(e, source, "Building UI from XML.");
return e;
};
}
xml2ui.SourceErrorFormat = SourceErrorFormat;
var PlatformFilter = (function (_super) {
__extends(PlatformFilter, _super);
function PlatformFilter() {
_super.apply(this, arguments);
}
PlatformFilter.prototype.parse = function (args) {
if (args.eventType === xml.ParserEventType.StartElement) {
if (PlatformFilter.isPlatform(args.elementName)) {
if (this.currentPlatformContext) {
throw new Error("Already in '" + this.currentPlatformContext + "' platform context and cannot switch to '" + args.elementName + "' platform! Platform tags cannot be nested.");
}
this.currentPlatformContext = args.elementName;
return;
}
}
if (args.eventType === xml.ParserEventType.EndElement) {
if (PlatformFilter.isPlatform(args.elementName)) {
this.currentPlatformContext = undefined;
return;
}
}
if (this.currentPlatformContext && !PlatformFilter.isCurentPlatform(this.currentPlatformContext)) {
return;
}
this.next(args);
};
PlatformFilter.isPlatform = function (value) {
return value && (value.toLowerCase() === platform_1.platformNames.android.toLowerCase()
|| value.toLowerCase() === platform_1.platformNames.ios.toLowerCase());
};
PlatformFilter.isCurentPlatform = function (value) {
return value && value.toLowerCase() === platform_1.device.os.toLowerCase();
};
return PlatformFilter;
}(XmlProducerBase));
xml2ui.PlatformFilter = PlatformFilter;
var XmlArgsReplay = (function (_super) {
__extends(XmlArgsReplay, _super);
function XmlArgsReplay(args, errorFormat) {
_super.call(this);
this.args = args;
this.error = errorFormat;
}
XmlArgsReplay.prototype.replay = function () {
var _this = this;
this.args.forEach(function (args) {
try {
_this.next(args);
}
catch (e) {
throw _this.error(e, args.position);
}
});
};
return XmlArgsReplay;
}(XmlProducerBase));
xml2ui.XmlArgsReplay = XmlArgsReplay;
var XmlStateParser = (function () {
function XmlStateParser(state) {
this.state = state;
}
XmlStateParser.prototype.parse = function (args) {
this.state = this.state.parse(args);
};
return XmlStateParser;
}());
xml2ui.XmlStateParser = XmlStateParser;
var TemplateParser = (function () {
function TemplateParser(parent, templateProperty) {
this.parent = parent;
this._context = templateProperty.context;
this._recordedXmlStream = new Array();
this._templateProperty = templateProperty;
this._nestingLevel = 0;
this._state = 0;
}
TemplateParser.prototype.parse = function (args) {
if (args.eventType === xml.ParserEventType.StartElement) {
this.parseStartElement(args.prefix, args.namespace, args.elementName, args.attributes);
}
else if (args.eventType === xml.ParserEventType.EndElement) {
this.parseEndElement(args.prefix, args.elementName);
}
this._recordedXmlStream.push(args);
return this._state === 2 ? this.parent : this;
};
Object.defineProperty(TemplateParser.prototype, "elementName", {
get: function () {
return this._templateProperty.elementName;
},
enumerable: true,
configurable: true
});
TemplateParser.prototype.parseStartElement = function (prefix, namespace, elementName, attributes) {
if (this._state === 0) {
this._state = 1;
}
else if (this._state === 2) {
throw new Error("Template must have exactly one root element but multiple elements were found.");
}
this._nestingLevel++;
};
TemplateParser.prototype.parseEndElement = function (prefix, elementName) {
if (this._state === 0) {
throw new Error("Template must have exactly one root element but none was found.");
}
else if (this._state === 2) {
throw new Error("No more closing elements expected for this template.");
}
this._nestingLevel--;
if (this._nestingLevel === 0) {
this._state = 2;
this.build();
}
};
TemplateParser.prototype.build = function () {
var _this = this;
if (this._templateProperty.name in this._templateProperty.parent.component) {
var context = this._context;
var errorFormat = this._templateProperty.errorFormat;
var template = function () {
var start;
var ui;
(start = new xml2ui.XmlArgsReplay(_this._recordedXmlStream, errorFormat))
.pipe(new XmlStateParser(ui = new ComponentParser(context, errorFormat)));
start.replay();
return ui.rootComponentModule.component;
};
this._templateProperty.parent.component[this._templateProperty.name] = template;
}
};
return TemplateParser;
}());
xml2ui.TemplateParser = TemplateParser;
var ComponentParser = (function () {
function ComponentParser(context, errorFormat) {
this.parents = new Array();
this.complexProperties = new Array();
this.context = context;
this.error = errorFormat;
}
ComponentParser.prototype.parse = function (args) {
var parent = this.parents[this.parents.length - 1];
var complexProperty = this.complexProperties[this.complexProperties.length - 1];
if (args.eventType === xml.ParserEventType.StartElement) {
if (ComponentParser.isComplexProperty(args.elementName)) {
var name = ComponentParser.getComplexPropertyName(args.elementName);
this.complexProperties.push({
parent: parent,
name: name,
items: [],
});
if (ComponentParser.isKnownTemplate(name, parent.exports)) {
return new TemplateParser(this, {
context: (parent ? getExports(parent.component) : null) || this.context,
parent: parent,
name: name,
elementName: args.elementName,
templateItems: [],
errorFormat: this.error
});
}
}
else {
var componentModule;
if (args.prefix && args.namespace) {
componentModule = loadCustomComponent(args.namespace, args.elementName, args.attributes, this.context, this.currentPage);
}
else {
var namespace = args.namespace;
if (defaultNameSpaceMatcher.test(namespace || '')) {
namespace = undefined;
}
componentModule = component_builder_1.getComponentModule(args.elementName, namespace, args.attributes, this.context);
}
if (componentModule) {
if (parent) {
if (complexProperty) {
ComponentParser.addToComplexProperty(parent, complexProperty, componentModule);
}
else if (parent.component._addChildFromBuilder) {
parent.component._addChildFromBuilder(args.elementName, componentModule.component);
}
}
else if (this.parents.length === 0) {
this.rootComponentModule = componentModule;
if (this.rootComponentModule && this.rootComponentModule.component instanceof page_1.Page) {
this.currentPage = this.rootComponentModule.component;
if (this.currentPage.exports) {
this.context = this.currentPage.exports;
}
}
}
this.parents.push(componentModule);
}
}
}
else if (args.eventType === xml.ParserEventType.EndElement) {
if (ComponentParser.isComplexProperty(args.elementName)) {
if (complexProperty) {
if (parent && parent.component._addArrayFromBuilder) {
parent.component._addArrayFromBuilder(complexProperty.name, complexProperty.items);
complexProperty.items = [];
}
}
this.complexProperties.pop();
}
else {
this.parents.pop();
}
}
return this;
};
ComponentParser.isComplexProperty = function (name) {
return types_1.isString(name) && name.indexOf(".") !== -1;
};
ComponentParser.getComplexPropertyName = function (fullName) {
var name;
if (types_1.isString(fullName)) {
var names = fullName.split(".");
name = names[names.length - 1];
}
return name;
};
ComponentParser.isKnownTemplate = function (name, exports) {
return ComponentParser.KNOWNTEMPLATES in exports && exports[ComponentParser.KNOWNTEMPLATES] && name in exports[ComponentParser.KNOWNTEMPLATES];
};
ComponentParser.addToComplexProperty = function (parent, complexProperty, elementModule) {
var parentComponent = parent.component;
if (ComponentParser.isKnownCollection(complexProperty.name, parent.exports)) {
complexProperty.items.push(elementModule.component);
}
else if (parentComponent._addChildFromBuilder) {
parentComponent._addChildFromBuilder(complexProperty.name, elementModule.component);
}
else {
parentComponent[complexProperty.name] = elementModule.component;
}
};
ComponentParser.isKnownCollection = function (name, context) {
return ComponentParser.KNOWNCOLLECTIONS in context && context[ComponentParser.KNOWNCOLLECTIONS] && name in context[ComponentParser.KNOWNCOLLECTIONS];
};
ComponentParser.KNOWNCOLLECTIONS = "knownCollections";
ComponentParser.KNOWNTEMPLATES = "knownTemplates";
return ComponentParser;
}());
xml2ui.ComponentParser = ComponentParser;
})(xml2ui || (xml2ui = {}));