From 806411d888a74d41c0199a5424bf120576ff0942 Mon Sep 17 00:00:00 2001 From: cap-Bernardito Date: Mon, 12 Jul 2021 16:54:48 +0300 Subject: [PATCH 1/6] feat: insert option as modulepath --- src/index.js | 50 +++++--- src/utils.js | 28 +++-- test/__snapshots__/insert-option.test.js.snap | 114 ++++++++++++++++++ test/fixtures/insertFn.js | 19 +++ test/insert-option.test.js | 18 +++ 5 files changed, 202 insertions(+), 27 deletions(-) create mode 100644 test/fixtures/insertFn.js diff --git a/src/index.js b/src/index.js index 373986b6..bc19a050 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,5 @@ +import path from "path"; + import { getImportInsertStyleElementCode, getImportGetTargetCode, @@ -26,7 +28,6 @@ loaderAPI.pitch = function loader(request) { typeof options.insert === "string" ? JSON.stringify(options.insert) : '"head"'; - const insertIsFunction = typeof options.insert === "function"; const injectType = options.injectType || "styleTag"; const { styleTagTransform } = options; const esModule = @@ -41,19 +42,30 @@ loaderAPI.pitch = function loader(request) { runtimeOptions.base = options.base; } - const insertFn = insertIsFunction - ? options.insert.toString() - : `function(style){ - var target = getTarget(${insert}); - - if (!target) { - throw new Error( - "Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid." - ); - } + const insertType = + typeof options.insert === "function" + ? "function" + : options.insert && path.isAbsolute(options.insert) + ? "modulePath" + : "selector"; + + let insertFn; + + if (insertType === "function") { + insertFn = options.insert.toString(); + } else if (insertType === "selector") { + insertFn = `function(style){ + var target = getTarget(${insert}); + + if (!target) { + throw new Error( + "Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid." + ); + } - target.appendChild(style); - }`; + target.appendChild(style); + }`; + } const styleTagTransformFn = typeof styleTagTransform === "function" @@ -76,7 +88,7 @@ loaderAPI.pitch = function loader(request) { return ` ${getImportLinkAPICode(esModule, this)} - ${getImportGetTargetCode(esModule, this, insertIsFunction)} + ${getImportGetTargetCode(esModule, this, insertType, options)} ${getImportLinkContentCode(esModule, this, request)} ${ esModule @@ -86,7 +98,7 @@ loaderAPI.pitch = function loader(request) { var options = ${JSON.stringify(runtimeOptions)}; -options.insert = ${insertFn}; +options.insert = ${insertType === "modulePath" ? "insertFn" : insertFn}; var update = API(content, options); @@ -109,7 +121,7 @@ ${esModule ? "export default {}" : ""}`; ${getImportStyleAPICode(esModule, this)} ${getImportStyleDomAPICode(esModule, this, isSingleton, isAuto)} - ${getImportGetTargetCode(esModule, this, insertIsFunction)} + ${getImportGetTargetCode(esModule, this, insertType, options)} ${getSetAttributesCode(esModule, this, options)} ${getImportInsertStyleElementCode(esModule, this)} ${getImportStyleContentCode(esModule, this, request)} @@ -131,7 +143,7 @@ var options = ${JSON.stringify(runtimeOptions)}; ${getStyleTagTransformFn(styleTagTransformFn, isSingleton)}; options.setAttributes = setAttributes; -options.insert = ${insertFn}; +options.insert = ${insertType === "modulePath" ? "insertFn" : insertFn}; options.domAPI = ${getdomAPI(isAuto)}; options.insertStyleElement = insertStyleElement; @@ -168,7 +180,7 @@ ${getExportLazyStyleCode(esModule, this, request)} return ` ${getImportStyleAPICode(esModule, this)} ${getImportStyleDomAPICode(esModule, this, isSingleton, isAuto)} - ${getImportGetTargetCode(esModule, this, insertIsFunction)} + ${getImportGetTargetCode(esModule, this, insertType, options)} ${getSetAttributesCode(esModule, this, options)} ${getImportInsertStyleElementCode(esModule, this)} ${getImportStyleContentCode(esModule, this, request)} @@ -183,7 +195,7 @@ var options = ${JSON.stringify(runtimeOptions)}; ${getStyleTagTransformFn(styleTagTransformFn, isSingleton)}; options.setAttributes = setAttributes; -options.insert = ${insertFn}; +options.insert = ${insertType === "modulePath" ? "insertFn" : insertFn}; options.domAPI = ${getdomAPI(isAuto)}; options.insertStyleElement = insertStyleElement; diff --git a/src/utils.js b/src/utils.js index 6267edb6..8e532fa7 100644 --- a/src/utils.js +++ b/src/utils.js @@ -112,15 +112,27 @@ function getImportStyleContentCode(esModule, loaderContext, request) { : `var content = require(${modulePath});`; } -function getImportGetTargetCode(esModule, loaderContext, insertIsFunction) { - const modulePath = stringifyRequest( - loaderContext, - `!${path.join(__dirname, "runtime/getTarget.js")}` - ); +function getImportGetTargetCode(esModule, loaderContext, insertType, options) { + if (insertType === "selector") { + const modulePath = stringifyRequest( + loaderContext, + `!${path.join(__dirname, "runtime/getTarget.js")}` + ); - return esModule - ? `${!insertIsFunction ? `import getTarget from ${modulePath};` : ""}` - : `${!insertIsFunction ? `var getTarget = require(${modulePath});` : ""}`; + return esModule + ? `import getTarget from ${modulePath};` + : `var getTarget = require(${modulePath});`; + } + + if (insertType === "modulePath") { + const modulePath = stringifyRequest(loaderContext, `!${options.insert}`); + + return esModule + ? `import insertFn from ${modulePath};` + : `var insertFn = require(${modulePath});`; + } + + return ""; } function getImportInsertStyleElementCode(esModule, loaderContext) { diff --git a/test/__snapshots__/insert-option.test.js.snap b/test/__snapshots__/insert-option.test.js.snap index 12c42e44..b2ce4a32 100644 --- a/test/__snapshots__/insert-option.test.js.snap +++ b/test/__snapshots__/insert-option.test.js.snap @@ -342,6 +342,30 @@ exports[`"insert" option should insert styles into "head" bottom when not specif exports[`"insert" option should insert styles into "head" bottom when not specified and when the "injectType" option is "styleTag": warnings 1`] = `Array []`; +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazySingletonStyleTag" and insert is object: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazySingletonStyleTag" and insert is object: errors 1`] = `Array []`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazySingletonStyleTag" and insert is object: warnings 1`] = `Array []`; + exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazySingletonStyleTag": DOM 1`] = ` " + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazyStyleTag" and insert is object: errors 1`] = `Array []`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazyStyleTag" and insert is object: warnings 1`] = `Array []`; + exports[`"insert" option should insert styles into "head" top when the "injectType" option is "lazyStyleTag": DOM 1`] = ` " + + +

Body

+
+ + + +" +`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "linkTag" and insert is object: errors 1`] = `Array []`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "linkTag" and insert is object: warnings 1`] = `Array []`; + exports[`"insert" option should insert styles into "head" top when the "injectType" option is "linkTag": DOM 1`] = ` " style-loader test @@ -408,6 +474,30 @@ exports[`"insert" option should insert styles into "head" top when the "injectTy exports[`"insert" option should insert styles into "head" top when the "injectType" option is "linkTag": warnings 1`] = `Array []`; +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "singletonStyleTag" and insert is object: DOM 1`] = ` +" + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "singletonStyleTag" and insert is object: errors 1`] = `Array []`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "singletonStyleTag" and insert is object: warnings 1`] = `Array []`; + exports[`"insert" option should insert styles into "head" top when the "injectType" option is "singletonStyleTag": DOM 1`] = ` " + style-loader test + + + +

Body

+
+ + + +" +`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "styleTag" and insert is object: errors 1`] = `Array []`; + +exports[`"insert" option should insert styles into "head" top when the "injectType" option is "styleTag" and insert is object: warnings 1`] = `Array []`; + exports[`"insert" option should insert styles into "head" top when the "injectType" option is "styleTag": DOM 1`] = ` "