mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-04-03 10:11:15 +02:00
committed by
GitHub
parent
4c5a30370c
commit
aec5537de0
6
.changes/fix-html-template.md
Normal file
6
.changes/fix-html-template.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"tauri-utils": patch
|
||||
"tauri-codegen": patch
|
||||
---
|
||||
|
||||
Properly serialize HTML template tags.
|
||||
@@ -11,7 +11,9 @@ use sha2::{Digest, Sha256};
|
||||
|
||||
use tauri_utils::assets::AssetKey;
|
||||
use tauri_utils::config::{AppUrl, Config, PatternKind, WindowUrl};
|
||||
use tauri_utils::html::{inject_nonce_token, parse as parse_html};
|
||||
use tauri_utils::html::{
|
||||
inject_nonce_token, parse as parse_html, serialize_node as serialize_html_node,
|
||||
};
|
||||
|
||||
#[cfg(feature = "shell-scope")]
|
||||
use tauri_utils::config::{ShellAllowedArg, ShellAllowedArgs, ShellAllowlistScope};
|
||||
@@ -37,10 +39,10 @@ fn map_core_assets(
|
||||
options.dangerous_disable_asset_csp_modification.clone();
|
||||
move |key, path, input, csp_hashes| {
|
||||
if path.extension() == Some(OsStr::new("html")) {
|
||||
let mut document = parse_html(String::from_utf8_lossy(input).into_owned());
|
||||
|
||||
#[allow(clippy::collapsible_if)]
|
||||
if csp {
|
||||
let mut document = parse_html(String::from_utf8_lossy(input).into_owned());
|
||||
|
||||
if target == Target::Linux {
|
||||
::tauri_utils::html::inject_csp_token(&mut document);
|
||||
}
|
||||
@@ -77,9 +79,9 @@ fn map_core_assets(
|
||||
.push(format!("'sha256-{}'", base64::encode(&hash)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*input = document.to_string().as_bytes().to_vec();
|
||||
*input = serialize_html_node(&document);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -6,9 +6,15 @@
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use html5ever::{interface::QualName, namespace_url, ns, tendril::TendrilSink, LocalName};
|
||||
use html5ever::{
|
||||
interface::QualName,
|
||||
namespace_url, ns,
|
||||
serialize::{HtmlSerializer, SerializeOpts, Serializer, TraversalScope},
|
||||
tendril::TendrilSink,
|
||||
LocalName,
|
||||
};
|
||||
pub use kuchiki::NodeRef;
|
||||
use kuchiki::{Attribute, ExpandedName};
|
||||
use kuchiki::{Attribute, ExpandedName, NodeData};
|
||||
use serde::Serialize;
|
||||
#[cfg(feature = "isolation")]
|
||||
use serialize_to_javascript::DefaultTemplate;
|
||||
@@ -24,6 +30,90 @@ pub const SCRIPT_NONCE_TOKEN: &str = "__TAURI_SCRIPT_NONCE__";
|
||||
/// The token used for style nonces.
|
||||
pub const STYLE_NONCE_TOKEN: &str = "__TAURI_STYLE_NONCE__";
|
||||
|
||||
// taken from https://github.com/kuchiki-rs/kuchiki/blob/57ee6920d835315a498e748ba4b07a851ae5e498/src/serializer.rs#L12
|
||||
fn serialize_node_ref_internal<S: Serializer>(
|
||||
node: &NodeRef,
|
||||
serializer: &mut S,
|
||||
traversal_scope: TraversalScope,
|
||||
) -> crate::Result<()> {
|
||||
match (traversal_scope, node.data()) {
|
||||
(ref scope, &NodeData::Element(ref element)) => {
|
||||
if *scope == TraversalScope::IncludeNode {
|
||||
let attrs = element.attributes.borrow();
|
||||
|
||||
// Unfortunately we need to allocate something to hold these &'a QualName
|
||||
let attrs = attrs
|
||||
.map
|
||||
.iter()
|
||||
.map(|(name, attr)| {
|
||||
(
|
||||
QualName::new(attr.prefix.clone(), name.ns.clone(), name.local.clone()),
|
||||
&attr.value,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
serializer.start_elem(
|
||||
element.name.clone(),
|
||||
attrs.iter().map(|&(ref name, value)| (name, &**value)),
|
||||
)?
|
||||
}
|
||||
|
||||
let children = match element.template_contents.as_ref() {
|
||||
Some(template_root) => template_root.children(),
|
||||
None => node.children(),
|
||||
};
|
||||
for child in children {
|
||||
serialize_node_ref_internal(&child, serializer, TraversalScope::IncludeNode)?
|
||||
}
|
||||
|
||||
if *scope == TraversalScope::IncludeNode {
|
||||
serializer.end_elem(element.name.clone())?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
(_, &NodeData::DocumentFragment) | (_, &NodeData::Document(_)) => {
|
||||
for child in node.children() {
|
||||
serialize_node_ref_internal(&child, serializer, TraversalScope::IncludeNode)?
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
(TraversalScope::ChildrenOnly(_), _) => Ok(()),
|
||||
|
||||
(TraversalScope::IncludeNode, &NodeData::Doctype(ref doctype)) => {
|
||||
serializer.write_doctype(&doctype.name).map_err(Into::into)
|
||||
}
|
||||
(TraversalScope::IncludeNode, &NodeData::Text(ref text)) => {
|
||||
serializer.write_text(&text.borrow()).map_err(Into::into)
|
||||
}
|
||||
(TraversalScope::IncludeNode, &NodeData::Comment(ref text)) => {
|
||||
serializer.write_comment(&text.borrow()).map_err(Into::into)
|
||||
}
|
||||
(TraversalScope::IncludeNode, &NodeData::ProcessingInstruction(ref contents)) => {
|
||||
let contents = contents.borrow();
|
||||
serializer
|
||||
.write_processing_instruction(&contents.0, &contents.1)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes the node to HTML.
|
||||
pub fn serialize_node(node: &NodeRef) -> Vec<u8> {
|
||||
let mut u8_vec = Vec::new();
|
||||
let mut ser = HtmlSerializer::new(
|
||||
&mut u8_vec,
|
||||
SerializeOpts {
|
||||
traversal_scope: TraversalScope::IncludeNode,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
serialize_node_ref_internal(node, &mut ser, TraversalScope::IncludeNode).unwrap();
|
||||
u8_vec
|
||||
}
|
||||
|
||||
/// Parses the given HTML string.
|
||||
pub fn parse(html: String) -> NodeRef {
|
||||
kuchiki::parse_html().one(html)
|
||||
|
||||
Reference in New Issue
Block a user