diff --git a/CrossPlatformModules.csproj b/CrossPlatformModules.csproj index 1c5b9e9da..b4ac50cb4 100644 --- a/CrossPlatformModules.csproj +++ b/CrossPlatformModules.csproj @@ -514,6 +514,7 @@ + @@ -1474,7 +1475,7 @@ False - + \ No newline at end of file diff --git a/application/application-common.ts b/application/application-common.ts index fab430056..e39642835 100644 --- a/application/application-common.ts +++ b/application/application-common.ts @@ -1,6 +1,5 @@ require("globals"); import definition = require("application"); -import cssParser = require("js-libs/reworkcss"); import fs = require("file-system"); import fileSystemAccess = require("file-system/file-system-access"); import styleScope = require("ui/styling/style-scope"); @@ -28,10 +27,8 @@ export function loadCss() { var cssFileName = fs.path.join(fs.knownFolders.currentApp().path, definition.cssFile); var applicationCss; if (fs.File.exists(cssFileName)) { - // Read the CSS file. new fileSystemAccess.FileSystemAccess().readText(cssFileName, r => { applicationCss = r; }); - var applicationCssSyntaxTree = cssParser.parse(applicationCss, undefined); - definition.cssSelectorsCache = styleScope.StyleScope.createSelectorsFromSyntaxTree(applicationCssSyntaxTree); + definition.cssSelectorsCache = styleScope.StyleScope.createSelectorsFromCss(applicationCss, cssFileName); } } } \ No newline at end of file diff --git a/apps/tests/app/mainPage.ts b/apps/tests/app/mainPage.ts index 80f41cd28..be7855725 100644 --- a/apps/tests/app/mainPage.ts +++ b/apps/tests/app/mainPage.ts @@ -20,7 +20,7 @@ class MyTraceWriter implements trace.TraceWriter { trace.addWriter(new MyTraceWriter()); trace.enable(); -trace.setCategories(trace.categories.Test); +trace.setCategories(trace.categories.Test + "," + trace.categories.Error); var textView = new textViewModule.TextView(); textView.editable = false; diff --git a/apps/tests/ui/label/label-tests-wrong.css b/apps/tests/ui/label/label-tests-wrong.css new file mode 100644 index 000000000..139e1f048 --- /dev/null +++ b/apps/tests/ui/label/label-tests-wrong.css @@ -0,0 +1,4 @@ +label { + + background-color: red; +} diff --git a/apps/tests/ui/label/label-tests.ts b/apps/tests/ui/label/label-tests.ts index 9946cc9d7..0ed0bde4b 100644 --- a/apps/tests/ui/label/label-tests.ts +++ b/apps/tests/ui/label/label-tests.ts @@ -25,6 +25,25 @@ import page = require("ui/page"); import textBase = require("ui/text-base"); import enums = require("ui/enums"); import labelTestsNative = require("./label-tests-native"); +import trace = require("trace"); + +var errorMessage; +var errorTraceWriter = { + write: function (message, category, messageType) { + if (category === trace.categories.Error) { + errorMessage = message; + } + } +} + +export var setUp = function () { + trace.addWriter(errorTraceWriter); +} + +export var tearDown = function () { + trace.removeWriter(errorTraceWriter); + errorMessage = undefined; +} export var test_Label_Members = function () { var label = new LabelModule.Label(); @@ -487,3 +506,28 @@ export var testNativeTextAlignmentFromLocal = function () { TKUnit.assert(actualResult === expectedTextAlignment, "Actual: " + actualResult + "; Expected: " + expectedTextAlignment); }); } + +export var testErrorMessageWhenWrongCssIsAddedWithFile = function () { + helper.buildUIAndRunTest(_createLabelFunc(), function (views: Array) { + var view = views[0]; + view.id = "testLabel"; + var page = views[1]; + errorMessage = undefined; + page.addCssFile("/app/tests/ui/label/label-tests-wrong.css"); + + TKUnit.assertNotEqual(errorMessage, undefined); + }); + +} + +export var testErrorMessageWhenWrongCssIsAdded = function () { + helper.buildUIAndRunTest(_createLabelFunc(), function (views: Array) { + var view = views[0]; + view.id = "testLabel"; + var page = views[1]; + errorMessage = undefined; + page.addCss("label { < !--Test wrong comment-- > background-color: red; }"); + + TKUnit.assertNotEqual(errorMessage, undefined); + }); +} diff --git a/js-libs/reworkcss/reworkcss.js b/js-libs/reworkcss/reworkcss.js index 430129313..67603f59d 100644 --- a/js-libs/reworkcss/reworkcss.js +++ b/js-libs/reworkcss/reworkcss.js @@ -57,17 +57,25 @@ module.exports.parse = function(css, options){ */ function error(msg) { - if (options.silent === true) { - return false; - } + if (options.silent === true) { + return false; + }; - var err = new Error(options.source + ':' + lineno + ':' + column + ': ' + msg); - err.reason = msg; - err.filename = options.source; - err.line = lineno; - err.column = column; - err.source = css; - throw err; + var errorMessage; + if (options.source) { + errorMessage = options.source + ':' + lineno + ':' + column + ': ' + msg; + } + else { + errorMessage = "Parsing '" + css + "' issue an error: " + msg; + } + + var err = new Error(errorMessage); + err.reason = msg; + err.filename = options.source; + err.line = lineno; + err.column = column; + err.source = css; + throw err; } /** diff --git a/trace/trace.d.ts b/trace/trace.d.ts index 3653f9e9f..a464a7002 100644 --- a/trace/trace.d.ts +++ b/trace/trace.d.ts @@ -68,6 +68,7 @@ declare module "trace" { export var Navigation: string; export var Test: string; export var Binding: string; + export var Error: string; export var All: string; diff --git a/trace/trace.ts b/trace/trace.ts index 6ba8a9515..e6207c558 100644 --- a/trace/trace.ts +++ b/trace/trace.ts @@ -107,7 +107,8 @@ export module categories { export var Navigation = "Navigation"; export var Test = "Test"; export var Binding = "Binding"; - export var All = VisualTreeEvents + "," + Layout + "," + Style + "," + ViewHierarchy + "," + NativeLifecycle + "," + Debug + "," + Navigation + "," + Test + "," + Binding; + export var Error = "Error"; + export var All = VisualTreeEvents + "," + Layout + "," + Style + "," + ViewHierarchy + "," + NativeLifecycle + "," + Debug + "," + Navigation + "," + Test + "," + Binding + "," + Error; export var separator = ","; diff --git a/ui/page/page-common.ts b/ui/page/page-common.ts index 9006d66e5..c3245ffaa 100644 --- a/ui/page/page-common.ts +++ b/ui/page/page-common.ts @@ -5,7 +5,6 @@ import frame = require("ui/frame"); import styleScope = require("ui/styling/style-scope"); import fs = require("file-system"); import fileSystemAccess = require("file-system/file-system-access"); -import trace = require("trace"); export module knownEvents { export var navigatedTo = "navigatedTo"; @@ -53,7 +52,11 @@ export class Page extends contentView.ContentView implements dts.Page { } public addCss(cssString: string): void { - this._styleScope.addCss(cssString); + this._addCssInternal(cssString, undefined); + } + + private _addCssInternal(cssString: string, cssFileName: string): void { + this._styleScope.addCss(cssString, cssFileName); this._refreshCss(); } @@ -62,7 +65,7 @@ export class Page extends contentView.ContentView implements dts.Page { var realCssFileName = fs.path.join(fs.knownFolders.currentApp().path, cssFileName); if (fs.File.exists(realCssFileName)) { new fileSystemAccess.FileSystemAccess().readText(realCssFileName, r => { cssString = r; }); - this.addCss(cssString); + this._addCssInternal(cssString, cssFileName); } } @@ -101,22 +104,18 @@ export class Page extends contentView.ContentView implements dts.Page { return; } - try { - this._styleScope.ensureSelectors(); + this._styleScope.ensureSelectors(); - var scope = this._styleScope; - var checkSelectors = (view: view.View): boolean => { - scope.applySelectors(view); - return true; - } - - checkSelectors(this); - view.eachDescendant(this, checkSelectors); - - this._cssApplied = true; - } catch (e) { - trace.write("Css styling failed: " + e, trace.categories.Style); + var scope = this._styleScope; + var checkSelectors = (view: view.View): boolean => { + scope.applySelectors(view); + return true; } + + checkSelectors(this); + view.eachDescendant(this, checkSelectors); + + this._cssApplied = true; } private _resetCssValues() { diff --git a/ui/styling/style-scope.ts b/ui/styling/style-scope.ts index 27c648cb6..5859ef2e6 100644 --- a/ui/styling/style-scope.ts +++ b/ui/styling/style-scope.ts @@ -12,6 +12,7 @@ export class StyleScope { private _viewIdToKey = {}; private _css: string; + private _cssFileName: string; private _cssSelectors: Array; get css(): string { @@ -19,33 +20,44 @@ export class StyleScope { } set css(value: string) { this._css = value; + this._cssFileName = undefined; this._cssSelectors = undefined; this._reset(); } - public addCss(cssString: string): void { + public addCss(cssString: string, cssFileName: string): void { if (this._css === undefined) { this._css = cssString; } else { this._css += cssString; } + this._cssFileName = cssFileName; this._reset(); if (this._cssSelectors) { - var addedCssTree = cssParser.parse(cssString, undefined); - var addedSelectors = StyleScope.createSelectorsFromSyntaxTree(addedCssTree); + var addedSelectors = StyleScope.createSelectorsFromCss(cssString, cssFileName); this._cssSelectors = this._joinCssSelectorsArrays([this._cssSelectors, addedSelectors]); } } + public static createSelectorsFromCss(css: string, cssFileName: string): cssSelector.CssSelector[] { + try { + var pageCssSyntaxTree = css ? cssParser.parse(css, { source: cssFileName }) : null; + var pageCssSelectors; + if (pageCssSyntaxTree) { + pageCssSelectors = StyleScope.createSelectorsFromSyntaxTree(pageCssSyntaxTree); + } + return pageCssSelectors; + } + catch (e) { + trace.write("Css styling failed: " + e, trace.categories.Error, trace.messageType.error); + } + } + public ensureSelectors() { if (!this._cssSelectors && (this._css || application.cssSelectorsCache)) { var applicationCssSelectors = application.cssSelectorsCache ? application.cssSelectorsCache : null; - var pageCssSyntaxTree = this._css ? cssParser.parse(this._css, undefined) : null; - var pageCssSelectors; - if (pageCssSyntaxTree) { - pageCssSelectors = StyleScope.createSelectorsFromSyntaxTree(pageCssSyntaxTree); - } + var pageCssSelectors = StyleScope.createSelectorsFromCss(this._css, this._cssFileName); this._cssSelectors = this._joinCssSelectorsArrays([applicationCssSelectors, pageCssSelectors]); } } @@ -131,7 +143,7 @@ export class StyleScope { } } - public static createSelectorsFromSyntaxTree(ast: cssParser.SyntaxTree): Array { + private static createSelectorsFromSyntaxTree(ast: cssParser.SyntaxTree): Array { var result: Array = []; var rules = ast.stylesheet.rules; @@ -168,6 +180,6 @@ export function applyInlineSyle(view: view.View, style: string) { var filteredDeclarations = syntaxTree.stylesheet.rules[0].declarations.filter((val, i, arr) => { return val.type === "declaration" }); cssSelector.applyInlineSyle(view, filteredDeclarations); } catch (ex) { - trace.write("Applying local style failed: " + ex, trace.categories.Style); + trace.write("Applying local style failed: " + ex, trace.categories.Error, trace.messageType.error); } }