mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
chore: cleanup
This commit is contained in:
@@ -2,18 +2,16 @@
|
||||
* Provides ModuleNameResolver class used for loading files based on device capabilities.
|
||||
*/ /** */
|
||||
|
||||
import { PlatformContext } from "./qualifier-matcher";
|
||||
// export { PlatformContext } from "./qualifier-matcher";
|
||||
import { PlatformContext } from './qualifier-matcher';
|
||||
|
||||
export { PlatformContext } from './qualifier-matcher';
|
||||
|
||||
export type ModuleListProvider = () => string[];
|
||||
|
||||
export class ModuleNameResolver {
|
||||
constructor(
|
||||
context: PlatformContext,
|
||||
moduleListProvider?: ModuleListProvider
|
||||
);
|
||||
resolveModuleName(path: string, ext: string): string;
|
||||
clearCache(): void;
|
||||
constructor(context: PlatformContext, moduleListProvider?: ModuleListProvider);
|
||||
resolveModuleName(path: string, ext: string): string;
|
||||
clearCache(): void;
|
||||
}
|
||||
|
||||
export function resolveModuleName(path: string, ext: string): string;
|
||||
|
||||
@@ -1,123 +1,108 @@
|
||||
import { ModuleNameResolver as ModuleNameResolverDefinition } from "./";
|
||||
import { screen, device } from "../platform";
|
||||
import * as appCommonModule from "../application/application-common";
|
||||
import {
|
||||
PlatformContext,
|
||||
findMatch,
|
||||
stripQualifiers,
|
||||
} from "./qualifier-matcher";
|
||||
import { registerModulesFromFileSystem } from "./non-bundle-workflow-compat";
|
||||
import { Trace } from "../trace";
|
||||
import { ModuleNameResolver as ModuleNameResolverDefinition } from './';
|
||||
import { screen, device } from '../platform';
|
||||
import * as appCommonModule from '../application/application-common';
|
||||
import { PlatformContext, findMatch, stripQualifiers } from './qualifier-matcher';
|
||||
import { registerModulesFromFileSystem } from './non-bundle-workflow-compat';
|
||||
import { Trace } from '../trace';
|
||||
|
||||
export { PlatformContext } from './qualifier-matcher';
|
||||
|
||||
export type ModuleListProvider = () => string[];
|
||||
|
||||
export class ModuleNameResolver implements ModuleNameResolverDefinition {
|
||||
private _cache = {};
|
||||
private _cache = {};
|
||||
|
||||
constructor(
|
||||
private context: PlatformContext,
|
||||
private moduleListProvider: ModuleListProvider = global.getRegisteredModules
|
||||
) {}
|
||||
constructor(private context: PlatformContext, private moduleListProvider: ModuleListProvider = global.getRegisteredModules) {}
|
||||
|
||||
public resolveModuleName(path: string, ext: string): string {
|
||||
const key = path + ext;
|
||||
let result: string = this._cache[key];
|
||||
if (result === undefined) {
|
||||
result = this.resolveModuleNameImpl(path, ext);
|
||||
this._cache[key] = result;
|
||||
}
|
||||
public resolveModuleName(path: string, ext: string): string {
|
||||
const key = path + ext;
|
||||
let result: string = this._cache[key];
|
||||
if (result === undefined) {
|
||||
result = this.resolveModuleNameImpl(path, ext);
|
||||
this._cache[key] = result;
|
||||
}
|
||||
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(
|
||||
`path: '${path}' with ext: '${ext}' resolved: '${result}'`,
|
||||
Trace.categories.ModuleNameResolver
|
||||
);
|
||||
}
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`path: '${path}' with ext: '${ext}' resolved: '${result}'`, Trace.categories.ModuleNameResolver);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public clearCache(): void {
|
||||
this._cache = {};
|
||||
}
|
||||
public clearCache(): void {
|
||||
this._cache = {};
|
||||
}
|
||||
|
||||
private resolveModuleNameImpl(path: string, ext: string): string {
|
||||
let result: string = null;
|
||||
ext = ext ? "." + ext : "";
|
||||
private resolveModuleNameImpl(path: string, ext: string): string {
|
||||
let result: string = null;
|
||||
ext = ext ? '.' + ext : '';
|
||||
|
||||
// Compatibility path for non-webpack workflow
|
||||
// register modules from FS first
|
||||
if (!global.TNS_WEBPACK) {
|
||||
registerModulesFromFileSystem(path);
|
||||
}
|
||||
// Compatibility path for non-webpack workflow
|
||||
// register modules from FS first
|
||||
if (!global.TNS_WEBPACK) {
|
||||
registerModulesFromFileSystem(path);
|
||||
}
|
||||
|
||||
// This call will return a clean path without qualifiers
|
||||
path = stripQualifiers(path);
|
||||
// This call will return a clean path without qualifiers
|
||||
path = stripQualifiers(path);
|
||||
|
||||
let candidates = this.getCandidates(path, ext);
|
||||
result = findMatch(path, ext, candidates, this.context);
|
||||
let candidates = this.getCandidates(path, ext);
|
||||
result = findMatch(path, ext, candidates, this.context);
|
||||
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private getCandidates(path: string, ext: string): Array<string> {
|
||||
const candidates = this.moduleListProvider().filter(
|
||||
(moduleName) =>
|
||||
moduleName.startsWith(path) &&
|
||||
(!ext || moduleName.endsWith(ext))
|
||||
);
|
||||
private getCandidates(path: string, ext: string): Array<string> {
|
||||
const candidates = this.moduleListProvider().filter((moduleName) => moduleName.startsWith(path) && (!ext || moduleName.endsWith(ext)));
|
||||
|
||||
return candidates;
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
}
|
||||
|
||||
let resolverInstance: ModuleNameResolver;
|
||||
|
||||
export function resolveModuleName(path: string, ext: string): string {
|
||||
if (global.__snapshot) {
|
||||
return resolveModuleSnapshot(path, ext);
|
||||
}
|
||||
if (global.__snapshot) {
|
||||
return resolveModuleSnapshot(path, ext);
|
||||
}
|
||||
|
||||
if (!resolverInstance) {
|
||||
resolverInstance = new ModuleNameResolver({
|
||||
width: screen.mainScreen.widthDIPs,
|
||||
height: screen.mainScreen.heightDIPs,
|
||||
os: device.os,
|
||||
deviceType: device.deviceType,
|
||||
});
|
||||
}
|
||||
if (!resolverInstance) {
|
||||
resolverInstance = new ModuleNameResolver({
|
||||
width: screen.mainScreen.widthDIPs,
|
||||
height: screen.mainScreen.heightDIPs,
|
||||
os: device.os,
|
||||
deviceType: device.deviceType,
|
||||
});
|
||||
}
|
||||
|
||||
return resolverInstance.resolveModuleName(path, ext);
|
||||
return resolverInstance.resolveModuleName(path, ext);
|
||||
}
|
||||
|
||||
function resolveModuleSnapshot(path, ext) {
|
||||
Trace.write(
|
||||
`Resolving module in SNAPSHOT context - path: '${path}' with ext: '${ext}'`,
|
||||
Trace.categories.ModuleNameResolver
|
||||
);
|
||||
Trace.write(`Resolving module in SNAPSHOT context - path: '${path}' with ext: '${ext}'`, Trace.categories.ModuleNameResolver);
|
||||
|
||||
// Platform module when in snapshot. So resolve modules with default android phone.
|
||||
// NB: The only module name that should ever be resolved while in snapshot is app.css, because it is
|
||||
// applied explicitly in the snapshot by [NativeScriptSnapshotPlugin](https://github.com/NativeScript/nativescript-dev-webpack/blob/48b26f412fd70c19dc0b9c7763e08e9505a0ae11/plugins/NativeScriptSnapshotPlugin/index.js#L48-L56)
|
||||
return new ModuleNameResolver({
|
||||
width: 400,
|
||||
height: 800,
|
||||
os: "Android",
|
||||
deviceType: "Phone",
|
||||
}).resolveModuleName(path, ext);
|
||||
// Platform module when in snapshot. So resolve modules with default android phone.
|
||||
// NB: The only module name that should ever be resolved while in snapshot is app.css, because it is
|
||||
// applied explicitly in the snapshot by [NativeScriptSnapshotPlugin](https://github.com/NativeScript/nativescript-dev-webpack/blob/48b26f412fd70c19dc0b9c7763e08e9505a0ae11/plugins/NativeScriptSnapshotPlugin/index.js#L48-L56)
|
||||
return new ModuleNameResolver({
|
||||
width: 400,
|
||||
height: 800,
|
||||
os: 'Android',
|
||||
deviceType: 'Phone',
|
||||
}).resolveModuleName(path, ext);
|
||||
}
|
||||
|
||||
export function clearCache() {
|
||||
if (resolverInstance) {
|
||||
resolverInstance.clearCache();
|
||||
}
|
||||
if (resolverInstance) {
|
||||
resolverInstance.clearCache();
|
||||
}
|
||||
}
|
||||
|
||||
export function _setResolver(resolver: ModuleNameResolver) {
|
||||
resolverInstance = resolver;
|
||||
resolverInstance = resolver;
|
||||
}
|
||||
|
||||
appCommonModule.on("livesync", (args) => clearCache());
|
||||
appCommonModule.on("orientationChanged", (args) => {
|
||||
resolverInstance = undefined;
|
||||
appCommonModule.on('livesync', (args) => clearCache());
|
||||
appCommonModule.on('orientationChanged', (args) => {
|
||||
resolverInstance = undefined;
|
||||
});
|
||||
|
||||
@@ -1,73 +1,59 @@
|
||||
import * as fs from "../file-system";
|
||||
import * as appCommonModule from "../application/application-common";
|
||||
import { Trace } from "../trace";
|
||||
import * as fs from '../file-system';
|
||||
import * as appCommonModule from '../application/application-common';
|
||||
import { Trace } from '../trace';
|
||||
|
||||
const cache = new Set<string>();
|
||||
let initialized = false;
|
||||
|
||||
function register(name: string, loader: (name?: string) => void) {
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(
|
||||
`[Compat] Register module: ${name}`,
|
||||
Trace.categories.ModuleNameResolver
|
||||
);
|
||||
}
|
||||
global.registerModule(name, loader);
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`[Compat] Register module: ${name}`, Trace.categories.ModuleNameResolver);
|
||||
}
|
||||
global.registerModule(name, loader);
|
||||
|
||||
if (name.startsWith("tns_modules")) {
|
||||
const nonTnsModulesName = name.substr("tns_modules".length + 1);
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(
|
||||
`[Compat] Register module: ${nonTnsModulesName}`,
|
||||
Trace.categories.ModuleNameResolver
|
||||
);
|
||||
}
|
||||
global.registerModule(nonTnsModulesName, loader);
|
||||
}
|
||||
if (name.startsWith('tns_modules')) {
|
||||
const nonTnsModulesName = name.substr('tns_modules'.length + 1);
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`[Compat] Register module: ${nonTnsModulesName}`, Trace.categories.ModuleNameResolver);
|
||||
}
|
||||
global.registerModule(nonTnsModulesName, loader);
|
||||
}
|
||||
}
|
||||
|
||||
function processFile(file: fs.File) {
|
||||
const filePathRelativeToApp = file.path.substr(
|
||||
fs.knownFolders.currentApp().path.length + 1
|
||||
);
|
||||
const loadContent = () => file.readTextSync();
|
||||
const filePathRelativeToApp = file.path.substr(fs.knownFolders.currentApp().path.length + 1);
|
||||
const loadContent = () => file.readTextSync();
|
||||
|
||||
switch (file.extension.toLocaleLowerCase()) {
|
||||
case ".js":
|
||||
const noExtPath = filePathRelativeToApp.substr(
|
||||
0,
|
||||
filePathRelativeToApp.length - ".js".length
|
||||
);
|
||||
switch (file.extension.toLocaleLowerCase()) {
|
||||
case '.js':
|
||||
const noExtPath = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - '.js'.length);
|
||||
|
||||
register(filePathRelativeToApp, function () {
|
||||
return global.require(file.path);
|
||||
});
|
||||
register(noExtPath, function () {
|
||||
return global.require(file.path);
|
||||
});
|
||||
break;
|
||||
register(filePathRelativeToApp, function () {
|
||||
return global.require(file.path);
|
||||
});
|
||||
register(noExtPath, function () {
|
||||
return global.require(file.path);
|
||||
});
|
||||
break;
|
||||
|
||||
case ".css":
|
||||
register(filePathRelativeToApp, loadContent);
|
||||
break;
|
||||
case '.css':
|
||||
register(filePathRelativeToApp, loadContent);
|
||||
break;
|
||||
|
||||
case ".xml":
|
||||
register(filePathRelativeToApp, loadContent);
|
||||
break;
|
||||
}
|
||||
case '.xml':
|
||||
register(filePathRelativeToApp, loadContent);
|
||||
break;
|
||||
}
|
||||
|
||||
if (file.name === "package.json") {
|
||||
const json = global.require(file.path);
|
||||
if (json.main) {
|
||||
let name = filePathRelativeToApp.substr(
|
||||
0,
|
||||
filePathRelativeToApp.length - "package.json".length - 1
|
||||
);
|
||||
let requirePath = fs.path.join(file.parent.path, json.main);
|
||||
if (file.name === 'package.json') {
|
||||
const json = global.require(file.path);
|
||||
if (json.main) {
|
||||
let name = filePathRelativeToApp.substr(0, filePathRelativeToApp.length - 'package.json'.length - 1);
|
||||
let requirePath = fs.path.join(file.parent.path, json.main);
|
||||
|
||||
register(name, () => global.require(requirePath));
|
||||
}
|
||||
}
|
||||
register(name, () => global.require(requirePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,34 +61,31 @@ function processFile(file: fs.File) {
|
||||
* @param Folder path
|
||||
*/
|
||||
function processFolder(path: string): boolean {
|
||||
if (cache.has(path)) {
|
||||
return true;
|
||||
}
|
||||
cache.add(path);
|
||||
if (cache.has(path)) {
|
||||
return true;
|
||||
}
|
||||
cache.add(path);
|
||||
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(
|
||||
`[Compat] Processing folder: ${path}`,
|
||||
Trace.categories.ModuleNameResolver
|
||||
);
|
||||
}
|
||||
if (Trace.isEnabled()) {
|
||||
Trace.write(`[Compat] Processing folder: ${path}`, Trace.categories.ModuleNameResolver);
|
||||
}
|
||||
|
||||
let folderEmpty = true;
|
||||
let folderEmpty = true;
|
||||
|
||||
if (fs.Folder.exists(path)) {
|
||||
const folder = fs.Folder.fromPath(path);
|
||||
if (fs.Folder.exists(path)) {
|
||||
const folder = fs.Folder.fromPath(path);
|
||||
|
||||
folder.eachEntity((file) => {
|
||||
if (file instanceof fs.File) {
|
||||
processFile(file);
|
||||
folderEmpty = false;
|
||||
}
|
||||
folder.eachEntity((file) => {
|
||||
if (file instanceof fs.File) {
|
||||
processFile(file);
|
||||
folderEmpty = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return !folderEmpty;
|
||||
return !folderEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,62 +94,48 @@ function processFolder(path: string): boolean {
|
||||
* @param moduleName
|
||||
*/
|
||||
export function registerModulesFromFileSystem(moduleName: string) {
|
||||
initialize();
|
||||
initialize();
|
||||
|
||||
let folderProcessed = false;
|
||||
let parentFolderProcessed = false;
|
||||
// moduleName is a folder with package.json
|
||||
const path = fs.path.join(fs.knownFolders.currentApp().path, moduleName);
|
||||
if (fs.Folder.exists(path)) {
|
||||
folderProcessed = processFolder(path);
|
||||
}
|
||||
let folderProcessed = false;
|
||||
let parentFolderProcessed = false;
|
||||
// moduleName is a folder with package.json
|
||||
const path = fs.path.join(fs.knownFolders.currentApp().path, moduleName);
|
||||
if (fs.Folder.exists(path)) {
|
||||
folderProcessed = processFolder(path);
|
||||
}
|
||||
|
||||
// moduleName is file - load all files in its parent folder
|
||||
const parentName = moduleName.substr(
|
||||
0,
|
||||
moduleName.lastIndexOf(fs.path.separator)
|
||||
);
|
||||
const parentFolderPath = fs.path.join(
|
||||
fs.knownFolders.currentApp().path,
|
||||
parentName
|
||||
);
|
||||
if (fs.Folder.exists(parentFolderPath)) {
|
||||
parentFolderProcessed = processFolder(parentFolderPath);
|
||||
}
|
||||
// moduleName is file - load all files in its parent folder
|
||||
const parentName = moduleName.substr(0, moduleName.lastIndexOf(fs.path.separator));
|
||||
const parentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, parentName);
|
||||
if (fs.Folder.exists(parentFolderPath)) {
|
||||
parentFolderProcessed = processFolder(parentFolderPath);
|
||||
}
|
||||
|
||||
// Return only if we processed the actual folder or its parent folder.
|
||||
// If the parent folder is empty we should still check tns_modules
|
||||
// as this might be just a name of a plugin (ex. "nativescript-ui-autocomplete")
|
||||
if (folderProcessed || (parentFolderProcessed && parentName)) {
|
||||
return;
|
||||
}
|
||||
// Return only if we processed the actual folder or its parent folder.
|
||||
// If the parent folder is empty we should still check tns_modules
|
||||
// as this might be just a name of a plugin (ex. "nativescript-ui-autocomplete")
|
||||
if (folderProcessed || (parentFolderProcessed && parentName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// moduleName is a folder in tns_modules ex. "nativescript-ui-chart"
|
||||
const tnsModulesPath = fs.path.join(
|
||||
fs.knownFolders.currentApp().path,
|
||||
"tns_modules",
|
||||
moduleName
|
||||
);
|
||||
if (fs.Folder.exists(tnsModulesPath)) {
|
||||
processFolder(tnsModulesPath);
|
||||
}
|
||||
// moduleName is a folder in tns_modules ex. "nativescript-ui-chart"
|
||||
const tnsModulesPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', moduleName);
|
||||
if (fs.Folder.exists(tnsModulesPath)) {
|
||||
processFolder(tnsModulesPath);
|
||||
}
|
||||
|
||||
// moduleName a file in tns_modules/plugin. Avoid traversing the whole tns_modules folder if parentName is empty
|
||||
if (parentName) {
|
||||
const tnsParentFolderPath = fs.path.join(
|
||||
fs.knownFolders.currentApp().path,
|
||||
"tns_modules",
|
||||
parentName
|
||||
);
|
||||
if (fs.Folder.exists(tnsParentFolderPath)) {
|
||||
processFolder(tnsParentFolderPath);
|
||||
}
|
||||
}
|
||||
// moduleName a file in tns_modules/plugin. Avoid traversing the whole tns_modules folder if parentName is empty
|
||||
if (parentName) {
|
||||
const tnsParentFolderPath = fs.path.join(fs.knownFolders.currentApp().path, 'tns_modules', parentName);
|
||||
if (fs.Folder.exists(tnsParentFolderPath)) {
|
||||
processFolder(tnsParentFolderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
if (!initialized) {
|
||||
appCommonModule.on("livesync", (args) => cache.clear());
|
||||
initialized = true;
|
||||
}
|
||||
if (!initialized) {
|
||||
appCommonModule.on('livesync', (args) => cache.clear());
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,17 +3,12 @@
|
||||
*/
|
||||
|
||||
export interface PlatformContext {
|
||||
width: number;
|
||||
height: number;
|
||||
os: string;
|
||||
deviceType: string;
|
||||
width: number;
|
||||
height: number;
|
||||
os: string;
|
||||
deviceType: string;
|
||||
}
|
||||
|
||||
export function findMatch(
|
||||
path: string,
|
||||
ext: string,
|
||||
candidates: Array<string>,
|
||||
context: PlatformContext
|
||||
): string;
|
||||
export function findMatch(path: string, ext: string, candidates: Array<string>, context: PlatformContext): string;
|
||||
|
||||
export function stripQualifiers(path: string): string;
|
||||
|
||||
@@ -1,197 +1,177 @@
|
||||
const MIN_WH: string = "minWH";
|
||||
const MIN_W: string = "minW";
|
||||
const MIN_H: string = "minH";
|
||||
const MIN_WH: string = 'minWH';
|
||||
const MIN_W: string = 'minW';
|
||||
const MIN_H: string = 'minH';
|
||||
const PRIORITY_STEP = 10000;
|
||||
|
||||
export interface PlatformContext {
|
||||
width: number;
|
||||
height: number;
|
||||
os: string;
|
||||
deviceType: string;
|
||||
width: number;
|
||||
height: number;
|
||||
os: string;
|
||||
deviceType: string;
|
||||
}
|
||||
|
||||
interface QualifierSpec {
|
||||
isMatch(path: string): boolean;
|
||||
getMatchOccurences(path: string): Array<string>;
|
||||
getMatchValue(value: string, context: PlatformContext): number;
|
||||
isMatch(path: string): boolean;
|
||||
getMatchOccurences(path: string): Array<string>;
|
||||
getMatchValue(value: string, context: PlatformContext): number;
|
||||
}
|
||||
|
||||
const minWidthHeightQualifier: QualifierSpec = {
|
||||
isMatch: function (path: string): boolean {
|
||||
return new RegExp(`.${MIN_WH}\\d+`).test(path);
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp(`.${MIN_WH}\\d+`, "g"));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const numVal = parseInt(value.substr(MIN_WH.length + 1));
|
||||
if (isNaN(numVal)) {
|
||||
return -1;
|
||||
}
|
||||
isMatch: function (path: string): boolean {
|
||||
return new RegExp(`.${MIN_WH}\\d+`).test(path);
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp(`.${MIN_WH}\\d+`, 'g'));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const numVal = parseInt(value.substr(MIN_WH.length + 1));
|
||||
if (isNaN(numVal)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const actualLength = Math.min(context.width, context.height);
|
||||
if (actualLength < numVal) {
|
||||
return -1;
|
||||
}
|
||||
const actualLength = Math.min(context.width, context.height);
|
||||
if (actualLength < numVal) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return PRIORITY_STEP - (actualLength - numVal);
|
||||
},
|
||||
return PRIORITY_STEP - (actualLength - numVal);
|
||||
},
|
||||
};
|
||||
|
||||
const minWidthQualifier: QualifierSpec = {
|
||||
isMatch: function (path: string): boolean {
|
||||
return (
|
||||
new RegExp(`.${MIN_W}\\d+`).test(path) &&
|
||||
!new RegExp(`.${MIN_WH}\\d+`).test(path)
|
||||
);
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp(`.${MIN_W}\\d+`, "g"));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const numVal = parseInt(value.substr(MIN_W.length + 1));
|
||||
if (isNaN(numVal)) {
|
||||
return -1;
|
||||
}
|
||||
isMatch: function (path: string): boolean {
|
||||
return new RegExp(`.${MIN_W}\\d+`).test(path) && !new RegExp(`.${MIN_WH}\\d+`).test(path);
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp(`.${MIN_W}\\d+`, 'g'));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const numVal = parseInt(value.substr(MIN_W.length + 1));
|
||||
if (isNaN(numVal)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const actualWidth = context.width;
|
||||
if (actualWidth < numVal) {
|
||||
return -1;
|
||||
}
|
||||
const actualWidth = context.width;
|
||||
if (actualWidth < numVal) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return PRIORITY_STEP - (actualWidth - numVal);
|
||||
},
|
||||
return PRIORITY_STEP - (actualWidth - numVal);
|
||||
},
|
||||
};
|
||||
|
||||
const minHeightQualifier: QualifierSpec = {
|
||||
isMatch: function (path: string): boolean {
|
||||
return (
|
||||
new RegExp(`.${MIN_H}\\d+`).test(path) &&
|
||||
!new RegExp(`.${MIN_WH}\\d+`).test(path)
|
||||
);
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp(`.${MIN_H}\\d+`, "g"));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const numVal = parseInt(value.substr(MIN_H.length + 1));
|
||||
if (isNaN(numVal)) {
|
||||
return -1;
|
||||
}
|
||||
isMatch: function (path: string): boolean {
|
||||
return new RegExp(`.${MIN_H}\\d+`).test(path) && !new RegExp(`.${MIN_WH}\\d+`).test(path);
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp(`.${MIN_H}\\d+`, 'g'));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const numVal = parseInt(value.substr(MIN_H.length + 1));
|
||||
if (isNaN(numVal)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const actualHeight = context.height;
|
||||
if (actualHeight < numVal) {
|
||||
return -1;
|
||||
}
|
||||
const actualHeight = context.height;
|
||||
if (actualHeight < numVal) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return PRIORITY_STEP - (actualHeight - numVal);
|
||||
},
|
||||
return PRIORITY_STEP - (actualHeight - numVal);
|
||||
},
|
||||
};
|
||||
|
||||
const platformQualifier: QualifierSpec = {
|
||||
isMatch: function (path: string): boolean {
|
||||
return path.includes(".android") || path.includes(".ios");
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp("\\.android|\\.ios", "g"));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const val = value.substr(1);
|
||||
isMatch: function (path: string): boolean {
|
||||
return path.includes('.android') || path.includes('.ios');
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp('\\.android|\\.ios', 'g'));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const val = value.substr(1);
|
||||
|
||||
return val === context.os.toLowerCase() ? 1 : -1;
|
||||
},
|
||||
return val === context.os.toLowerCase() ? 1 : -1;
|
||||
},
|
||||
};
|
||||
|
||||
const orientationQualifier: QualifierSpec = {
|
||||
isMatch: function (path: string): boolean {
|
||||
return path.includes(".land") || path.includes(".port");
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp("\\.land|\\.port", "g"));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const val = value.substr(1);
|
||||
const isLandscape: number = context.width > context.height ? 1 : -1;
|
||||
isMatch: function (path: string): boolean {
|
||||
return path.includes('.land') || path.includes('.port');
|
||||
},
|
||||
getMatchOccurences: function (path: string): Array<string> {
|
||||
return path.match(new RegExp('\\.land|\\.port', 'g'));
|
||||
},
|
||||
getMatchValue(value: string, context: PlatformContext): number {
|
||||
const val = value.substr(1);
|
||||
const isLandscape: number = context.width > context.height ? 1 : -1;
|
||||
|
||||
return val === "land" ? isLandscape : -isLandscape;
|
||||
},
|
||||
return val === 'land' ? isLandscape : -isLandscape;
|
||||
},
|
||||
};
|
||||
|
||||
// List of supported qualifiers ordered by priority
|
||||
const supportedQualifiers: Array<QualifierSpec> = [
|
||||
minWidthHeightQualifier,
|
||||
minWidthQualifier,
|
||||
minHeightQualifier,
|
||||
orientationQualifier,
|
||||
platformQualifier,
|
||||
];
|
||||
const supportedQualifiers: Array<QualifierSpec> = [minWidthHeightQualifier, minWidthQualifier, minHeightQualifier, orientationQualifier, platformQualifier];
|
||||
|
||||
function checkQualifiers(path: string, context: PlatformContext): number {
|
||||
let result = 0;
|
||||
for (let i = 0; i < supportedQualifiers.length; i++) {
|
||||
let qualifier = supportedQualifiers[i];
|
||||
if (qualifier.isMatch(path)) {
|
||||
let occurences = qualifier.getMatchOccurences(path);
|
||||
// Always get the last qualifier among identical occurences
|
||||
result = qualifier.getMatchValue(
|
||||
occurences[occurences.length - 1],
|
||||
context
|
||||
);
|
||||
if (result < 0) {
|
||||
// Non of the supported qualifiers matched this or the match was not satisfied
|
||||
return -1;
|
||||
}
|
||||
let result = 0;
|
||||
for (let i = 0; i < supportedQualifiers.length; i++) {
|
||||
let qualifier = supportedQualifiers[i];
|
||||
if (qualifier.isMatch(path)) {
|
||||
let occurences = qualifier.getMatchOccurences(path);
|
||||
// Always get the last qualifier among identical occurences
|
||||
result = qualifier.getMatchValue(occurences[occurences.length - 1], context);
|
||||
if (result < 0) {
|
||||
// Non of the supported qualifiers matched this or the match was not satisfied
|
||||
return -1;
|
||||
}
|
||||
|
||||
result += (supportedQualifiers.length - i) * PRIORITY_STEP;
|
||||
result += (supportedQualifiers.length - i) * PRIORITY_STEP;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
export function stripQualifiers(path: string): string {
|
||||
// Strip qualifiers from path if any
|
||||
for (let i = 0; i < supportedQualifiers.length; i++) {
|
||||
let qualifier = supportedQualifiers[i];
|
||||
if (qualifier.isMatch(path)) {
|
||||
let occurences = qualifier.getMatchOccurences(path);
|
||||
for (let j = 0; j < occurences.length; j++) {
|
||||
path = path.replace(occurences[j], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Strip qualifiers from path if any
|
||||
for (let i = 0; i < supportedQualifiers.length; i++) {
|
||||
let qualifier = supportedQualifiers[i];
|
||||
if (qualifier.isMatch(path)) {
|
||||
let occurences = qualifier.getMatchOccurences(path);
|
||||
for (let j = 0; j < occurences.length; j++) {
|
||||
path = path.replace(occurences[j], '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
return path;
|
||||
}
|
||||
|
||||
export function findMatch(
|
||||
path: string,
|
||||
ext: string,
|
||||
candidates: Array<string>,
|
||||
context: PlatformContext
|
||||
): string {
|
||||
let fullPath: string = ext ? path + ext : path;
|
||||
let bestValue = -1;
|
||||
let result: string = null;
|
||||
export function findMatch(path: string, ext: string, candidates: Array<string>, context: PlatformContext): string {
|
||||
let fullPath: string = ext ? path + ext : path;
|
||||
let bestValue = -1;
|
||||
let result: string = null;
|
||||
|
||||
for (let i = 0; i < candidates.length; i++) {
|
||||
const filePath = candidates[i];
|
||||
for (let i = 0; i < candidates.length; i++) {
|
||||
const filePath = candidates[i];
|
||||
|
||||
// Check if candidate is correct for given path
|
||||
const cleanFilePath: string = stripQualifiers(filePath);
|
||||
if (cleanFilePath !== fullPath) {
|
||||
continue;
|
||||
}
|
||||
// Check if candidate is correct for given path
|
||||
const cleanFilePath: string = stripQualifiers(filePath);
|
||||
if (cleanFilePath !== fullPath) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = checkQualifiers(filePath, context);
|
||||
const value = checkQualifiers(filePath, context);
|
||||
|
||||
if (value >= 0 && value > bestValue) {
|
||||
bestValue = value;
|
||||
result = candidates[i];
|
||||
}
|
||||
}
|
||||
if (value >= 0 && value > bestValue) {
|
||||
bestValue = value;
|
||||
result = candidates[i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user