soiz1's picture
Upload 150 files
bee6636 verified
use oxc::{allocator::Allocator, span::Span};
use transform::{
TransformResult, Transformer,
transform::{Transform, TransformLL},
transforms,
};
use crate::RewriterError;
#[derive(PartialEq, Eq)]
enum HtmlRewriteType<'alloc: 'data, 'data> {
AddScramAttr { key: &'data str, val: &'data str },
ReplaceAttr { new: &'alloc str },
ReplaceText { new: &'alloc str },
InsertText { text: &'alloc str },
RemoveText,
}
#[derive(PartialEq, Eq)]
pub struct HtmlRewrite<'alloc: 'data, 'data> {
span: Span,
ty: HtmlRewriteType<'alloc, 'data>,
}
impl<'alloc: 'data, 'data> HtmlRewrite<'alloc, 'data> {
pub fn add_scram_attr(after: Span, key: &'data str, val: &'data str) -> Self {
Self {
span: Span::new(after.end, after.end),
ty: HtmlRewriteType::AddScramAttr { key, val },
}
}
pub fn replace_attr(val: Span, new: &'alloc str) -> Self {
Self {
span: val,
ty: HtmlRewriteType::ReplaceAttr { new },
}
}
pub fn remove_attr(data: &'data str, key: Span, value: Span) -> Self {
let end = if Self::attr_is_quoted(data, value) {
value.end + 1
} else {
value.end
};
Self {
span: Span::new(key.start, end),
ty: HtmlRewriteType::RemoveText,
}
}
pub fn replace(node: Span, text: &'alloc str) -> Self {
Self {
span: node,
ty: HtmlRewriteType::ReplaceText { new: text },
}
}
pub fn insert_text(after: Span, text: &'alloc str) -> Self {
Self {
span: Span::new(after.end, after.end),
ty: HtmlRewriteType::InsertText { text },
}
}
pub fn remove_node(node: Span) -> Self {
Self {
span: node,
ty: HtmlRewriteType::RemoveText,
}
}
fn attr_is_quoted(data: &str, attr: Span) -> bool {
data.get((attr.start - 1) as usize..attr.start as usize)
.is_some_and(|x| x == "\'" || x == "\"")
}
}
impl<'alloc: 'data, 'data> Transform<'data> for HtmlRewrite<'alloc, 'data> {
type ToLowLevelData = &'data str;
fn span(&self) -> Span {
self.span
}
fn into_low_level(self, data: &Self::ToLowLevelData, _offset: i32) -> TransformLL<'data> {
let data = *data;
match self.ty {
HtmlRewriteType::AddScramAttr { key, val } => {
TransformLL::insert(transforms![" scramjet-attr-", key, "=\"", val, "\""])
}
HtmlRewriteType::ReplaceAttr { new } => {
TransformLL::replace(if Self::attr_is_quoted(data, self.span) {
transforms![new]
} else {
transforms!["\"", new, "\""]
})
}
HtmlRewriteType::ReplaceText { new } => TransformLL::replace(transforms![new]),
HtmlRewriteType::InsertText { text } => TransformLL::insert(transforms![text]),
HtmlRewriteType::RemoveText => TransformLL::replace(transforms![]),
}
}
}
impl PartialOrd for HtmlRewrite<'_, '_> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for HtmlRewrite<'_, '_> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.span.start.cmp(&other.span.start)
}
}
pub(crate) struct HtmlChanges<'alloc: 'data, 'data> {
inner: Transformer<'alloc, 'data, HtmlRewrite<'alloc, 'data>>,
}
impl<'alloc: 'data, 'data> HtmlChanges<'alloc, 'data> {
#[inline]
pub fn new() -> Self {
Self {
inner: Transformer::new(),
}
}
#[inline]
pub fn add(&mut self, rewrite: HtmlRewrite<'alloc, 'data>) {
self.inner.add(std::iter::once(rewrite));
}
#[inline]
pub fn set_alloc(&mut self, alloc: &'alloc Allocator) -> Result<(), RewriterError> {
Ok(self.inner.set_alloc(alloc)?)
}
#[inline]
pub fn take_alloc(&mut self) -> Result<(), RewriterError> {
Ok(self.inner.take_alloc()?)
}
#[inline]
pub fn empty(&self) -> bool {
self.inner.empty()
}
#[inline]
pub fn perform(&mut self, html: &'data str) -> Result<TransformResult<'alloc>, RewriterError> {
Ok(self.inner.perform(html, &html, false)?)
}
}