Skip to content

Commit 414ebc6

Browse files
committed
feat(style-scope): Resolve css sheets from tns_modules
If the css sheet is not in the app directory, try to find it in the tns_modules folder.
1 parent 8e2af03 commit 414ebc6

File tree

3 files changed

+83
-14
lines changed

3 files changed

+83
-14
lines changed

tests/app/ui/styling/style-tests.ts

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import types = require("utils/types");
1212
import viewModule = require("ui/core/view");
1313
import styleModule = require("ui/styling/style");
1414
import dependencyObservableModule = require("ui/core/dependency-observable");
15+
import { resolveFileNameFromUrl } from "ui/styling/style-scope";
1516

1617
export function test_css_dataURI_is_applied_to_backgroundImageSource() {
1718
var stack = new stackModule.StackLayout();
@@ -1382,9 +1383,9 @@ export function test_star_attr_selector_incorrect_syntax() {
13821383
export function test_alone_attr_selector() {
13831384
let testButton = new buttonModule.Button();
13841385
testButton["testAttr"] = "flow";
1385-
1386+
13861387
let testCss = "[testAttr*='flower'] { background-color: #FF0000; } button { background-color: #00FF00; }";
1387-
1388+
13881389
let testFunc = function (views: Array<viewModule.View>) {
13891390
// style from correct type css should be applied
13901391
helper.assertViewBackgroundColor(testButton, "#00FF00");
@@ -1395,9 +1396,9 @@ export function test_alone_attr_selector() {
13951396
export function test_UsingSameSelectors_ShouldApplyLatest() {
13961397
let testButton = new buttonModule.Button();
13971398
testButton.className = 'green';
1398-
1399+
13991400
let testCss = ".green { background-color: #FF0000; } .green { background-color: #00FF00; }";
1400-
1401+
14011402
let testFunc = function (views: Array<viewModule.View>) {
14021403
// style from correct type css should be applied
14031404
helper.assertViewBackgroundColor(testButton, "#00FF00");
@@ -1408,9 +1409,9 @@ export function test_UsingSameSelectors_ShouldApplyLatest() {
14081409
export function test_UsingSameSelectorsWithSpecific_ShouldApplyLatest() {
14091410
let testButton = new buttonModule.Button();
14101411
testButton.className = 'red green';
1411-
1412+
14121413
let testCss = ".red { background-color: #FF0000; } Button.green { background-color: #00FF00; }";
1413-
1414+
14141415
let testFunc = function (views: Array<viewModule.View>) {
14151416
// style from correct type css should be applied
14161417
helper.assertViewBackgroundColor(testButton, "#00FF00");
@@ -1435,6 +1436,55 @@ export function test_CascadingClassNamesAppliesAfterPageLoad() {
14351436
});
14361437
}
14371438

1439+
export function test_resolveFileNameFromUrl_local_file_tilda() {
1440+
const localFileExistsMock = (fileName: string ) => true;
1441+
let url = "~/theme/core.css";
1442+
let appDirectory = "app";
1443+
let expected = `${appDirectory}/theme/core.css`;
1444+
let result = resolveFileNameFromUrl(url, appDirectory, localFileExistsMock);
1445+
1446+
TKUnit.assertEqual(result, expected, "Should resolve local file with leading tilda (~/)");
1447+
}
1448+
1449+
export function test_resolveFileNameFromUrl_local_file_no_tilda() {
1450+
const localFileExistsMock = (fileName: string ) => true;
1451+
let url = "theme/core.css";
1452+
let appDirectory = "app";
1453+
let expected = `${appDirectory}/theme/core.css`;
1454+
let result = resolveFileNameFromUrl(url, appDirectory, localFileExistsMock);
1455+
1456+
TKUnit.assertEqual(result, expected, "Should resolve local file without leading tilda (no ~/)");
1457+
}
1458+
1459+
export function test_resolveFileNameFromUrl_external_file_tilda() {
1460+
const externalFileExistsMock = (fileName: string) => (fileName.indexOf("tns_modules") !== -1);
1461+
let url = "~/theme/core.css";
1462+
let appDirectory = "app";
1463+
let expected = `${appDirectory}/tns_modules/theme/core.css`;
1464+
let result = resolveFileNameFromUrl(url, appDirectory, externalFileExistsMock);
1465+
1466+
TKUnit.assertEqual(result, expected, "Should resolve file from tns_modules with leading tilda (~/)");
1467+
}
1468+
1469+
export function test_resolveFileNameFromUrl_external_file_no_tilda() {
1470+
const externalFileExistsMock = (fileName: string) => (fileName.indexOf("tns_modules") !== -1);
1471+
let url = "theme/core.css";
1472+
let appDirectory = "app";
1473+
let expected = `${appDirectory}/tns_modules/theme/core.css`;
1474+
let result = resolveFileNameFromUrl(url, appDirectory, externalFileExistsMock);
1475+
1476+
TKUnit.assertEqual(result, expected, "Should resolve file from tns_modules without leading tilda (no ~/)");
1477+
}
1478+
1479+
export function test_resolveFileNameFromUrl_unexisting_file() {
1480+
const fileDoesNotExistMock = (fileName: string) => false;
1481+
let url = "~/theme/core.css";
1482+
let appDirectory = "app";
1483+
let result = resolveFileNameFromUrl(url, appDirectory, fileDoesNotExistMock);
1484+
1485+
TKUnit.assertNull(result, "Shouldn't resolve unexisting file");
1486+
}
1487+
14381488
// <snippet module="ui/styling" title="styling">
1439-
// For information and example how to use style properties please refer to special [**Styling**](../../../styling.md) topic.
1489+
// For information and example how to use style properties please refer to special [**Styling**](../../../styling.md) topic.
14401490
// </snippet>

tns-core-modules/ui/styling/style-scope.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ declare module "ui/styling/style-scope" {
3232
public getAnimations(ruleset: RuleSet): KeyframeAnimationInfo[];
3333
}
3434

35+
export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (string) => boolean): string;
3536
export function applyInlineSyle(view: view.View, style: string): void;
3637
}

tns-core-modules/ui/styling/style-scope.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,11 @@ export class StyleScope {
149149
if (utils.isFileOrResourcePath(url)) {
150150
ensureFS();
151151

152-
let fileName = types.isString(url) ? url.trim() : "";
153-
if (fileName.indexOf("~/") === 0) {
154-
fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", ""));
155-
}
152+
let appDirectory = fs.knownFolders.currentApp().path;
153+
let fileName = resolveFileNameFromUrl(url, appDirectory, fs.File.exists);
156154

157-
if (fs.File.exists(fileName)) {
158-
let file = fs.File.fromPath(fileName);
155+
if (fileName !== null) {
156+
let file: fileSystemModule.File = fs.File.fromPath(fileName);
159157
let text = file.readTextSync();
160158
if (text) {
161159
selectors = selectors.concat(StyleScope.createSelectorsFromCss(text, fileName, keyframes));
@@ -197,7 +195,7 @@ export class StyleScope {
197195
}
198196

199197
public applySelectors(view: view.View): void {
200-
this.ensureSelectors();
198+
this.ensureSelectors();
201199

202200
let state = this._selectors.query(view);
203201

@@ -245,6 +243,26 @@ export class StyleScope {
245243
}
246244
}
247245

246+
export function resolveFileNameFromUrl(url: string, appDirectory: string, fileExists: (string) => boolean): string {
247+
let fileName: string = types.isString(url) ? url.trim() : "";
248+
249+
if (fileName.indexOf("~/") === 0) {
250+
fileName = fileName.replace("~/", "");
251+
}
252+
253+
let local = fs.path.join(appDirectory, fileName);
254+
if (fileExists(local)) {
255+
return local;
256+
}
257+
258+
let external = fs.path.join(appDirectory, "tns_modules", fileName);
259+
if (fileExists(external)) {
260+
return external;
261+
}
262+
263+
return null;
264+
}
265+
248266
export function applyInlineSyle(view: view.View, style: string) {
249267
try {
250268
let syntaxTree = cssParser.parse("local { " + style + " }", undefined);

0 commit comments

Comments
 (0)