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

Commit 9c01744

Browse files
committed
feat: add plugin to support android/ios styleUrls
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
1 parent 4553011 commit 9c01744

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ var sources = require("webpack-sources");
22
var fs = require("fs");
33
var path = require("path");
44

5+
exports.StyleUrlResolvePlugin = require('./resource-resolver-plugins/StyleUrlResolvePlugin');
6+
57
//HACK: changes the JSONP chunk eval function to `global["nativescriptJsonp"]`
68
// applied to tns-java-classes.js only
79
exports.NativeScriptJsonpPlugin = function(options) {
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
const ts = require("typescript");
2+
const fs = require("fs");
3+
const path = require("path");
4+
5+
const StyleUrlResolvePlugin = (function() {
6+
function StyleUrlResolvePlugin(options) {
7+
if (!options || !options.platform) {
8+
throw new Error(`Target platform must be specified!`);
9+
}
10+
11+
this.platform = options.platform;
12+
}
13+
14+
StyleUrlResolvePlugin.prototype.apply = function (compiler) {
15+
compiler.plugin("make", (compilation, callback) => {
16+
const aotPlugin = getAotPlugin(compilation);
17+
aotPlugin._program.getSourceFiles()
18+
.map(sf => this.setCurrentDirectory(sf))
19+
.forEach(sf => this.usePlatformStyleUrl(sf));
20+
21+
callback();
22+
})
23+
};
24+
25+
function getAotPlugin(compilation) {
26+
let maybeAotPlugin = compilation._ngToolsWebpackPluginInstance;
27+
if (!maybeAotPlugin) {
28+
throw new Error(`This plugin must be used with the AotPlugin!`);
29+
}
30+
31+
return maybeAotPlugin;
32+
}
33+
34+
StyleUrlResolvePlugin.prototype.usePlatformStyleUrl = function(sourceFile) {
35+
this.setCurrentDirectory(sourceFile);
36+
ts.forEachChild(sourceFile, node => this.traverseDecorators(node));
37+
}
38+
39+
StyleUrlResolvePlugin.prototype.setCurrentDirectory = function(sourceFile) {
40+
this.currentDirectory = path.resolve(sourceFile.path, "..");
41+
42+
return sourceFile;
43+
}
44+
45+
StyleUrlResolvePlugin.prototype.traverseDecorators = function(node) {
46+
if (node.kind !== ts.SyntaxKind.ClassDeclaration || !node.decorators) {
47+
return;
48+
}
49+
50+
node.decorators.forEach(decorator => {
51+
this.traverseDecoratorArguments(decorator.expression.arguments);
52+
});
53+
}
54+
55+
StyleUrlResolvePlugin.prototype.traverseDecoratorArguments = function(args) {
56+
args.forEach(arg => this.traverseProperties(arg.properties));
57+
}
58+
59+
StyleUrlResolvePlugin.prototype.traverseProperties = function(properties) {
60+
properties.filter(isStyleUrls)
61+
.forEach(prop => this.traversePropertyElements(prop));
62+
}
63+
64+
function isStyleUrls(property) {
65+
return property.name.text === "styleUrls";
66+
}
67+
68+
StyleUrlResolvePlugin.prototype.traversePropertyElements = function(property) {
69+
property.initializer.elements
70+
.filter(el => this.notPlatformUrl(el.text))
71+
.filter(el => this.noCommonFile(el.text))
72+
.forEach(el => this.replaceStyleUrlsValue(el));
73+
}
74+
75+
StyleUrlResolvePlugin.prototype.notPlatformUrl = function(styleUrl) {
76+
let extensionStartIndex = styleUrl.lastIndexOf(".");
77+
let extension = styleUrl.slice(extensionStartIndex);
78+
79+
return !styleUrl.endsWith(`.${this.platform}${extension}`);
80+
}
81+
82+
StyleUrlResolvePlugin.prototype.noCommonFile = function(styleUrl) {
83+
let stylePath = path.resolve(this.currentDirectory, styleUrl);
84+
85+
return !fs.existsSync(stylePath);
86+
}
87+
88+
StyleUrlResolvePlugin.prototype.replaceStyleUrlsValue = function(element) {
89+
const extensionStartIndex = element.text.lastIndexOf(".");
90+
const prefix = element.text.slice(0, extensionStartIndex);
91+
const currentExtension = element.text.slice(extensionStartIndex);
92+
93+
element.text = `${prefix}.${this.platform}${currentExtension}`;
94+
}
95+
96+
return StyleUrlResolvePlugin;
97+
})();
98+
99+
module.exports = StyleUrlResolvePlugin;

webpack.common.js.angular.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module.exports = function (platform, destinationApp) {
5151
entryModule: path.resolve(__dirname, "app/app.module#AppModule"),
5252
typeChecking: false
5353
}),
54+
new nsWebpack.StyleUrlResolvePlugin({platform}),
5455
];
5556

5657
if (process.env.npm_config_uglify) {

0 commit comments

Comments
 (0)