Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix "Passing individual values" issue #15

Merged
merged 3 commits into from
Jan 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,29 +168,35 @@ module.exports = {

## <a name="passing-individual-values"></a> Passing individual values

> If you are getting all your `htmlWebpackPlugin` instances generated within a loop, and you want to get indivisual passing values for each `.ejs` template as variables, you can try this. (This method is using webapck loader inline mechanic to load every `ejs` file instead, you can also set html-loader/template-ejs-Loader options for each `.ejs` file.)

`webpack.config.js`

```javascript
const { htmlWebpackPluginTemplateCustomizer } = require('template-ejs-loader')
...
module.exports = {
~~~
...

plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: `!${require.resolve('html-loader')}??ruleSet[1].rules[0].use[0]!${path.resolve(
__dirname,
'../lib/index.js'
)}?${queryString.stringify({
// Use the query as an option to pass to the loader
root: './src/ejs',
data: JSON.stringify({
foo: 'bar',
}),
})}!${path.resolve(__dirname, './src/ejs/index.ejs')}`,
template: htmlWebpackPluginTemplateCustomizer({
htmlLoaderOption:{
... // set individual html-loader option here
},
templateEjsLoaderOption:{
root:'' // set individual template-ejs-loader option here
data:{
foo:'test' // you can have indivisual data injection for each .ejs file, too.
}
},
templatePath:'./src/index.ejs' // ejs template path
}),
}),
]

~~~
...
}
```

Expand Down
39 changes: 38 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { readFileSync } from 'fs'
import { resolve, dirname } from 'path'

import { compile, Options, Data } from 'ejs'
import { LoaderContext } from 'webpack'

Expand Down Expand Up @@ -88,9 +87,47 @@ const resolveRequirePaths = async (context: EjsLoaderContext, content: string) =

return resultContent
}
// Since Node.js had marked the querystring as legacy API in version 14.x, and recommended using URLSearchParams,
// we should migrate from "querystring" to "URLSearchParams" if we want to get URL query string here.
// check this: https://www.linkedin.com/pulse/how-migrate-from-querystring-urlsearchparams-nodejs-vladim%C3%ADr-gorej?trk=articles_directory
const obj2URLQueryString = (config?:{[prop: string]: any })=>{
if(!config)return''
let optionArr:string[][] = []
Object.keys(config).forEach((key)=>{
const optionItem = [key,JSON.stringify(config[key])]
optionArr.push(optionItem)
})
return new URLSearchParams(optionArr).toString()
}

export type htmlWebpackPluginTemplateCustomizerConfig = {
htmlLoaderOption? :{
[key: string]: any
},
templateEjsLoaderOption?: Options & { data?: Data | string }
templatePath?:string
}

export type { SourceMap, AdditionalData }

export function htmlWebpackPluginTemplateCustomizer(config:htmlWebpackPluginTemplateCustomizerConfig){
const htmlLoader = `${require.resolve("html-loader")}` // get html-loader entry path
const templateEjsLoader = `${require.resolve("template-ejs-loader")}` // get template-ejs-loader entry path

let htmlLoaderOption = `${obj2URLQueryString(config.htmlLoaderOption)}` // get html-loader option
let templateEjsLoaderOption = `${obj2URLQueryString(config.templateEjsLoaderOption)}` // get template-ejs-loader option
// Check if option string is empty; (And if it's not, prepend a questionmark '?');
// This usage is about webpack loader inline, you can check the spec here : https://webpack.js.org/concepts/loaders/#inline
if(htmlLoaderOption){
htmlLoaderOption = `?${htmlLoaderOption}`;
}
if(templateEjsLoaderOption){
templateEjsLoaderOption = `?${templateEjsLoaderOption}`;
}
// combile loaders/loader options/templatePath then generate customized template name
return `!${htmlLoader}${htmlLoaderOption}!${templateEjsLoader}${templateEjsLoaderOption}!${config.templatePath}`
}

export default async function ejsLoader(
this: EjsLoaderContext,
content: string,
Expand Down