Skip to content

Commit c063e62

Browse files
committed
Add initial variable processing
This supports the work in whatwg/html#11392 with a new processor found in variables.rs, documented there. This required updating the parser to store line numbers for each element, which changed a lot of test call sites.
1 parent e3d362b commit c063e62

File tree

11 files changed

+516
-78
lines changed

11 files changed

+516
-78
lines changed

src/annotate_attributes.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ mod tests {
311311
// before and after the attributes table, to demonstrate that this is
312312
// not sensitive to which order they occur in (i.e., these could be
313313
// reordered in the HTML spec).
314-
let document = parse_document_async(
314+
let parsed = parse_document_async(
315315
r#"
316316
<!DOCTYPE html>
317317
<h3>The a element</h3>
@@ -333,6 +333,7 @@ mod tests {
333333
<dd><code data-x="attr-area-href">href</code>
334334
</dl>
335335
"#.trim().as_bytes()).await?;
336+
let document = parsed.document().clone();
336337
let mut proc = Processor::new();
337338
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
338339
proc.apply().await?;
@@ -368,7 +369,7 @@ mod tests {
368369
async fn test_variant() -> io::Result<()> {
369370
// This checks that <!-- variant --> and <!-- or: --> work correctly.
370371
// i.e., the variant description is used where requested
371-
let document = parse_document_async(
372+
let parsed = parse_document_async(
372373
r#"
373374
<!DOCTYPE html>
374375
<h3>The a element</h3>
@@ -386,6 +387,7 @@ mod tests {
386387
<dd><code data-x="attr-area-href">href</code><!-- variant -->
387388
</dl>
388389
"#.trim().as_bytes()).await?;
390+
let document = parsed.document().clone();
389391
let mut proc = Processor::new();
390392
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
391393
proc.apply().await?;
@@ -415,7 +417,7 @@ mod tests {
415417
#[tokio::test]
416418
async fn test_special_semantics() -> io::Result<()> {
417419
// Checks that the special rules for using : instead of an em dash work.
418-
let document = parse_document_async(
420+
let parsed = parse_document_async(
419421
r#"
420422
<!DOCTYPE html>
421423
<h3>The a element</h3>
@@ -428,6 +430,7 @@ mod tests {
428430
<tr><th><code data-x>name</code><td><code data-x="attr-a-name">a</code><td>Anchor name
429431
</tbody></table>
430432
"#.trim().as_bytes()).await?;
433+
let document = parsed.document().clone();
431434
let mut proc = Processor::new();
432435
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
433436
proc.apply().await?;
@@ -451,7 +454,7 @@ mod tests {
451454
#[tokio::test]
452455
async fn test_special_semantics_multiple() -> io::Result<()> {
453456
// Checks that the special rules for joining any special semantics with a ; work.
454-
let document = parse_document_async(
457+
let parsed = parse_document_async(
455458
r#"
456459
<!DOCTYPE html>
457460
<h3>The a element</h3>
@@ -465,6 +468,7 @@ mod tests {
465468
<tr><th><code data-x>name</code><td><code data-x="attr-a-name">a</code><td>Name of the anchor
466469
</tbody></table>
467470
"#.trim().as_bytes()).await?;
471+
let document = parsed.document().clone();
468472
let mut proc = Processor::new();
469473
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
470474
proc.apply().await?;
@@ -490,7 +494,7 @@ mod tests {
490494
async fn test_identical_links() -> io::Result<()> {
491495
// This checks the same identifier can be linked multiple times without
492496
// repeating the description.
493-
let document = parse_document_async(
497+
let parsed = parse_document_async(
494498
r#"
495499
<!DOCTYPE html>
496500
<h3>The img element</h3>
@@ -508,6 +512,7 @@ mod tests {
508512
<tr><th><code data-x>width</code><td><code data-x="attr-dim-width">img</code>; <code data-x="attr-dim-width">video</code><td>Horizontal dimension
509513
</tbody></table>
510514
"#.trim().as_bytes()).await?;
515+
let document = parsed.document().clone();
511516
let mut proc = Processor::new();
512517
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
513518
proc.apply().await?;

src/boilerplate.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ mod tests {
166166
"<tr><td>en<td>English",
167167
)
168168
.await?;
169-
let document = parse_document_async(
169+
let parsed = parse_document_async(
170170
"<!DOCTYPE html><table><!--BOILERPLATE languages--></table>".as_bytes(),
171-
)
172-
.await?;
171+
).await?;
172+
let document = parsed.document().clone();
173173
let mut proc = Processor::new(boilerplate_dir.path(), Path::new("."));
174174
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
175175
proc.apply().await?;
@@ -188,10 +188,10 @@ mod tests {
188188
"data:text/html,Hello, world!",
189189
)
190190
.await?;
191-
let document = parse_document_async(
191+
let parsed = parse_document_async(
192192
"<!DOCTYPE html><a href=\"<!--BOILERPLATE data.url-->\">hello</a>".as_bytes(),
193-
)
194-
.await?;
193+
).await?;
194+
let document = parsed.document().clone();
195195
let mut proc = Processor::new(boilerplate_dir.path(), Path::new("."));
196196
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
197197
proc.apply().await?;
@@ -208,9 +208,10 @@ mod tests {
208208
tokio::fs::write(example_dir.path().join("ex1"), "first").await?;
209209
tokio::fs::write(example_dir.path().join("ex2"), "second").await?;
210210
tokio::fs::write(example_dir.path().join("ignored"), "bad").await?;
211-
let document =
211+
let parsed =
212212
parse_document_async("<!DOCTYPE html><pre>EXAMPLE ex1</pre><pre><code class=html>\nEXAMPLE ex2 </code></pre><p>EXAMPLE ignored</p>".as_bytes())
213213
.await?;
214+
let document = parsed.document().clone();
214215
let mut proc = Processor::new(Path::new("."), example_dir.path());
215216
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
216217
proc.apply().await?;
@@ -229,7 +230,8 @@ mod tests {
229230
"<!DOCTYPE html><body><pre>EXAMPLE ../foo</pre>",
230231
];
231232
for example in bad_path_examples {
232-
let document = parse_document_async(example.as_bytes()).await?;
233+
let parsed = parse_document_async(example.as_bytes()).await?;
234+
let document = parsed.document().clone();
233235
let mut proc = Processor::new(Path::new("."), Path::new("."));
234236
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
235237
let result = proc.apply().await;

src/dom_utils.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ pub trait NodeHandleExt {
2828
/// Sets an attribute on the element. Must be an element.
2929
fn set_attribute(&self, name: &QualName, value: StrTendril);
3030

31+
/// Removes an attribute from the element, if present. No-op if not an element.
32+
fn remove_attribute(&self, name: &QualName);
33+
3134
/// Returns true if the node is an element.
3235
fn is_element(&self) -> bool;
3336

@@ -220,6 +223,16 @@ impl NodeHandleExt for Handle {
220223
}
221224
}
222225

226+
fn remove_attribute(&self, name: &QualName) {
227+
let mut attrs = match self.data {
228+
NodeData::Element { ref attrs, .. } => attrs.borrow_mut(),
229+
_ => return,
230+
};
231+
if let Some(i) = attrs.iter().position(|a| &a.name == name) {
232+
attrs.remove(i);
233+
}
234+
}
235+
223236
fn is_element(&self) -> bool {
224237
matches!(&self.data, NodeData::Element { .. })
225238
}

src/interface_index.rs

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ mod tests {
186186

187187
#[tokio::test]
188188
async fn test_two_interfaces_in_one_block() -> io::Result<()> {
189-
let document = parse_document_async(
189+
let parsed = parse_document_async(
190190
r#"
191191
<!DOCTYPE html>
192192
<pre><code class=idl>
@@ -197,8 +197,8 @@ INSERT INTERFACES HERE
197197
"#
198198
.trim()
199199
.as_bytes(),
200-
)
201-
.await?;
200+
).await?;
201+
let document = parsed.document().clone();
202202
let mut proc = Processor::new();
203203
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
204204
proc.apply()?;
@@ -216,7 +216,7 @@ interface <dfn interface="">HTMLBlinkElement</dfn> { ... }
216216

217217
#[tokio::test]
218218
async fn test_two_interfaces_in_separate_blocks() -> io::Result<()> {
219-
let document = parse_document_async(
219+
let parsed = parse_document_async(
220220
r#"
221221
<!DOCTYPE html>
222222
<pre><code class=idl>
@@ -229,8 +229,8 @@ INSERT INTERFACES HERE
229229
"#
230230
.trim()
231231
.as_bytes(),
232-
)
233-
.await?;
232+
).await?;
233+
let document = parsed.document().clone();
234234
let mut proc = Processor::new();
235235
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
236236
proc.apply()?;
@@ -250,7 +250,7 @@ interface <dfn interface="">HTMLBlinkElement</dfn> { ... }
250250

251251
#[tokio::test]
252252
async fn interface_with_partial() -> io::Result<()> {
253-
let document = parse_document_async(
253+
let parsed = parse_document_async(
254254
r#"
255255
<!DOCTYPE html>
256256
<pre><code class=idl>
@@ -263,8 +263,8 @@ INSERT INTERFACES HERE
263263
"#
264264
.trim()
265265
.as_bytes(),
266-
)
267-
.await?;
266+
).await?;
267+
let document = parsed.document().clone();
268268
let mut proc = Processor::new();
269269
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
270270
proc.apply()?;
@@ -284,7 +284,7 @@ partial interface <span id="HTMLMarqueeElement-partial">HTMLMarqueeElement</span
284284

285285
#[tokio::test]
286286
async fn interface_with_two_partials() -> io::Result<()> {
287-
let document = parse_document_async(
287+
let parsed = parse_document_async(
288288
r#"
289289
<!DOCTYPE html>
290290
<pre><code class=idl>
@@ -296,8 +296,8 @@ INSERT INTERFACES HERE
296296
"#
297297
.trim()
298298
.as_bytes(),
299-
)
300-
.await?;
299+
).await?;
300+
let document = parsed.document().clone();
301301
let mut proc = Processor::new();
302302
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
303303
proc.apply()?;
@@ -316,7 +316,7 @@ partial interface <span id="HTMLMarqueeElement-partial-2">HTMLMarqueeElement</sp
316316

317317
#[tokio::test]
318318
async fn only_partials() -> io::Result<()> {
319-
let document = parse_document_async(
319+
let parsed = parse_document_async(
320320
r#"
321321
<!DOCTYPE html>
322322
<pre><code class=idl>
@@ -327,8 +327,8 @@ INSERT INTERFACES HERE
327327
"#
328328
.trim()
329329
.as_bytes(),
330-
)
331-
.await?;
330+
).await?;
331+
let document = parsed.document().clone();
332332
let mut proc = Processor::new();
333333
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
334334
proc.apply()?;
@@ -346,7 +346,7 @@ partial interface <span id="HTMLMarqueeElement-partial-2">HTMLMarqueeElement</sp
346346

347347
#[tokio::test]
348348
async fn marker_before() -> io::Result<()> {
349-
let document = parse_document_async(
349+
let parsed = parse_document_async(
350350
r#"
351351
<!DOCTYPE html>
352352
INSERT INTERFACES HERE
@@ -356,8 +356,8 @@ interface <dfn interface>HTMLMarqueeElement</dfn> { ... }
356356
"#
357357
.trim()
358358
.as_bytes(),
359-
)
360-
.await?;
359+
).await?;
360+
let document = parsed.document().clone();
361361
let mut proc = Processor::new();
362362
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
363363
proc.apply()?;
@@ -376,7 +376,8 @@ interface <dfn interface="">HTMLMarqueeElement</dfn> { ... }
376376

377377
#[tokio::test]
378378
async fn no_marker() -> io::Result<()> {
379-
let document = parse_document_async("<!DOCTYPE html>".as_bytes()).await?;
379+
let parsed = parse_document_async("<!DOCTYPE html>".as_bytes()).await?;
380+
let document = parsed.document().clone();
380381
let mut proc = Processor::new();
381382
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
382383
let result = proc.apply();
@@ -386,11 +387,11 @@ interface <dfn interface="">HTMLMarqueeElement</dfn> { ... }
386387

387388
#[tokio::test]
388389
async fn duplicate_marker() -> io::Result<()> {
389-
let document = parse_document_async(
390+
let parsed = parse_document_async(
390391
"<!DOCTYPE html><div>INSERT INTERFACES HERE</div><div>INSERT INTERFACES HERE</div>"
391392
.as_bytes(),
392-
)
393-
.await?;
393+
).await?;
394+
let document = parsed.document().clone();
394395
let mut proc = Processor::new();
395396
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
396397
let result = proc.apply();
@@ -400,7 +401,7 @@ interface <dfn interface="">HTMLMarqueeElement</dfn> { ... }
400401

401402
#[tokio::test]
402403
async fn duplicate_dfn() -> io::Result<()> {
403-
let document = parse_document_async(
404+
let parsed = parse_document_async(
404405
r#"
405406
<!DOCTYPE html>
406407
<pre><code class=idl>
@@ -409,8 +410,8 @@ interface <dfn interface>HTMLMarqueeElement</dfn> { ... }
409410
</code></pre>
410411
"#
411412
.as_bytes(),
412-
)
413-
.await?;
413+
).await?;
414+
let document = parsed.document().clone();
414415
let mut proc = Processor::new();
415416
dom_utils::scan_dom(&document, &mut |h| proc.visit(h));
416417
let result = proc.apply();

src/main.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod parser;
1717
mod rcdom_with_line_numbers;
1818
mod represents;
1919
mod self_link;
20+
mod variables;
2021
mod tag_omission;
2122

2223
#[tokio::main]
@@ -40,19 +41,22 @@ async fn run() -> io::Result<()> {
4041
// Because parsing can jump around the tree a little, it's most reasonable
4142
// to just parse the whole document before doing any processing. Even for
4243
// the HTML standard, this doesn't take too long.
43-
let document = parser::parse_document_async(tokio::io::stdin()).await?;
44+
let parsed = parser::parse_document_async(tokio::io::stdin()).await?;
45+
let document = parsed.document().clone();
4446

4547
let mut boilerplate = boilerplate::Processor::new(cache_dir.clone(), source_dir.join("demos"));
4648
let mut represents = represents::Processor::new();
4749
let mut annotate_attributes = annotate_attributes::Processor::new();
4850
let mut tag_omission = tag_omission::Processor::new();
4951
let mut interface_index = interface_index::Processor::new();
5052
let mut self_link = self_link::Processor::new();
53+
let mut variables = variables::Processor::new(&parsed);
5154

5255
// We do exactly one pass to identify the changes that need to be made.
5356
dom_utils::scan_dom(&document, &mut |h| {
5457
boilerplate.visit(h);
5558
represents.visit(h);
59+
variables.visit(h);
5660
annotate_attributes.visit(h);
5761
tag_omission.visit(h);
5862
interface_index.visit(h);
@@ -64,6 +68,7 @@ async fn run() -> io::Result<()> {
6468
// conflicts between them.
6569
boilerplate.apply().await?;
6670
represents.apply()?;
71+
variables.apply()?;
6772
annotate_attributes.apply().await?;
6873
tag_omission.apply()?;
6974
interface_index.apply()?;

0 commit comments

Comments
 (0)