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

Commit be12c23

Browse files
authored
feat: add plugin to support android/ios styleUrls (#47)
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 be12c23

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

Diff for: index.js

+2
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) {

Diff for: resource-resolver-plugins/StyleUrlResolvePlugin.js

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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+
.forEach(sf => this.usePlatformStyleUrl(sf));
19+
20+
callback();
21+
})
22+
};
23+
24+
function getAotPlugin(compilation) {
25+
let maybeAotPlugin = compilation._ngToolsWebpackPluginInstance;
26+
if (!maybeAotPlugin) {
27+
throw new Error(`This plugin must be used with the AotPlugin!`);
28+
}
29+
30+
return maybeAotPlugin;
31+
}
32+
33+
StyleUrlResolvePlugin.prototype.usePlatformStyleUrl = function(sourceFile) {
34+
this.setCurrentDirectory(sourceFile);
35+
ts.forEachChild(sourceFile, node => this.traverseDecorators(node));
36+
}
37+
38+
StyleUrlResolvePlugin.prototype.setCurrentDirectory = function(sourceFile) {
39+
this.currentDirectory = path.resolve(sourceFile.path, "..");
40+
}
41+
42+
StyleUrlResolvePlugin.prototype.traverseDecorators = function(node) {
43+
if (node.kind !== ts.SyntaxKind.ClassDeclaration || !node.decorators) {
44+
return;
45+
}
46+
47+
node.decorators.forEach(decorator => {
48+
this.traverseDecoratorArguments(decorator.expression.arguments);
49+
});
50+
}
51+
52+
StyleUrlResolvePlugin.prototype.traverseDecoratorArguments = function(args) {
53+
args.forEach(arg => this.traverseProperties(arg.properties));
54+
}
55+
56+
StyleUrlResolvePlugin.prototype.traverseProperties = function(properties) {
57+
properties.filter(isStyleUrls)
58+
.forEach(prop => this.traversePropertyElements(prop));
59+
}
60+
61+
function isStyleUrls(property) {
62+
return property.name.text === "styleUrls";
63+
}
64+
65+
StyleUrlResolvePlugin.prototype.traversePropertyElements = function(property) {
66+
property.initializer.elements
67+
.filter(el => this.notPlatformUrl(el.text))
68+
.filter(el => this.noMultiplatformFile(el.text))
69+
.forEach(el => this.replaceStyleUrlsValue(el));
70+
}
71+
72+
StyleUrlResolvePlugin.prototype.notPlatformUrl = function(styleUrl) {
73+
let extensionStartIndex = styleUrl.lastIndexOf(".");
74+
let extension = styleUrl.slice(extensionStartIndex);
75+
76+
return !styleUrl.endsWith(`.${this.platform}${extension}`);
77+
}
78+
79+
StyleUrlResolvePlugin.prototype.noMultiplatformFile = function(styleUrl) {
80+
let stylePath = path.resolve(this.currentDirectory, styleUrl);
81+
82+
return !fs.existsSync(stylePath);
83+
}
84+
85+
StyleUrlResolvePlugin.prototype.replaceStyleUrlsValue = function(element) {
86+
const extensionStartIndex = element.text.lastIndexOf(".");
87+
const prefix = element.text.slice(0, extensionStartIndex);
88+
const currentExtension = element.text.slice(extensionStartIndex);
89+
90+
element.text = `${prefix}.${this.platform}${currentExtension}`;
91+
}
92+
93+
return StyleUrlResolvePlugin;
94+
})();
95+
96+
module.exports = StyleUrlResolvePlugin;

Diff for: webpack.common.js.angular.template

+1
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)