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

Commit

Permalink
feat: add UrlResolvePlugin for platform-specific template/style urls (#…
Browse files Browse the repository at this point in the history
…155)

fixes #75
  • Loading branch information
EddyVerbruggen authored and sis0k0 committed May 29, 2017
1 parent 30e9c97 commit 2ccf55b
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 103 deletions.
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ var isAngular = Object.keys(packageJson.dependencies).filter(function (dependenc


if (isAngular) {
exports.StyleUrlResolvePlugin = require("./resource-resolver-plugins/StyleUrlResolvePlugin");
exports.UrlResolvePlugin = require("./resource-resolver-plugins/UrlResolvePlugin");
}

//HACK: changes the JSONP chunk eval function to `global["nativescriptJsonp"]`
Expand Down
1 change: 1 addition & 0 deletions installer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function install() {
let packageJson = helpers.getPackageJson(PROJECT_DIR);

projectFilesManager.addProjectFiles(PROJECT_DIR, APP_DIR);
projectFilesManager.editExistingProjectFiles(PROJECT_DIR);

let scripts = packageJson.scripts || {};
scripts = npmScriptsManager.removeDeprecatedNpmScripts(scripts);
Expand Down
8 changes: 6 additions & 2 deletions prepublish/angular/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ module.exports = `
typeChecking: false
}),

// Resolve .ios.css and .android.css component stylesheets
new nsWebpack.StyleUrlResolvePlugin({platform}),
// Resolve .ios.css and .android.css component stylesheets, and .ios.html and .android component views
new nsWebpack.UrlResolvePlugin({
platform: platform,
resolveStylesUrls: true,
resolveTemplateUrl: true
}),
`;
24 changes: 24 additions & 0 deletions projectFilesManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,29 @@ function getFullTemplatesPath(projectDir, templates) {
return updatedTemplates;
}

function editExistingProjectFiles(projectDir) {
const webpackConfigPath = getFullPath(projectDir, "webpack.config.js");
const webpackCommonPath = getFullPath(projectDir, "webpack.common.js");

editWebpackConfig(webpackConfigPath, replaceStyleUrlResolvePlugin);
editWebpackConfig(webpackCommonPath, replaceStyleUrlResolvePlugin);
}

function editWebpackConfig(path, fn) {
if (!fs.existsSync(path)) {
return;
}

const config = fs.readFileSync(path, "utf8");
const newConfig = fn(config);

fs.writeFileSync(path, newConfig, "utf8");
}

function replaceStyleUrlResolvePlugin(config) {
return config.replace(/StyleUrlResolvePlugin/g, "UrlResolvePlugin");
}

function getFullPath(projectDir, filePath) {
return path.resolve(projectDir, filePath);
}
Expand All @@ -103,4 +126,5 @@ function tsOrJs(projectDir, name) {
module.exports = {
addProjectFiles,
removeProjectFiles,
editExistingProjectFiles,
};
97 changes: 0 additions & 97 deletions resource-resolver-plugins/StyleUrlResolvePlugin.js

This file was deleted.

109 changes: 109 additions & 0 deletions resource-resolver-plugins/UrlResolvePlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const ts = require("typescript");
const fs = require("fs");
const path = require("path");

const UrlResolvePlugin = (function() {
function UrlResolvePlugin(options) {
if (!options || !options.platform) {
throw new Error(`Target platform must be specified!`);
}

this.platform = options.platform;

// these are true by default
this.resolveStylesUrls = options.resolveStylesUrls === undefined || options.resolveStylesUrls;
this.resolveTemplateUrl = options.resolveTemplateUrl === undefined || options.resolveTemplateUrl;

if (!this.resolveStylesUrls && !this.resolveTemplateUrl) {
throw new Error(`resolveStylesUrls and resolveTemplateUrl mustn't both be false`);
}
}

UrlResolvePlugin.prototype.apply = function (compiler) {
compiler.plugin("make", (compilation, callback) => {
const aotPlugin = getAotPlugin(compilation);
aotPlugin._program.getSourceFiles()
.forEach(sf => this.usePlatformUrl(sf));

callback();
})
};

function getAotPlugin(compilation) {
let maybeAotPlugin = compilation._ngToolsWebpackPluginInstance;
if (!maybeAotPlugin) {
throw new Error(`This plugin must be used with the AotPlugin!`);
}

return maybeAotPlugin;
}

UrlResolvePlugin.prototype.usePlatformUrl = function(sourceFile) {
this.setCurrentDirectory(sourceFile);
ts.forEachChild(sourceFile, node => this.traverseDecorators(node));
}

UrlResolvePlugin.prototype.setCurrentDirectory = function(sourceFile) {
this.currentDirectory = path.resolve(sourceFile.path, "..");
}

UrlResolvePlugin.prototype.traverseDecorators = function(node) {
if (node.kind !== ts.SyntaxKind.ClassDeclaration || !node.decorators) {
return;
}

node.decorators.forEach(decorator => {
this.traverseDecoratorArguments(decorator.expression.arguments);
});
}

UrlResolvePlugin.prototype.traverseDecoratorArguments = function(args) {
args.forEach(arg => arg.properties && this.traverseProperties(arg.properties));
}

UrlResolvePlugin.prototype.traverseProperties = function(properties) {
properties
.filter(prop => this.isRelevantNode(prop))
.forEach(prop => this.traversePropertyElements(prop));
}

UrlResolvePlugin.prototype.isRelevantNode = function(property) {
return this.resolveStylesUrls && property.name.text === "styleUrls" ||
this.resolveTemplateUrl && property.name.text === "templateUrl"
}

UrlResolvePlugin.prototype.traversePropertyElements = function(property) {
const elements = property.initializer.elements === undefined ? [property.initializer] : property.initializer.elements;

elements
.filter(el => !!el.text)
.filter(el => this.notPlatformUrl(el.text))
.filter(el => this.noMultiplatformFile(el.text))
.forEach(el => this.replaceUrlsValue(el));
}

UrlResolvePlugin.prototype.notPlatformUrl = function(url) {
let extensionStartIndex = url.lastIndexOf(".");
let extension = url.slice(extensionStartIndex);

return !url.endsWith(`.${this.platform}${extension}`);
}

UrlResolvePlugin.prototype.noMultiplatformFile = function(url) {
let filePath = path.resolve(this.currentDirectory, url);

return !fs.existsSync(filePath);
}

UrlResolvePlugin.prototype.replaceUrlsValue = function(element) {
const extensionStartIndex = element.text.lastIndexOf(".");
const prefix = element.text.slice(0, extensionStartIndex);
const currentExtension = element.text.slice(extensionStartIndex);

element.text = `${prefix}.${this.platform}${currentExtension}`;
}

return UrlResolvePlugin;
})();

module.exports = UrlResolvePlugin;
9 changes: 6 additions & 3 deletions templates/webpack.angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,9 +160,12 @@ function getPlugins(platform, env) {
typeChecking: false
}),

// Resolve .ios.css and .android.css component stylesheets
new nsWebpack.StyleUrlResolvePlugin({platform}),

// // Resolve .ios.css and .android.css component stylesheets, and .ios.html and .android component views
new nsWebpack.UrlResolvePlugin({
platform: platform,
resolveStylesUrls: true,
resolveTemplateUrl: true
}),
];

if (env.uglify) {
Expand Down

0 comments on commit 2ccf55b

Please sign in to comment.