Skip to content

Commit

Permalink
feat: add boolean type for builtins.html[0].inject (#3771)
Browse files Browse the repository at this point in the history
* feat: add boolean type for builtins.html[0].inject

* refactor

* fix

* fix

---------

Co-authored-by: ahabhgk <[email protected]>
  • Loading branch information
lippzhang and ahabhgk authored Sep 13, 2023
1 parent 80d153f commit 7aa8e47
Show file tree
Hide file tree
Showing 9 changed files with 175 additions and 98 deletions.
6 changes: 3 additions & 3 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -716,12 +716,12 @@ export interface RawHtmlRspackPluginOptions {
template?: string
templateContent?: string
templateParameters?: Record<string, string>
/** `head`, `body` or None */
inject?: "head" | "body"
/** "head", "body" or "false" */
inject: "head" | "body" | "false"
/** path or `auto` */
publicPath?: string
/** `blocking`, `defer`, or `module` */
scriptLoading?: "blocking" | "defer" | "module"
scriptLoading: "blocking" | "defer" | "module"
/** entry_chunk_name (only entry chunks are supported) */
chunks?: Array<string>
excludedChunks?: Array<string>
Expand Down
21 changes: 7 additions & 14 deletions crates/rspack_binding_options/src/options/raw_builtins/raw_html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ pub struct RawHtmlRspackPluginOptions {
pub template: Option<String>,
pub template_content: Option<String>,
pub template_parameters: Option<HashMap<String, String>>,
/// `head`, `body` or None
#[napi(ts_type = "\"head\" | \"body\"")]
pub inject: Option<RawHtmlInject>,
/// "head", "body" or "false"
#[napi(ts_type = "\"head\" | \"body\" | \"false\"")]
pub inject: RawHtmlInject,
/// path or `auto`
pub public_path: Option<String>,
/// `blocking`, `defer`, or `module`
#[napi(ts_type = "\"blocking\" | \"defer\" | \"module\"")]
pub script_loading: Option<RawHtmlScriptLoading>,
pub script_loading: RawHtmlScriptLoading,

/// entry_chunk_name (only entry chunks are supported)
pub chunks: Option<Vec<String>>,
Expand All @@ -47,17 +47,10 @@ pub struct RawHtmlRspackPluginOptions {

impl From<RawHtmlRspackPluginOptions> for HtmlRspackPluginOptions {
fn from(value: RawHtmlRspackPluginOptions) -> Self {
let inject = value
.inject
.as_ref()
.map(|s| HtmlInject::from_str(s).unwrap_or_else(|_| panic!("Invalid inject value: {s}")));
let inject = HtmlInject::from_str(&value.inject).expect("Invalid inject value");

let script_loading = HtmlScriptLoading::from_str(
&value
.script_loading
.unwrap_or_else(|| String::from("defer")),
)
.expect("value.script_loading has unwrap_or_else so this will never happen");
let script_loading =
HtmlScriptLoading::from_str(&value.script_loading).expect("Invalid script_loading value");

let sri = value.sri.as_ref().map(|s| {
HtmlSriHashFunction::from_str(s).unwrap_or_else(|_| panic!("Invalid sri value: {s}"))
Expand Down
16 changes: 12 additions & 4 deletions crates/rspack_plugin_html/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::sri::HtmlSriHashFunction;
pub enum HtmlInject {
Head,
Body,
False,
}

impl FromStr for HtmlInject {
Expand All @@ -24,9 +25,11 @@ impl FromStr for HtmlInject {
Ok(HtmlInject::Head)
} else if s.eq("body") {
Ok(HtmlInject::Body)
} else if s.eq("false") {
Ok(HtmlInject::False)
} else {
Err(anyhow::Error::msg(
"inject in html config only support 'head' or 'body'",
"inject in html config only support 'head', 'body', or 'false'",
))
}
}
Expand Down Expand Up @@ -70,8 +73,9 @@ pub struct HtmlRspackPluginOptions {
pub template: Option<String>,
pub template_content: Option<String>,
pub template_parameters: Option<HashMap<String, String>>,
/// `head`, `body` or None
pub inject: Option<HtmlInject>,
/// `head`, `body`, `false`
#[serde(default = "default_inject")]
pub inject: HtmlInject,
/// path or `auto`
pub public_path: Option<String>,
/// `blocking`, `defer`, or `module`
Expand Down Expand Up @@ -100,14 +104,18 @@ fn default_script_loading() -> HtmlScriptLoading {
HtmlScriptLoading::Defer
}

fn default_inject() -> HtmlInject {
HtmlInject::Head
}

impl Default for HtmlRspackPluginOptions {
fn default() -> HtmlRspackPluginOptions {
HtmlRspackPluginOptions {
filename: default_filename(),
template: None,
template_content: None,
template_parameters: None,
inject: None,
inject: default_inject(),
public_path: None,
script_loading: default_script_loading(),
chunks: None,
Expand Down
52 changes: 22 additions & 30 deletions crates/rspack_plugin_html/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,36 +132,28 @@ impl Plugin for HtmlRspackPlugin {
.collect::<Vec<_>>();

let mut tags = vec![];
for (asset_name, asset) in included_assets {
if let Some(extension) = Path::new(&asset_name).extension() {
let asset_uri = format!(
"{}{asset_name}",
config.get_public_path(compilation, &self.config.filename),
);
let mut tag: Option<HTMLPluginTag> = None;
if extension.eq_ignore_ascii_case("css") {
tag = Some(HTMLPluginTag::create_style(
&asset_uri,
Some(if let Some(inject) = &config.inject {
*inject
} else {
HtmlInject::Head
}),
));
} else if extension.eq_ignore_ascii_case("js") || extension.eq_ignore_ascii_case("mjs") {
tag = Some(HTMLPluginTag::create_script(
&asset_uri,
Some(if let Some(inject) = &config.inject {
*inject
} else {
HtmlInject::Head
}),
&config.script_loading,
))
}

if let Some(tag) = tag {
tags.push((tag, asset));
// if inject is 'false', don't do anything
if !matches!(config.inject, HtmlInject::False) {
for (asset_name, asset) in included_assets {
if let Some(extension) = Path::new(&asset_name).extension() {
let asset_uri = format!(
"{}{asset_name}",
config.get_public_path(compilation, &self.config.filename),
);
let mut tag: Option<HTMLPluginTag> = None;
if extension.eq_ignore_ascii_case("css") {
tag = Some(HTMLPluginTag::create_style(&asset_uri, config.inject));
} else if extension.eq_ignore_ascii_case("js") || extension.eq_ignore_ascii_case("mjs") {
tag = Some(HTMLPluginTag::create_script(
&asset_uri,
config.inject,
&config.script_loading,
))
}

if let Some(tag) = tag {
tags.push((tag, asset));
}
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions crates/rspack_plugin_html/src/visitors/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ pub struct HTMLPluginTag {
pub tag_name: String,
pub attributes: Vec<HtmlPluginAttribute>,
pub void_tag: bool,
// `head` or `body`
// `head`, `body`, `false`
pub append_to: HtmlInject,
}

impl HTMLPluginTag {
pub fn create_style(href: &str, append_to: Option<HtmlInject>) -> HTMLPluginTag {
pub fn create_style(href: &str, append_to: HtmlInject) -> HTMLPluginTag {
HTMLPluginTag {
tag_name: "link".to_string(),
append_to: append_to.unwrap_or(HtmlInject::Head),
append_to,
attributes: vec![
HtmlPluginAttribute {
attr_name: "href".to_string(),
Expand All @@ -42,7 +42,7 @@ impl HTMLPluginTag {

pub fn create_script(
src: &str,
append_to: Option<HtmlInject>,
append_to: HtmlInject,
script_loading: &HtmlScriptLoading,
) -> HTMLPluginTag {
let mut attributes = vec![HtmlPluginAttribute {
Expand All @@ -67,7 +67,7 @@ impl HTMLPluginTag {

HTMLPluginTag {
tag_name: "script".to_string(),
append_to: append_to.unwrap_or(HtmlInject::Body),
append_to,
attributes,
void_tag: false,
}
Expand Down Expand Up @@ -107,6 +107,7 @@ impl<'a, 'c> AssetWriter<'a, 'c> {
HtmlInject::Body => {
body_tags.push(ele);
}
_ => (),
}
}
AssetWriter {
Expand Down
16 changes: 14 additions & 2 deletions packages/rspack/src/builtin-plugin/HtmlRspackPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const htmlRspackPluginOptions = z.strictObject({
template: z.string().optional(),
templateContent: z.string().optional(),
templateParameters: z.record(z.string()).optional(),
inject: z.enum(["head", "body"]).optional(),
inject: z.enum(["head", "body"]).or(z.boolean()).optional(),
publicPath: z.string().optional(),
scriptLoading: z.enum(["blocking", "defer", "module"]).optional(),
chunks: z.string().array().optional(),
Expand All @@ -34,9 +34,21 @@ export const HtmlRspackPlugin = create(
};
}
}
const scriptLoading = c.scriptLoading ?? "defer";
const configInject = c.inject ?? true;
const inject =
configInject === true
? scriptLoading === "blocking"
? "body"
: "head"
: configInject === false
? "false"
: configInject;
return {
...c,
meta
meta,
scriptLoading,
inject
};
}
);
40 changes: 40 additions & 0 deletions packages/rspack/tests/configCases/builtins/html-inject/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const fs = require("fs");
const path = require("path");

it("body-index.html inject", () => {
const htmlPath = path.join(__dirname, "./body-index.html");
const htmlContent = fs.readFileSync(htmlPath, "utf-8");
expect(
htmlContent.includes('<script src="main.js" defer></script></body>')
).toBe(true);
});

it("head-index.html inject", () => {
const htmlPath = path.join(__dirname, "./head-index.html");
const htmlContent = fs.readFileSync(htmlPath, "utf-8");
expect(
htmlContent.includes('<script src="main.js" defer></script></head>')
).toBe(true);
});

it("true-blocking-index.html inject", () => {
const htmlPath = path.join(__dirname, "./true-blocking-index.html");
const htmlContent = fs.readFileSync(htmlPath, "utf-8");
expect(htmlContent.includes('<script src="main.js"></script></body>')).toBe(
true
);
});

it("true-defer-index.html inject", () => {
const htmlPath = path.join(__dirname, "./true-defer-index.html");
const htmlContent = fs.readFileSync(htmlPath, "utf-8");
expect(
htmlContent.includes('<script src="main.js" defer></script></head>')
).toBe(true);
});

it("false-index.html inject", () => {
const htmlPath = path.join(__dirname, "./false-index.html");
const htmlContent = fs.readFileSync(htmlPath, "utf-8");
expect(htmlContent.includes('<script src="main.js"')).toBe(false);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const { HtmlRspackPlugin } = require("../../../../");

module.exports = [
{
plugins: [
new HtmlRspackPlugin({
filename: "body-index.html",
inject: "body"
})
]
},
{
plugins: [
new HtmlRspackPlugin({
filename: "head-index.html",
inject: "head"
})
]
},
{
plugins: [
new HtmlRspackPlugin({
filename: "true-blocking-index.html",
inject: true,
scriptLoading: "blocking"
})
]
},
{
plugins: [
new HtmlRspackPlugin({
filename: "true-defer-index.html",
inject: true
})
]
},
{
plugins: [
new HtmlRspackPlugin({
filename: "false-index.html",
inject: false
})
]
}
];
Loading

0 comments on commit 7aa8e47

Please sign in to comment.