Merge pull request #706 from NativeScript/CSS-and-code-files-from-XML

CSS and XML code files now can be specified in XML
This commit is contained in:
Vladimir Enchev
2015-09-10 13:59:07 +03:00
6 changed files with 133 additions and 5 deletions

View File

@ -79,6 +79,7 @@
<TypeScriptCompile Include="apps\action-bar-demo\pages\data-binding.ts">
<DependentUpon>data-binding.xml</DependentUpon>
</TypeScriptCompile>
<TypeScriptCompile Include="apps\tests\xml-declaration\custom-code-file.ts" />
<TypeScriptCompile Include="apps\transforms\app.ts" />
<TypeScriptCompile Include="apps\transforms\main-page.ts" />
<TypeScriptCompile Include="apps\transforms\model.ts" />
@ -110,6 +111,7 @@
<Content Include="apps\action-bar-demo\pages\center-view-segmented.xml" />
<Content Include="apps\action-bar-demo\pages\center-view.xml" />
<Content Include="apps\action-bar-demo\pages\data-binding.xml" />
<Content Include="apps\tests\xml-declaration\custom-css-file.css" />
<Content Include="apps\transforms\main-page.xml">
<SubType>Designer</SubType>
</Content>
@ -1982,8 +1984,6 @@
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
<UserProperties ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" />
<UserProperties ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2linear-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" />
<UserProperties ui_2layouts_2wrap-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2layouts_2grid-layout_2package_1json__JSONSchema="" ui_2layouts_2dock-layout_2package_1json__JSONSchema="" ui_2layouts_2absolute-layout_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2web-view_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2content-view_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2gallery-app_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2absolute-layout-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" apps_2editable-text-demo_2package_1json__JSONSchema="http://json.schemastore.org/package" ui_2scroll-view_2package_1json__JSONSchema="http://json.schemastore.org/package" />
</VisualStudio>
</ProjectExtensions>

View File

@ -0,0 +1,3 @@
export function loaded(args) {
args.object.customCodeLoaded = true;
}

View File

@ -0,0 +1,3 @@
.MyClass {
background-color: green;
}

View File

