Skip to content
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
13 changes: 13 additions & 0 deletions src/dom_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ pub trait NodeHandleExt {
/// Sets an attribute on the element. Must be an element.
fn set_attribute(&self, name: &QualName, value: StrTendril);

/// Removes an attribute from the element, if present. Must be an element.
fn remove_attribute(&self, name: &QualName);

/// Returns true if the node is an element.
fn is_element(&self) -> bool;

Expand Down Expand Up @@ -225,6 +228,16 @@ impl NodeHandleExt for Handle {
}
}

fn remove_attribute(&self, name: &QualName) {
let mut attrs = match self.data {
NodeData::Element { ref attrs, .. } => attrs.borrow_mut(),
_ => panic!("not an element"),
};
if let Some(i) = attrs.iter().position(|a| &a.name == name) {
attrs.remove(i);
}
}

fn is_element(&self) -> bool {
matches!(&self.data, NodeData::Element { .. })
}
Expand Down
4 changes: 4 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod rcdom_with_line_numbers;
mod represents;
mod self_link;
mod tag_omission;
mod variables;

#[tokio::main]
async fn main() -> io::Result<()> {
Expand Down Expand Up @@ -60,11 +61,13 @@ async fn run_preprocess() -> io::Result<()> {
let mut tag_omission = tag_omission::Processor::new();
let mut interface_index = interface_index::Processor::new();
let mut self_link = self_link::Processor::new();
let mut variables = variables::Processor::new(&parsed);

// We do exactly one pass to identify the changes that need to be made.
dom_utils::scan_dom(&document, &mut |h| {
boilerplate.visit(h);
represents.visit(h);
variables.visit(h);
annotate_attributes.visit(h);
tag_omission.visit(h);
interface_index.visit(h);
Expand All @@ -76,6 +79,7 @@ async fn run_preprocess() -> io::Result<()> {
// conflicts between them.
boilerplate.apply().await?;
represents.apply()?;
variables.apply()?;
annotate_attributes.apply().await?;
tag_omission.apply()?;
interface_index.apply()?;
Expand Down
36 changes: 27 additions & 9 deletions src/rcdom_with_line_numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ use html5ever::{
tendril::StrTendril,
tree_builder::{ElementFlags, NodeOrText, QuirksMode},
};
use markup5ever_rcdom::{Handle, RcDom};
use markup5ever_rcdom::{Handle, Node, RcDom};
use std::borrow::Cow;
use std::cell::Cell;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::io;
use std::rc::Rc;

pub struct RcDomWithLineNumbers {
dom: RcDom,
current_line: Cell<u64>,
node_line_map: RefCell<HashMap<*const Node, u64>>,
}

#[cfg(test)]
Expand Down Expand Up @@ -48,13 +51,21 @@ impl RcDomWithLineNumbers {
Ok(())
}
}

/// Returns the 1-based line number where the element represented by `handle`
/// was created, if known.
pub fn line_number_for(&self, handle: &Handle) -> Option<u64> {
let key = Rc::as_ptr(handle);
self.node_line_map.borrow().get(&key).cloned()
}
}

impl Default for RcDomWithLineNumbers {
fn default() -> Self {
Self {
dom: RcDom::default(),
current_line: Cell::new(1),
node_line_map: RefCell::new(HashMap::new()),
}
}
}
Expand All @@ -81,20 +92,27 @@ impl TreeSink for RcDomWithLineNumbers {
self
}

// Override to record the current line number for each created element handle.
fn create_element(
&self,
name: QualName,
attrs: Vec<Attribute>,
flags: ElementFlags,
) -> Self::Handle {
let h = self.dom.create_element(name, attrs, flags);
let key = Rc::as_ptr(&h);
let line = self.current_line.get();
self.node_line_map.borrow_mut().insert(key, line);
h
}

// Delegate all other methods to RcDom.
delegate! {
to self.dom {
fn get_document(&self) -> Self::Handle;

fn elem_name<'a>(&'a self, target: &'a Self::Handle) -> ExpandedName<'a>;

fn create_element(
&self,
name: QualName,
attrs: Vec<Attribute>,
flags: ElementFlags,
) -> Self::Handle;

fn create_comment(&self, text: StrTendril) -> Self::Handle;

fn create_pi(&self, target: StrTendril, data: StrTendril) -> Self::Handle;
Expand Down
Loading
Loading