From 6b0c9ae4bde9d2ef212a0e4b790279f030239343 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Wed, 23 Oct 2019 13:42:05 +0300 Subject: [PATCH 1/6] feat: use css2json loader by default --- css2json-loader.js | 17 ++++++++++++----- demo/AngularApp/webpack.config.js | 4 ++-- demo/JavaScriptApp/webpack.config.js | 4 ++-- demo/TypeScriptApp/webpack.config.js | 4 ++-- templates/webpack.angular.js | 4 ++-- templates/webpack.javascript.js | 4 ++-- templates/webpack.typescript.js | 4 ++-- templates/webpack.vue.js | 6 +++--- 8 files changed, 27 insertions(+), 20 deletions(-) diff --git a/css2json-loader.js b/css2json-loader.js index 022d645b..94f4941b 100644 --- a/css2json-loader.js +++ b/css2json-loader.js @@ -1,15 +1,22 @@ const parse = require("tns-core-modules/css").parse; -const nl = "\n"; module.exports = function (content, map) { const ast = parse(content); - const dependencies = getImportsFrom(ast) + + let dependencies = []; + getImportsFrom(ast) .map(mapURI) - .reduce((dependencies, { uri, requireURI }) => - dependencies + `global.registerModule(${uri}, () => require(${requireURI}));${nl}`, ""); + .forEach(({ uri, requireURI }) => { + dependencies.push(`global.registerModule(${uri}, () => require(${requireURI}));`); + + // call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css"; + if (uri !== requireURI) { + dependencies.push(`global.registerModule(${requireURI}, () => require(${requireURI}));`); + } + }); const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v); - this.callback(null, `${dependencies}module.exports = ${str};`, map); + this.callback(null, `${dependencies.join("\n")}module.exports = ${str};`, map); } function getImportsFrom(ast) { diff --git a/demo/AngularApp/webpack.config.js b/demo/AngularApp/webpack.config.js index 04179234..b5c77a72 100644 --- a/demo/AngularApp/webpack.config.js +++ b/demo/AngularApp/webpack.config.js @@ -226,14 +226,14 @@ module.exports = env => { test: /[\/|\\]app\.css$/, use: [ "nativescript-dev-webpack/style-hot-loader", - { loader: "css-loader", options: { url: false } } + "nativescript-dev-webpack/css2json-loader" ] }, { test: /[\/|\\]app\.scss$/, use: [ "nativescript-dev-webpack/style-hot-loader", - { loader: "css-loader", options: { url: false } }, + "nativescript-dev-webpack/css2json-loader", "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/templates/webpack.angular.js b/templates/webpack.angular.js index 593b27d0..b89e998b 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -233,14 +233,14 @@ module.exports = env => { test: /[\/|\\]app\.css$/, use: [ "nativescript-dev-webpack/style-hot-loader", - { loader: "css-loader", options: { url: false } } + "nativescript-dev-webpack/css2json-loader", ] }, { test: /[\/|\\]app\.scss$/, use: [ "nativescript-dev-webpack/style-hot-loader", - { loader: "css-loader", options: { url: false } }, + "nativescript-dev-webpack/css2json-loader", "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..8009009a 100644 --- a/templates/webpack.vue.js +++ b/templates/webpack.vue.js @@ -200,7 +200,7 @@ module.exports = env => { use: [ 'nativescript-dev-webpack/style-hot-loader', 'nativescript-dev-webpack/apply-css-loader.js', - { loader: "css-loader", options: { url: false } }, + 'nativescript-dev-webpack/css2json-loader', ], }, { @@ -208,8 +208,8 @@ module.exports = env => { use: [ 'nativescript-dev-webpack/style-hot-loader', 'nativescript-dev-webpack/apply-css-loader.js', - { loader: "css-loader", options: { url: false } }, - "sass-loader", + 'nativescript-dev-webpack/css2json-loader', + 'sass-loader', ], }, { From 8921120829274994b2761df8e38cf82d82035b1c Mon Sep 17 00:00:00 2001 From: vakrilov Date: Wed, 23 Oct 2019 15:51:07 +0300 Subject: [PATCH 2/6] fix: handle imports like @import url("./xxx.css") --- css2json-loader.js | 23 ++++++++++++++++------- templates/webpack.angular.js | 1 - 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/css2json-loader.js b/css2json-loader.js index 94f4941b..2a1e4462 100644 --- a/css2json-loader.js +++ b/css2json-loader.js @@ -1,4 +1,5 @@ const parse = require("tns-core-modules/css").parse; +const urlPattern = /('|")(.*?)\1/; module.exports = function (content, map) { const ast = parse(content); @@ -7,14 +8,13 @@ module.exports = function (content, map) { getImportsFrom(ast) .map(mapURI) .forEach(({ uri, requireURI }) => { - dependencies.push(`global.registerModule(${uri}, () => require(${requireURI}));`); + dependencies.push(`global.registerModule("${uri}", () => require("${requireURI}"));`); - // call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css"; + // Call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css"; if (uri !== requireURI) { - dependencies.push(`global.registerModule(${requireURI}, () => require(${requireURI}));`); + dependencies.push(`global.registerModule("${requireURI}", () => require("${requireURI}"));`); } }); - const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v); this.callback(null, `${dependencies.join("\n")}module.exports = ${str};`, map); } @@ -25,12 +25,21 @@ function getImportsFrom(ast) { } return ast.stylesheet.rules .filter(rule => rule.type === "import") - .map(importRule => importRule.import.replace(/[\'\"]/gm, "")); + .map(urlFromImportRule); } +/** + * Extracts the url from import rule (ex. `url("./platform.css")`) + */ +function urlFromImportRule(importRule) { + const urlValue = importRule.import; + const urlMatch = urlValue && urlValue.match(urlPattern); + return urlMatch && urlMatch[2]; +}; + function mapURI(uri) { return { - uri: JSON.stringify(uri), - requireURI: JSON.stringify(uri[0] === "~" && uri[1] !== "/" ? uri.substr(1) : uri) + uri: uri, + requireURI: uri[0] === "~" && uri[1] !== "/" ? uri.substr(1) : uri }; } diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index b89e998b..403e63a7 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -228,7 +228,6 @@ 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: [ From 0a3cb31bef04e66169a71f703e2989761bd79d3b Mon Sep 17 00:00:00 2001 From: vakrilov Date: Wed, 23 Oct 2019 18:30:39 +0300 Subject: [PATCH 3/6] test: add tests for css2json-loader --- .gitignore | 3 +++ css2json-loader.js | 45 ------------------------------- css2json-loader.spec.ts | 40 +++++++++++++++++++++++++++ css2json-loader.ts | 60 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 45 deletions(-) delete mode 100644 css2json-loader.js create mode 100644 css2json-loader.spec.ts create mode 100644 css2json-loader.ts 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/css2json-loader.js b/css2json-loader.js deleted file mode 100644 index 2a1e4462..00000000 --- a/css2json-loader.js +++ /dev/null @@ -1,45 +0,0 @@ -const parse = require("tns-core-modules/css").parse; -const urlPattern = /('|")(.*?)\1/; - -module.exports = function (content, map) { - const ast = parse(content); - - let dependencies = []; - getImportsFrom(ast) - .map(mapURI) - .forEach(({ uri, requireURI }) => { - dependencies.push(`global.registerModule("${uri}", () => require("${requireURI}"));`); - - // Call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css"; - if (uri !== requireURI) { - dependencies.push(`global.registerModule("${requireURI}", () => require("${requireURI}"));`); - } - }); - const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v); - this.callback(null, `${dependencies.join("\n")}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(urlFromImportRule); -} - -/** - * Extracts the url from import rule (ex. `url("./platform.css")`) - */ -function urlFromImportRule(importRule) { - const urlValue = importRule.import; - const urlMatch = urlValue && urlValue.match(urlPattern); - return urlMatch && urlMatch[2]; -}; - -function mapURI(uri) { - return { - uri: uri, - requireURI: 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..f1fd658f --- /dev/null +++ b/css2json-loader.spec.ts @@ -0,0 +1,40 @@ +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", () => { + 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); + }) + }) +}); diff --git a/css2json-loader.ts b/css2json-loader.ts new file mode 100644 index 00000000..8c0bb1cf --- /dev/null +++ b/css2json-loader.ts @@ -0,0 +1,60 @@ +import { parse, Rule, SyntaxTree } from "tns-core-modules/css"; +import { loader } from "webpack"; + +interface ImportRule extends Rule { + import: string; +} + +const betweenQuotesPattern = /('|")(.*?)\1/; +const unpackUrlPattern = /url\(([^\)]+)\)/; + +const loader: loader.Loader = function (content: string, map) { + const ast = parse(content, undefined); + + let dependencies = []; + getImportRules(ast) + .map(extractUrlFromRule) + .map(createRequireUri) + .forEach(({ uri, requireURI }) => { + dependencies.push(`global.registerModule("${uri}", () => require("${requireURI}"));`); + + // Call registerModule with requireURI to handle cases like @import "~@nativescript/theme/css/blue.css"; + if (uri !== requireURI) { + dependencies.push(`global.registerModule("${requireURI}", () => require("${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 From 632af4f518d024a614856b5f82dc140926b19fe8 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Thu, 24 Oct 2019 01:23:11 +0300 Subject: [PATCH 4/6] feat: add useForImports option --- css2json-loader.spec.ts | 45 ++++++++++++++++++++++++++++--- css2json-loader.ts | 10 +++++-- demo/AngularApp/webpack.config.js | 10 +++++-- templates/webpack.angular.js | 10 +++++-- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/css2json-loader.spec.ts b/css2json-loader.spec.ts index f1fd658f..76ce79e3 100644 --- a/css2json-loader.spec.ts +++ b/css2json-loader.spec.ts @@ -21,20 +21,59 @@ const someCSS = ` ` describe("css2jsonLoader", () => { - importTestCases.forEach((importTestCase) => { + 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(`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 index 8c0bb1cf..056a51b0 100644 --- a/css2json-loader.ts +++ b/css2json-loader.ts @@ -1,5 +1,6 @@ import { parse, Rule, SyntaxTree } from "tns-core-modules/css"; import { loader } from "webpack"; +import { getOptions } from "loader-utils"; interface ImportRule extends Rule { import: string; @@ -7,8 +8,13 @@ interface ImportRule extends Rule { 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 = []; @@ -16,11 +22,11 @@ const loader: loader.Loader = function (content: string, map) { .map(extractUrlFromRule) .map(createRequireUri) .forEach(({ uri, requireURI }) => { - dependencies.push(`global.registerModule("${uri}", () => require("${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("${requireURI}"));`); + dependencies.push(`global.registerModule("${requireURI}", () => require("${requirePrefix}${requireURI}"));`); } }); const str = JSON.stringify(ast, (k, v) => k === "position" ? undefined : v); diff --git a/demo/AngularApp/webpack.config.js b/demo/AngularApp/webpack.config.js index b5c77a72..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", - "nativescript-dev-webpack/css2json-loader" + { + loader: "nativescript-dev-webpack/css2json-loader", + options: { useForImports: true } + } ] }, { test: /[\/|\\]app\.scss$/, use: [ "nativescript-dev-webpack/style-hot-loader", - "nativescript-dev-webpack/css2json-loader", + { + loader: "nativescript-dev-webpack/css2json-loader", + options: { useForImports: true } + }, "sass-loader" ] }, diff --git a/templates/webpack.angular.js b/templates/webpack.angular.js index 403e63a7..330dd2cb 100644 --- a/templates/webpack.angular.js +++ b/templates/webpack.angular.js @@ -232,14 +232,20 @@ module.exports = env => { test: /[\/|\\]app\.css$/, use: [ "nativescript-dev-webpack/style-hot-loader", - "nativescript-dev-webpack/css2json-loader", + { + loader: "nativescript-dev-webpack/css2json-loader", + options: { useForImports: true } + } ] }, { test: /[\/|\\]app\.scss$/, use: [ "nativescript-dev-webpack/style-hot-loader", - "nativescript-dev-webpack/css2json-loader", + { + loader: "nativescript-dev-webpack/css2json-loader", + options: { useForImports: true } + }, "sass-loader" ] }, From 3305ee4d4893b99d5c11a55d0c96d7de37fcea36 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Fri, 25 Oct 2019 14:55:18 +0300 Subject: [PATCH 5/6] refactor: handle only app.css with css2json for Vue --- templates/webpack.vue.js | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/templates/webpack.vue.js b/templates/webpack.vue.js index 8009009a..e3dfd4c7 100644 --- a/templates/webpack.vue.js +++ b/templates/webpack.vue.js @@ -195,20 +195,43 @@ 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', - 'nativescript-dev-webpack/css2json-loader', + { loader: "css-loader", options: { url: false } }, ], }, { test: /\.scss$/, + exclude: /[\/|\\]app\.scss$/, use: [ 'nativescript-dev-webpack/style-hot-loader', 'nativescript-dev-webpack/apply-css-loader.js', - 'nativescript-dev-webpack/css2json-loader', + { loader: "css-loader", options: { url: false } }, 'sass-loader', ], }, From 1e38358fd4b91923b3b5f08538e3b5f0106f846c Mon Sep 17 00:00:00 2001 From: vakrilov Date: Fri, 25 Oct 2019 17:36:06 +0300 Subject: [PATCH 6/6] refactor: add check for css-loader --- apply-css-loader.js | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) 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 +}