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

Commit

Permalink
feat: add plugin to support android/ios styleUrls (#47)
Browse files Browse the repository at this point in the history
When given an url "./style.css" and the resource "style.css" does not
exist in the current directory, the plugin will change the url to
"style.android|ios.css". The target platform should be provided in the
options of the plugin.

Closes #36
  • Loading branch information
sis0k0 committed Jan 5, 2017
1 parent 4553011 commit be12c23
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ var sources = require("webpack-sources");
var fs = require("fs");
var path = require("path");

exports.StyleUrlResolvePlugin = require('./resource-resolver-plugins/StyleUrlResolvePlugin');

//HACK: changes the JSONP chunk eval function to `global["nativescriptJsonp"]`
// applied to tns-java-classes.js only
exports.NativeScriptJsonpPlugin = function(options) {
Expand Down
96 changes: 96 additions & 0 deletions resource-resolver-plugins/StyleUrlResolvePlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const ts = require("typescript");
const fs = require("fs");
const path = require("path");

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

this.platform = options.platform;
}

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

callback();
})
};

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

return maybeAotPlugin;
}

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

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

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

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

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

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

function isStyleUrls(property) {
return property.name.text === "styleUrls";
}

StyleUrlResolvePlugin.prototype.traversePropertyElements = function(property) {
property.initializer.elements
.filter(el => this.notPlatformUrl(el.text))
.filter(el => this.noMultiplatformFile(el.text))
.forEach(el => this.replaceStyleUrlsValue(el));
}

StyleUrlResolvePlugin.prototype.notPlatformUrl = function(styleUrl) {
let extensionStartIndex = styleUrl.lastIndexOf(".");
let extension = styleUrl.slice(extensionStartIndex);

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

StyleUrlResolvePlugin.prototype.noMultiplatformFile = function(styleUrl) {
let stylePath = path.resolve(this.currentDirectory, styleUrl);

return !fs.existsSync(stylePath);
}

StyleUrlResolvePlugin.prototype.replaceStyleUrlsValue = 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 StyleUrlResolvePlugin;
})();

module.exports = StyleUrlResolvePlugin;
1 change: 1 addition & 0 deletions webpack.common.js.angular.template
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ module.exports = function (platform, destinationApp) {
entryModule: path.resolve(__dirname, "app/app.module#AppModule"),
typeChecking: false
}),
new nsWebpack.StyleUrlResolvePlugin({platform}),
];

if (process.env.npm_config_uglify) {
Expand Down

0 comments on commit be12c23

Please sign in to comment.