diff --git a/.gitignore b/.gitignore
index e7cdd7db..fca848e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,6 +34,9 @@ bundle-config-loader.js
xml-namespace-loader.d.ts
xml-namespace-loader.js
+css2json-loader.d.ts
+css2json-loader.js
+
**/*.spec.js*
**/*.spec.d.ts*
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a84f3911..79ec1cc8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,29 @@
+
+# [1.3.0](https://github.com/NativeScript/nativescript-dev-webpack/compare/1.2.1...1.3.0) (2019-10-31)
+
+
+### Bug Fixes
+
+* exclude files from tests folder from built application ([c61f10e](https://github.com/NativeScript/nativescript-dev-webpack/commit/c61f10e))
+* fix dependencies in package.json ([eefd042](https://github.com/NativeScript/nativescript-dev-webpack/commit/eefd042)), closes [/github.com/NativeScript/nativescript-dev-webpack/blob/master/bundle-config-loader.ts#L4](https://github.com//github.com/NativeScript/nativescript-dev-webpack/blob/master/bundle-config-loader.ts/issues/L4) [/github.com/NativeScript/nativescript-dev-webpack/blob/2978b81b5a8100774b2bb4a331ac8637205927b8/package.json#L54](https://github.com//github.com/NativeScript/nativescript-dev-webpack/blob/2978b81b5a8100774b2bb4a331ac8637205927b8/package.json/issues/L54)
+* fix xxd path for local snapshots generation ([f63d493](https://github.com/NativeScript/nativescript-dev-webpack/commit/f63d493))
+* handle correctly webpack compilation errors ([363c4da](https://github.com/NativeScript/nativescript-dev-webpack/commit/363c4da))
+* handle imports like [@import](https://github.com/import) url("./xxx.css") ([8921120](https://github.com/NativeScript/nativescript-dev-webpack/commit/8921120))
+* search for the proper NDK executable on Windows ([f93bb6c](https://github.com/NativeScript/nativescript-dev-webpack/commit/f93bb6c))
+* Unbound namespace error with ios and android ([#1053](https://github.com/NativeScript/nativescript-dev-webpack/issues/1053)) ([6cd6efe](https://github.com/NativeScript/nativescript-dev-webpack/commit/6cd6efe))
+
+
+### Features
+
+* add useForImports option ([632af4f](https://github.com/NativeScript/nativescript-dev-webpack/commit/632af4f))
+* ensure valid CLI version when Windows snapshot is requested ([3a687c0](https://github.com/NativeScript/nativescript-dev-webpack/commit/3a687c0))
+* support [@nativescript](https://github.com/nativescript) scope in host resolver ([efda509](https://github.com/NativeScript/nativescript-dev-webpack/commit/efda509))
+* support useLibs though env.compileSnapshot and calculate the NDK path internally ([5431bd7](https://github.com/NativeScript/nativescript-dev-webpack/commit/5431bd7))
+* support V8 snapshots on Windows ([2e9b753](https://github.com/NativeScript/nativescript-dev-webpack/commit/2e9b753))
+* use css2json loader by default ([6b0c9ae](https://github.com/NativeScript/nativescript-dev-webpack/commit/6b0c9ae))
+
+
+
## [1.2.1](https://github.com/NativeScript/nativescript-dev-webpack/compare/1.2.0...1.2.1) (2019-10-03)
diff --git a/apply-css-loader.js b/apply-css-loader.js
index a543e525..41e0f674 100644
--- a/apply-css-loader.js
+++ b/apply-css-loader.js
@@ -1,18 +1,43 @@
+const cssLoaderWarning = "The apply-css-loader expects the file to be pre-processed by css-loader. It might not work properly. Please check your webpack configuration";
+
+function checkForCssLoader(loaders, loaderIndex) {
+ if (!loaders) {
+ return false;
+ }
+
+ for (var i = loaderIndex + 1; i < loaders.length; i++) {
+ const loader = loaders[i];
+ if (loader.path && loader.path.indexOf("css-loader") > 0) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
module.exports = function (content, map) {
if (this.request.match(/\/app\.(css|scss|less|sass)$/)) {
return content;
}
+
+ // Emit a warning if the file was not processed by the css-loader.
+ if (!checkForCssLoader(this.loaders, this.loaderIndex)) {
+ this.emitWarning(new Error(cssLoaderWarning));
+ }
+
content += `
const application = require("tns-core-modules/application");
require("tns-core-modules/ui/styling/style-scope");
- exports.forEach(cssExport => {
- if (cssExport.length > 1 && cssExport[1]) {
- // applying the second item of the export as it contains the css contents
- application.addCss(cssExport[1]);
- }
- });
- `;
+ if (typeof exports.forEach === "function") {
+ exports.forEach(cssExport => {
+ if (cssExport.length > 1 && cssExport[1]) {
+ // applying the second item of the export as it contains the css contents
+ application.addCss(cssExport[1]);
+ }
+ });
+ }
+`;
this.callback(null, content, map);
-}
\ No newline at end of file
+}
diff --git a/css2json-loader.js b/css2json-loader.js
deleted file mode 100644
index 022d645b..00000000
--- a/css2json-loader.js
+++ /dev/null
@@ -1,29 +0,0 @@
-const parse = require("tns-core-modules/css").parse;
-const nl = "\n";
-
-module.exports = function (content, map) {
- const ast = parse(content);
- const dependencies = getImportsFrom(ast)
- .map(mapURI)
- .reduce((dependencies, { uri, requireURI }) =>
- dependencies + `global.registerModule(${uri}, () => require(${requireURI}));${nl}`, "");
-
- const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v);
- this.callback(null, `${dependencies}module.exports = ${str};`, map);
-}
-
-function getImportsFrom(ast) {
- if (!ast || ast.type !== "stylesheet" || !ast.stylesheet) {
- return [];
- }
- return ast.stylesheet.rules
- .filter(rule => rule.type === "import")
- .map(importRule => importRule.import.replace(/[\'\"]/gm, ""));
-}
-
-function mapURI(uri) {
- return {
- uri: JSON.stringify(uri),
- requireURI: JSON.stringify(uri[0] === "~" && uri[1] !== "/" ? uri.substr(1) : uri)
- };
-}
diff --git a/css2json-loader.spec.ts b/css2json-loader.spec.ts
new file mode 100644
index 00000000..76ce79e3
--- /dev/null
+++ b/css2json-loader.spec.ts
@@ -0,0 +1,79 @@
+import css2jsonLoader from "./css2json-loader";
+
+const importTestCases = [
+ `@import url("custom.css");`,
+ `@import url('custom.css');`,
+ `@import url('custom.css') print;`,
+ `@import url("custom.css") print;`,
+ `@import url('custom.css') screen and (orientation:landscape);`,
+ `@import url("custom.css") screen and (orientation:landscape);`,
+ `@import 'custom.css';`,
+ `@import "custom.css";`,
+ `@import 'custom.css' screen;`,
+ `@import "custom.css" screen;`,
+ `@import url(custom.css);`,
+]
+
+const someCSS = `
+.btn {
+ background-color: #7f9
+}
+`
+
+describe("css2jsonLoader", () => {
+ it("converts CSS to JSON", (done) => {
+ const loaderContext = {
+ callback: (error, source: string, map) => {
+ expect(source).toContain(`{"type":"declaration","property":"background-color","value":"#7f9"}`);
+
+ done();
+ }
+ }
+
+ css2jsonLoader.call(loaderContext, someCSS);
+ })
+
+ importTestCases.forEach((importTestCase) => {
+ it(`handles: ${importTestCase}`, (done) => {
+
+ const loaderContext = {
+ callback: (error, source: string, map) => {
+ expect(source).toContain(`global.registerModule("custom.css", () => require("custom.css"))`);
+ expect(source).toContain(`{"type":"declaration","property":"background-color","value":"#7f9"}`);
+
+ done();
+ },
+ }
+
+ css2jsonLoader.call(loaderContext, importTestCase + someCSS);
+ })
+ });
+
+ it("inlines css2json loader in imports if option is provided", (done) => {
+ const loaderContext = {
+ callback: (error, source: string, map) => {
+ expect(source).toContain(`global.registerModule("custom.css", () => require("!nativescript-dev-webpack/css2json-loader?useForImports!custom.css"))`);
+ expect(source).toContain(`{"type":"declaration","property":"background-color","value":"#7f9"}`);
+
+ done();
+ },
+ query: { useForImports: true }
+ }
+
+ css2jsonLoader.call(loaderContext, `@import url("custom.css");` + someCSS);
+ })
+
+ it("registers modules for paths starting with ~", (done) => {
+ const loaderContext = {
+ callback: (error, source: string, map) => {
+ expect(source).toContain(`global.registerModule("~custom.css", () => require("custom.css"))`);
+ expect(source).toContain(`global.registerModule("custom.css", () => require("custom.css"))`);
+ expect(source).toContain(`{"type":"declaration","property":"background-color","value":"#7f9"}`);
+
+ done();
+ }
+ }
+
+ css2jsonLoader.call(loaderContext, `@import url("~custom.css");` + someCSS);
+ })
+});
diff --git a/css2json-loader.ts b/css2json-loader.ts
new file mode 100644
index 00000000..056a51b0
--- /dev/null
+++ b/css2json-loader.ts
@@ -0,0 +1,66 @@
+import { parse, Rule, SyntaxTree } from "tns-core-modules/css";
+import { loader } from "webpack";
+import { getOptions } from "loader-utils";
+
+interface ImportRule extends Rule {
+ import: string;
+}
+
+const betweenQuotesPattern = /('|")(.*?)\1/;
+const unpackUrlPattern = /url\(([^\)]+)\)/;
+const inlineLoader = "!nativescript-dev-webpack/css2json-loader?useForImports!"
+
+const loader: loader.Loader = function (content: string, map) {
+ const options = getOptions(this) || {};
+ const inline = !!options.useForImports;
+ const requirePrefix = inline ? inlineLoader : "";
+
+ const ast = parse(content, undefined);
+
+ let dependencies = [];
+ getImportRules(ast)
+ .map(extractUrlFromRule)
+ .map(createRequireUri)
+ .forEach(({ uri, requireURI }) => {
+ dependencies.push(`global.registerModule("${uri}", () => require("${requirePrefix}${requireURI}"));`);
+
+ // Call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css";
+ if (uri !== requireURI) {
+ dependencies.push(`global.registerModule("${requireURI}", () => require("${requirePrefix}${requireURI}"));`);
+ }
+ });
+ const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v);
+ this.callback(null, `${dependencies.join("\n")}module.exports = ${str};`, map);
+}
+
+function getImportRules(ast: SyntaxTree): ImportRule[] {
+ if (!ast || (ast).type !== "stylesheet" || !ast.stylesheet) {
+ return [];
+ }
+ return ast.stylesheet.rules
+ .filter(rule => rule.type === "import" && (rule).import)
+}
+
+/**
+ * Extracts the url from import rule (ex. `url("./platform.css")`)
+ */
+function extractUrlFromRule(importRule: ImportRule): string {
+ const urlValue = importRule.import;
+
+ const unpackedUrlMatch = urlValue.match(unpackUrlPattern);
+ const unpackedValue = unpackedUrlMatch ? unpackedUrlMatch[1] : urlValue
+
+ const quotesMatch = unpackedValue.match(betweenQuotesPattern);
+ return quotesMatch ? quotesMatch[2] : unpackedValue;
+};
+
+function createRequireUri(uri): { uri: string, requireURI: string } {
+ return {
+ uri: uri,
+ requireURI: uri[0] === "~" && uri[1] !== "/" ? uri.substr(1) : uri
+ };
+}
+
+
+
+export default loader;
\ No newline at end of file
diff --git a/demo/AngularApp/webpack.config.js b/demo/AngularApp/webpack.config.js
index 04179234..28f2fbd2 100644
--- a/demo/AngularApp/webpack.config.js
+++ b/demo/AngularApp/webpack.config.js
@@ -226,14 +226,20 @@ module.exports = env => {
test: /[\/|\\]app\.css$/,
use: [
"nativescript-dev-webpack/style-hot-loader",
- { loader: "css-loader", options: { url: false } }
+ {
+ loader: "nativescript-dev-webpack/css2json-loader",
+ options: { useForImports: true }
+ }
]
},
{
test: /[\/|\\]app\.scss$/,
use: [
"nativescript-dev-webpack/style-hot-loader",
- { loader: "css-loader", options: { url: false } },
+ {
+ loader: "nativescript-dev-webpack/css2json-loader",
+ options: { useForImports: true }
+ },
"sass-loader"
]
},
diff --git a/demo/JavaScriptApp/webpack.config.js b/demo/JavaScriptApp/webpack.config.js
index c4684e61..b889ef6f 100644
--- a/demo/JavaScriptApp/webpack.config.js
+++ b/demo/JavaScriptApp/webpack.config.js
@@ -188,13 +188,13 @@ module.exports = env => {
{
test: /\.css$/,
- use: { loader: "css-loader", options: { url: false } }
+ use: "nativescript-dev-webpack/css2json-loader"
},
{
test: /\.scss$/,
use: [
- { loader: "css-loader", options: { url: false } },
+ "nativescript-dev-webpack/css2json-loader",
"sass-loader"
]
},
diff --git a/demo/TypeScriptApp/webpack.config.js b/demo/TypeScriptApp/webpack.config.js
index 2418be9d..df0542e0 100644
--- a/demo/TypeScriptApp/webpack.config.js
+++ b/demo/TypeScriptApp/webpack.config.js
@@ -194,13 +194,13 @@ module.exports = env => {
{
test: /\.css$/,
- use: { loader: "css-loader", options: { url: false } }
+ use: "nativescript-dev-webpack/css2json-loader"
},
{
test: /\.scss$/,
use: [
- { loader: "css-loader", options: { url: false } },
+ "nativescript-dev-webpack/css2json-loader",
"sass-loader"
]
},
diff --git a/snapshot/android/snapshot-generator.js b/snapshot/android/snapshot-generator.js
index dac5e4cf..c7481f2e 100644
--- a/snapshot/android/snapshot-generator.js
+++ b/snapshot/android/snapshot-generator.js
@@ -2,6 +2,7 @@ const fs = require("fs");
const { dirname, relative, join, EOL } = require("path");
const child_process = require("child_process");
const { convertToUnixPath, warn } = require("../../lib/utils");
+const { isWindows } = require("./utils");
const PropertiesReader = require('properties-reader');
const shelljs = require("shelljs");
@@ -209,7 +210,7 @@ SnapshotGenerator.prototype.buildSnapshotLibs = function (androidNdkPath, recomm
}
SnapshotGenerator.prototype.getAndroidNdkBuildPath = function (androidNdkPath, recommendedAndroidNdkRevision) {
- const ndkBuildExecutableName = "ndk-build";
+ const ndkBuildExecutableName = isWindows() ? "ndk-build.cmd" : "ndk-build";
let hasNdk = false;
// fallback for Android Runtime < 6.2.0 with the 6.1.0 value
recommendedAndroidNdkRevision = recommendedAndroidNdkRevision || "20.0.5594570";
diff --git a/snapshot/android/utils.js b/snapshot/android/utils.js
index aef7157b..947f0302 100644
--- a/snapshot/android/utils.js
+++ b/snapshot/android/utils.js
@@ -60,6 +60,10 @@ function isMacOSCatalinaOrHigher() {
return isCatalinaOrHigher;
}
+function isWindows() {
+ return getHostOS() === CONSTANTS.WIN_OS_NAME;
+}
+
const downloadFile = (url, destinationFilePath, timeout) =>
new Promise((resolve, reject) => {
getRequestOptions(url, timeout)
@@ -119,5 +123,6 @@ module.exports = {
isMacOSCatalinaOrHigher,
downloadFile,
getJsonFile,
- isSubPath
+ isSubPath,
+ isWindows
};
diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js
index 593b27d0..330dd2cb 100644
--- a/templates/webpack.angular.js
+++ b/templates/webpack.angular.js
@@ -228,19 +228,24 @@ module.exports = env => {
{ test: /\.html$|\.xml$/, use: "raw-loader" },
- // tns-core-modules reads the app.css and its imports using css-loader
{
test: /[\/|\\]app\.css$/,
use: [
"nativescript-dev-webpack/style-hot-loader",
- { loader: "css-loader", options: { url: false } }
+ {
+ loader: "nativescript-dev-webpack/css2json-loader",
+ options: { useForImports: true }
+ }
]
},
{
test: /[\/|\\]app\.scss$/,
use: [
"nativescript-dev-webpack/style-hot-loader",
- { loader: "css-loader", options: { url: false } },
+ {
+ loader: "nativescript-dev-webpack/css2json-loader",
+ options: { useForImports: true }
+ },
"sass-loader"
]
},
diff --git a/templates/webpack.javascript.js b/templates/webpack.javascript.js
index 3f669da1..7ab17682 100644
--- a/templates/webpack.javascript.js
+++ b/templates/webpack.javascript.js
@@ -195,13 +195,13 @@ module.exports = env => {
{
test: /\.css$/,
- use: { loader: "css-loader", options: { url: false } }
+ use: "nativescript-dev-webpack/css2json-loader"
},
{
test: /\.scss$/,
use: [
- { loader: "css-loader", options: { url: false } },
+ "nativescript-dev-webpack/css2json-loader",
"sass-loader"
]
},
diff --git a/templates/webpack.typescript.js b/templates/webpack.typescript.js
index 50249817..e11e1117 100644
--- a/templates/webpack.typescript.js
+++ b/templates/webpack.typescript.js
@@ -202,13 +202,13 @@ module.exports = env => {
{
test: /\.css$/,
- use: { loader: "css-loader", options: { url: false } }
+ use: "nativescript-dev-webpack/css2json-loader"
},
{
test: /\.scss$/,
use: [
- { loader: "css-loader", options: { url: false } },
+ "nativescript-dev-webpack/css2json-loader",
"sass-loader"
]
},
diff --git a/templates/webpack.vue.js b/templates/webpack.vue.js
index edb031d4..e3dfd4c7 100644
--- a/templates/webpack.vue.js
+++ b/templates/webpack.vue.js
@@ -195,8 +195,30 @@ module.exports = env => {
},
].filter(loader => Boolean(loader)),
},
+ {
+ test: /[\/|\\]app\.css$/,
+ use: [
+ 'nativescript-dev-webpack/style-hot-loader',
+ {
+ loader: "nativescript-dev-webpack/css2json-loader",
+ options: { useForImports: true }
+ },
+ ],
+ },
+ {
+ test: /[\/|\\]app\.scss$/,
+ use: [
+ 'nativescript-dev-webpack/style-hot-loader',
+ {
+ loader: "nativescript-dev-webpack/css2json-loader",
+ options: { useForImports: true }
+ },
+ 'sass-loader',
+ ],
+ },
{
test: /\.css$/,
+ exclude: /[\/|\\]app\.css$/,
use: [
'nativescript-dev-webpack/style-hot-loader',
'nativescript-dev-webpack/apply-css-loader.js',
@@ -205,11 +227,12 @@ module.exports = env => {
},
{
test: /\.scss$/,
+ exclude: /[\/|\\]app\.scss$/,
use: [
'nativescript-dev-webpack/style-hot-loader',
'nativescript-dev-webpack/apply-css-loader.js',
{ loader: "css-loader", options: { url: false } },
- "sass-loader",
+ 'sass-loader',
],
},
{