@ -148,10 +148,91 @@ export function test_parse_ShouldNotCrashWithoutExports() {
var file = fs.File.fromPath(fs.path.join(__dirname, "mainPage.xml"));
var text = file.readTextSync();
var v: view.View = builder.parse(text);
var v: view.View = builder.parse(text);
TKUnit.assert(v instanceof view.View, "Expected result: View; Actual result: " + v + ";");
};
export function test_parse_ShouldResolveExportsFromCodeFile() {
var page = builder.parse("<Page codeFile='~/xml-declaration/custom-code-file' loaded='loaded'></Page>");
page._emit("loaded");
TKUnit.assert((<any>page).customCodeLoaded, "Parse should resolve exports from custom code file.");
}
export function test_parse_ShouldThrowErrorWhenInvalidCodeFileIsSpecified() {
var e: Error;
try {
builder.parse("<Page codeFile='~/xml-declaration/some-code-file' loaded='pageLoaded'></Page>");
} catch (ex) {
e = ex;
}
TKUnit.assert(e, "Expected result: Error; Actual result: " + e);
};
export function test_parse_ShouldResolveExportsFromCodeFileForTemplates() {
var p = <Page>builder.parse('<Page codeFile="~/xml-declaration/custom-code-file" xmlns:customControls="xml-declaration/mymodulewithxml"><ListView items="{{ items }}" itemLoading="{{ itemLoading }}"><ListView.itemTemplate><customControls:MyControl loaded="loaded" /></ListView.itemTemplate></ListView></Page>');
function testAction(views: Array<viewModule.View>) {
var ctrl;
var obj = new observable.Observable();
obj.set("items", [1]);
obj.set("itemLoading", function (args: listViewModule.ItemEventData) {
ctrl = args.view
});
p.bindingContext = obj;
TKUnit.wait(0.2);
TKUnit.assert((<any>ctrl).customCodeLoaded, "Parse should resolve exports for templates from custom code file.");
};
helper.navigate(function () { return p; });
try {
testAction([p.content, p]);
}
finally {
helper.goBack();
}
}
export function test_parse_ShouldApplyCssFromCssFile() {
var newPage: Page;
var pageFactory = function (): Page {
newPage = <Page>builder.parse("<Page cssFile='~/xml-declaration/custom-css-file.css'><Label cssClass='MyClass' /></Page>");
return newPage;
};
helper.navigate(pageFactory);
TKUnit.assert(newPage.isLoaded, "The page should be loaded here.");
try {
helper.assertViewBackgroundColor(newPage.content, "#008000");
}
finally {
helper.goBack();
}
};
export function test_parse_ShouldResolveExportsFromCodeFileAndApplyCssFile() {
var newPage: Page;
var pageFactory = function (): Page {
newPage = <Page>builder.parse("<Page codeFile='~/xml-declaration/custom-code-file' cssFile='~/xml-declaration/custom-css-file.css' loaded='loaded'><Label cssClass='MyClass' /></Page>");
return newPage;
};
helper.navigate(pageFactory);
TKUnit.assert(newPage.isLoaded, "The page should be loaded here.");
TKUnit.assert((<any>newPage).customCodeLoaded, "Parse should resolve exports from custom code file.");
try {
helper.assertViewBackgroundColor(newPage.content, "#008000");
}
finally {
helper.goBack();
}
};
export function test_parse_ShouldFindEventHandlersInExports() {
var loaded;
var page = builder.parse("<Page loaded='myLoaded'></Page>", {

View File

@ -10,6 +10,7 @@ import fs = require("file-system");
import gestures = require("ui/gestures");
import bindingBuilder = require("ui/builder/binding-builder");
import platform = require("platform");
import pages = require("ui/page");
var UI_PATH = "ui/";
var MODULES = {
@ -28,6 +29,8 @@ var ROW_SPAN = "rowSpan";
var DOCK = "dock";
var LEFT = "left";
var TOP = "top";
var CODEFILE = "codeFile";
var CSSFILE = "cssFile";
export var specialProperties: Array<string> = [
ROW,
@ -37,6 +40,8 @@ export var specialProperties: Array<string> = [
DOCK,
LEFT,
TOP,
CODEFILE,
CSSFILE
]
var eventHandlers = {};
@ -78,6 +83,42 @@ export function getComponentModule(elementName: string, namespace: string, attri
throw new Error("Cannot create module " + moduleId + ". " + ex + ". StackTrace: " + ex.stack);
}
if (attributes) {
if (attributes[CODEFILE]) {
if (instance instanceof pages.Page) {
var codeFilePath = attributes[CODEFILE].trim();
if (codeFilePath.indexOf("~/") === 0) {
codeFilePath = fs.path.join(fs.knownFolders.currentApp().path, codeFilePath.replace("~/", ""));
}
try {
exports = require(codeFilePath);
(<any>instance).exports = exports;
} catch (ex) {
throw new Error(`Code file with path "${codeFilePath}" cannot be found!`);
}
} else {
throw new Error("Code file atribute is valid only for pages!");
}
}
if (attributes[CSSFILE]) {
if (instance instanceof pages.Page) {
var cssFilePath = attributes[CSSFILE].trim();
if (cssFilePath.indexOf("~/") === 0) {
cssFilePath = fs.path.join(fs.knownFolders.currentApp().path, cssFilePath.replace("~/", ""));
}
if (fs.File.exists(cssFilePath)) {
(<pages.Page>instance).addCssFile(cssFilePath);
instance[CSSFILE] = true;
} else {
throw new Error(`Css file with path "${cssFilePath}" cannot be found!`);
}
} else {
throw new Error("Css file atribute is valid only for pages!");
}
}
}
if (instance && instanceModule) {
var bindings = new Array<bindable.BindingOptions>();

View File

@ -66,9 +66,9 @@ export function resolvePageFromEntry(entry: definition.NavigationEntry): pages.P
throw new Error("Failed to load Page from entry.moduleName: " + entry.moduleName);
}
// Possible CSS file path.
// Possible CSS file path. Add it only if CSS not already specified and loaded from cssFile Page attribute in XML.
var cssFileName = fileResolverModule.resolveFileName(moduleNamePath, "css");
if (cssFileName) {
if (cssFileName && !page["cssFile"]) {
page.addCssFile(cssFileName);
}
}