diff --git a/tests/app/ui/styling/style-tests.ts b/tests/app/ui/styling/style-tests.ts index 140c1a41d..10ba90741 100644 --- a/tests/app/ui/styling/style-tests.ts +++ b/tests/app/ui/styling/style-tests.ts @@ -12,6 +12,7 @@ import types = require("utils/types"); import viewModule = require("ui/core/view"); import styleModule = require("ui/styling/style"); import dependencyObservableModule = require("ui/core/dependency-observable"); +import { resolveFileNameFromUrl } from "ui/styling/style-scope"; export function test_css_dataURI_is_applied_to_backgroundImageSource() { var stack = new stackModule.StackLayout(); @@ -1382,9 +1383,9 @@ export function test_star_attr_selector_incorrect_syntax() { export function test_alone_attr_selector() { let testButton = new buttonModule.Button(); testButton["testAttr"] = "flow"; - + let testCss = "[testAttr*='flower'] { background-color: #FF0000; } button { background-color: #00FF00; }"; - + let testFunc = function (views: Array) { // style from correct type css should be applied helper.assertViewBackgroundColor(testButton, "#00FF00"); @@ -1395,9 +1396,9 @@ export function test_alone_attr_selector() { export function test_UsingSameSelectors_ShouldApplyLatest() { let testButton = new buttonModule.Button(); testButton.className = 'green'; - + let testCss = ".green { background-color: #FF0000; } .green { background-color: #00FF00; }"; - + let testFunc = function (views: Array) { // style from correct type css should be applied helper.assertViewBackgroundColor(testButton, "#00FF00"); @@ -1408,9 +1409,9 @@ export function test_UsingSameSelectors_ShouldApplyLatest() { export function test_UsingSameSelectorsWithSpecific_ShouldApplyLatest() { let testButton = new buttonModule.Button(); testButton.className = 'red green'; - + let testCss = ".red { background-color: #FF0000; } Button.green { background-color: #00FF00; }"; - + let testFunc = function (views: Array) { // style from correct type css should be applied helper.assertViewBackgroundColor(testButton, "#00FF00"); @@ -1435,6 +1436,55 @@ export function test_CascadingClassNamesAppliesAfterPageLoad() { }); } +export function test_resolveFileNameFromUrl_local_file_tilda() { + const localFileExistsMock = (fileName: string ) => true; + let url = "~/theme/core.css"; + let appDirectory = "app"; + let expected = `${appDirectory}/theme/core.css`; + let result = resolveFileNameFromUrl(url, appDirectory, localFileExistsMock); + + TKUnit.assertEqual(result, expected, "Should resolve local file with leading tilda (~/)"); +} + +export function test_resolveFileNameFromUrl_local_file_no_tilda() { + const localFileExistsMock = (fileName: string ) => true; + let url = "theme/core.css"; + let appDirectory = "app"; + let expected = `${appDirectory}/theme/core.css`; + let result = resolveFileNameFromUrl(url, appDirectory, localFileExistsMock); + + TKUnit.assertEqual(result, expected, "Should resolve local file without leading tilda (no ~/)"); +} + +export function test_resolveFileNameFromUrl_external_file_tilda() { + const externalFileExistsMock = (fileName: string) => (fileName.indexOf("tns_modules") !== -1); + let url = "~/theme/core.css"; + let appDirectory = "app"; + let expected = `${appDirectory}/tns_modules/theme/core.css`; + let result = resolveFileNameFromUrl(url, appDirectory, externalFileExistsMock); + + TKUnit.assertEqual(result, expected, "Should resolve file from tns_modules with leading tilda (~/)"); +} + +export function test_resolveFileNameFromUrl_external_file_no_tilda() { + const externalFileExistsMock = (fileName: string) => (fileName.indexOf("tns_modules") !== -1); + let url = "theme/core.css"; + let appDirectory = "app"; + let expected = `${appDirectory}/tns_modules/theme/core.css`; + let result = resolveFileNameFromUrl(url, appDirectory, externalFileExistsMock); + + TKUnit.assertEqual(result, expected, "Should resolve file from tns_modules without leading tilda (no ~/)"); +} + +export function test_resolveFileNameFromUrl_unexisting_file() { + const fileDoesNotExistMock = (fileName: string) => false; + let url = "~/theme/core.css"; + let appDirectory = "app"; + let result = resolveFileNameFromUrl(url, appDirectory, fileDoesNotExistMock); + + TKUnit.assertNull(result, "Shouldn't resolve unexisting file"); +} + // -// For information and example how to use style properties please refer to special [**Styling**](../../../styling.md) topic. +// For information and example how to use style properties please refer to special [**Styling**](../../../styling.md) topic. // diff --git a/tns-core-modules/ui/styling/style-scope.d.ts b/tns-core-modules/ui/styling/style-scope.d.ts index 429bb8029..7cdbd15b5 100644 --- a/tns-core-modules/ui/styling/style-scope.d.ts +++ b/tns-core-modules/ui/styling/style-scope.d.ts @@ -32,5 +32,6 @@ declare module "ui/styling/style-scope" { public getAnimations(ruleset: RuleSet): KeyframeAnimationInfo[]; } + export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (string) => boolean): string; export function applyInlineSyle(view: view.View, style: string): void; } diff --git a/tns-core-modules/ui/styling/style-scope.ts b/tns-core-modules/ui/styling/style-scope.ts index ce471ae50..bbfc4e79e 100644 --- a/tns-core-modules/ui/styling/style-scope.ts +++ b/tns-core-modules/ui/styling/style-scope.ts @@ -149,13 +149,11 @@ export class StyleScope { if (utils.isFileOrResourcePath(url)) { ensureFS(); - let fileName = types.isString(url) ? url.trim() : ""; - if (fileName.indexOf("~/") === 0) { - fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", "")); - } + let appDirectory = fs.knownFolders.currentApp().path; + let fileName = resolveFileNameFromUrl(url, appDirectory, fs.File.exists); - if (fs.File.exists(fileName)) { - let file = fs.File.fromPath(fileName); + if (fileName !== null) { + let file: fileSystemModule.File = fs.File.fromPath(fileName); let text = file.readTextSync(); if (text) { selectors = selectors.concat(StyleScope.createSelectorsFromCss(text, fileName, keyframes)); @@ -197,7 +195,7 @@ export class StyleScope { } public applySelectors(view: view.View): void { - this.ensureSelectors(); + this.ensureSelectors(); let state = this._selectors.query(view); @@ -245,6 +243,26 @@ export class StyleScope { } } +export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (string) => boolean): string { + let fileName: string = types.isString(url) ? url.trim() : ""; + + if (fileName.indexOf("~/") === 0) { + fileName = fileName.replace("~/", ""); + } + + let local = fs.path.join(appDirectory, fileName); + if (fileExists(local)) { + return local; + } + + let external = fs.path.join(appDirectory, "tns_modules", fileName); + if (fileExists(external)) { + return external; + } + + return null; +} + export function applyInlineSyle(view: view.View, style: string) { try { let syntaxTree = cssParser.parse("local { " + style + " }", undefined);