Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

feat(platforms): Add support for custom platform plugins #1119

Merged
merged 3 commits into from
Jan 30, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion bundle-config-loader.ts
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ const loader: loader.Loader = function (source, map) {
let {
angular = false,
loadCss = true,
platform,
unitTesting,
projectRoot,
appFullPath,
@@ -53,8 +54,14 @@ const loader: loader.Loader = function (source, map) {
}
`;

let sourceModule = "tns-core-modules";

if (platform && platform !== "ios" && platform !== "android") {
sourceModule = `nativescript-platform-${platform}`;
}

source = `
require("tns-core-modules/bundle-entry-points");
require("${sourceModule}/bundle-entry-points");
${source}
`;

11 changes: 10 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
@@ -103,6 +103,8 @@ exports.getAppPath = (platform, projectDir) => {
return `platforms/ios/${sanitizedName}/app`;
} else if (isAndroid(platform)) {
return ANDROID_APP_PATH;
} else if (hasPlatformPlugin(projectDir, platform)) {
return `platforms/${platform}/app`;
} else {
throw new Error(`Invalid platform: ${platform}`);
}
@@ -191,6 +193,13 @@ const sanitize = name => name
.filter(char => /[a-zA-Z0-9]/.test(char))
.join("");

function hasPlatformPlugin(appDirectory, platform) {
const packageJsonSource = getPackageJson(appDirectory);
const { dependencies } = packageJsonSource;

return !!dependencies[`nativescript-platform-${platform}`];
}

function getPackageJsonEntry(appDirectory) {
const packageJsonSource = getPackageJson(appDirectory);
const entry = packageJsonSource.main;
@@ -252,4 +261,4 @@ function ensurePathInCompilerOptions({ compilerOptions, sourcePath, destinationP
} else {
paths[sourcePath] = [destinationPath];
}
}
}
33 changes: 29 additions & 4 deletions plugins/PlatformFSPlugin.ts
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ export interface PlatformFSPluginOptions {
platform?: string;

/**
* A list of all platforms. By default it is `["ios", "android"]`.
* A list of all platforms. By default it is `["ios", "android", "desktop"]`.
*/
platforms?: string[];

@@ -18,6 +18,8 @@ export interface PlatformFSPluginOptions {
ignore?: string[];
}

const internalPlatforms = ["ios", "android"];

export class PlatformFSPlugin {
protected readonly platform: string;
protected readonly platforms: ReadonlyArray<string>;
@@ -26,7 +28,7 @@ export class PlatformFSPlugin {

constructor({ platform, platforms, ignore }: PlatformFSPluginOptions) {
this.platform = platform || "";
this.platforms = platforms || ["ios", "android"];
this.platforms = platforms || internalPlatforms;
this.ignore = ignore || [];
}

@@ -58,6 +60,8 @@ export function mapFileSystem(args: MapFileSystemArgs): any {
const fs = compiler.inputFileSystem;
ignore = args.ignore || [];

const isExternal = internalPlatforms.indexOf(platform) === -1;

const minimatchFileFilters = ignore.map(pattern => {
const minimatchFilter = minimatch.filter(pattern);
return file => minimatchFilter(relative(context, file));
@@ -80,7 +84,7 @@ export function mapFileSystem(args: MapFileSystemArgs): any {
return join(dir, name.substr(0, name.length - currentPlatformExt.length) + ext);
}
return file;
}
};

const isNotIgnored = file => !isIgnored(file);

@@ -95,7 +99,28 @@ export function mapFileSystem(args: MapFileSystemArgs): any {

function platformSpecificFile(file: string): string {
const {dir, name, ext} = parseFile(file);
const platformFilePath = join(dir, `${name}.${platform}${ext}`);
let platformFilePath = join(dir, `${name}.${platform}${ext}`);

if (isExternal && dir.indexOf("/@nativescript/core/") !== -1) {
let replacedPath;
try {
replacedPath = dir.replace(
/node_modules(\/[^/]+)?\/@nativescript\/core/,
`node_modules/nativescript-platform-${platform}`
);

platformFilePath = require.resolve(join(replacedPath, `${name}.${platform}${ext}`));
} catch (e) {
if (replacedPath) {
if (ext === ".d") {
platformFilePath = undefined;
} else {
platformFilePath = join(replacedPath, `${name}${ext}`);
}
}
}
}

return platformFilePath;
}

2 changes: 1 addition & 1 deletion templates/webpack.angular.js
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ module.exports = env => {
"tns-core-modules/ui/frame/activity",
]);

const platform = env && (env.android && "android" || env.ios && "ios");
const platform = env && (env.android && "android" || env.ios && "ios" || env.platform);
if (!platform) {
throw new Error("You need to provide a target platform!");
}
6 changes: 5 additions & 1 deletion templates/webpack.javascript.js
Original file line number Diff line number Diff line change
@@ -18,14 +18,18 @@ module.exports = env => {
"tns-core-modules/ui/frame/activity",
]);

const platform = env && (env.android && "android" || env.ios && "ios");
const platform = env && (env.android && "android" || env.ios && "ios" || env.platform);
if (!platform) {
throw new Error("You need to provide a target platform!");
}

const platforms = ["ios", "android"];
const projectRoot = __dirname;

if (env.platform) {
platforms.push(env.platform);
}

// Default destination inside platforms/<platform>/...
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));

6 changes: 5 additions & 1 deletion templates/webpack.typescript.js
Original file line number Diff line number Diff line change
@@ -20,14 +20,18 @@ module.exports = env => {
"tns-core-modules/ui/frame/activity",
]);

const platform = env && (env.android && "android" || env.ios && "ios");
const platform = env && (env.android && "android" || env.ios && "ios" || env.platform);
if (!platform) {
throw new Error("You need to provide a target platform!");
}

const platforms = ["ios", "android"];
const projectRoot = __dirname;

if (env.platform) {
platforms.push(env.platform);
}

// Default destination inside platforms/<platform>/...
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));

6 changes: 5 additions & 1 deletion templates/webpack.vue.js
Original file line number Diff line number Diff line change
@@ -22,14 +22,18 @@ module.exports = env => {
"tns-core-modules/ui/frame/activity",
]);

const platform = env && (env.android && "android" || env.ios && "ios");
const platform = env && (env.android && "android" || env.ios && "ios" || env.platform);
if (!platform) {
throw new Error("You need to provide a target platform!");
}

const platforms = ["ios", "android"];
const projectRoot = __dirname;

if (env.platform) {
platforms.push(env.platform);
}

// Default destination inside platforms/<platform>/...
const dist = resolve(projectRoot, nsWebpack.getAppPath(platform, projectRoot));

8 changes: 5 additions & 3 deletions xml-namespace-loader.ts
Original file line number Diff line number Diff line change
@@ -100,13 +100,15 @@ const loader: loader.Loader = function (source: string, map) {
// Register ios and android prefixes as namespaces to avoid "unbound xml namespace" errors
(<any>saxParser).ns["ios"] = "http://schemas.nativescript.org/tns.xsd";
(<any>saxParser).ns["android"] = "http://schemas.nativescript.org/tns.xsd";
(<any>saxParser).ns["desktop"] = "http://schemas.nativescript.org/tns.xsd";
(<any>saxParser).ns["web"] = "http://schemas.nativescript.org/tns.xsd";

saxParser.onopentag = (node: QualifiedTag) => { handleOpenTag(node.uri, node.local); };
saxParser.onerror = (err) => {
// Do only warning about invalid character "&"" for back-compatibility
// as it is common to use it in a binding expression
if (err &&
err.message.indexOf("Invalid character") >= 0 &&
if (err &&
err.message.indexOf("Invalid character") >= 0 &&
err.message.indexOf("Char: &") >= 0) {
this.emitWarning(err)
} else {
@@ -140,4 +142,4 @@ const loader: loader.Loader = function (source: string, map) {
})
}

export default loader;
export default loader;