Skip to content

Commit 46c38de

Browse files
authored
Merge pull request #679 from kivikakk/push-pmyomryuyqnw
prevent unexpected post-processing & simplify internal feed.
2 parents 5b2ea58 + d2d0cbb commit 46c38de

File tree

16 files changed

+410
-238
lines changed

16 files changed

+410
-238
lines changed

fuzz/fuzz_targets/all_options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ struct FuzzParseOptions {
122122
leave_footnote_definitions: bool,
123123
default_info_string: bool,
124124
broken_link_callback: bool,
125+
escaped_char_spans: bool,
125126
}
126127

127128
impl FuzzParseOptions {
@@ -146,6 +147,7 @@ impl FuzzParseOptions {
146147
} else {
147148
None
148149
},
150+
escaped_char_spans: self.escaped_char_spans,
149151
}
150152
}
151153
}

src/arena_tree.rs

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//! If you need mutability in the node’s `data`,
1313
//! make it a cell (`Cell` or `RefCell`) or use cells inside of it.
1414
15-
use std::cell::Cell;
15+
use std::cell::{BorrowError, Cell, Ref, RefCell, RefMut};
1616
use std::fmt;
1717

1818
/// A node inside a DOM-like tree.
@@ -29,12 +29,12 @@ pub struct Node<'a, T: 'a> {
2929

3030
/// A simple Debug implementation that prints the children as a tree, without
3131
/// looping through the various interior pointer cycles.
32-
impl<'a, T: 'a> fmt::Debug for Node<'a, T>
32+
impl<'a, T: 'a> fmt::Debug for Node<'a, RefCell<T>>
3333
where
3434
T: fmt::Debug,
3535
{
3636
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
37-
struct Children<'a, T>(Option<&'a Node<'a, T>>);
37+
struct Children<'a, T>(Option<&'a Node<'a, RefCell<T>>>);
3838
impl<T: fmt::Debug> fmt::Debug for Children<'_, T> {
3939
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
4040
f.debug_list()
@@ -45,11 +45,14 @@ where
4545
}
4646
}
4747

48-
let mut struct_fmt = f.debug_struct("Node");
49-
struct_fmt.field("data", &self.data);
50-
struct_fmt.field("children", &Children(self.first_child.get()));
51-
struct_fmt.finish()?;
52-
48+
if let Ok(data) = self.data.try_borrow() {
49+
write!(f, "{data:?}")?;
50+
} else {
51+
write!(f, "!!mutably borrowed!!")?;
52+
}
53+
if let Some(first_child) = self.first_child.get() {
54+
write!(f, " {:?}", &Children(Some(first_child)))?;
55+
}
5356
Ok(())
5457
}
5558
}
@@ -259,9 +262,17 @@ impl<'a, T> Node<'a, T> {
259262
macro_rules! axis_iterator {
260263
(#[$attr:meta] $name:ident : $next:ident) => {
261264
#[$attr]
262-
#[derive(Debug)]
263265
pub struct $name<'a, T: 'a>(Option<&'a Node<'a, T>>);
264266

267+
impl<'a, T: 'a> fmt::Debug for $name<'a, RefCell<T>>
268+
where
269+
T: fmt::Debug,
270+
{
271+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272+
f.debug_tuple(stringify!($name)).field(&self.0).finish()
273+
}
274+
}
275+
265276
impl<'a, T> Iterator for $name<'a, T> {
266277
type Item = &'a Node<'a, T>;
267278

@@ -304,9 +315,17 @@ axis_iterator! {
304315
}
305316

306317
/// An iterator of references to a given node and its descendants, in tree order.
307-
#[derive(Debug)]
308318
pub struct Descendants<'a, T: 'a>(Traverse<'a, T>);
309319

320+
impl<'a, T: 'a> fmt::Debug for Descendants<'a, RefCell<T>>
321+
where
322+
T: fmt::Debug,
323+
{
324+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
325+
f.debug_tuple("Descendants").field(&self.0).finish()
326+
}
327+
}
328+
310329
impl<'a, T> Iterator for Descendants<'a, T> {
311330
type Item = &'a Node<'a, T>;
312331

@@ -338,12 +357,23 @@ pub enum NodeEdge<T> {
338357
macro_rules! traverse_iterator {
339358
(#[$attr:meta] $name:ident : $first_child:ident, $next_sibling:ident) => {
340359
#[$attr]
341-
#[derive(Debug)]
342360
pub struct $name<'a, T: 'a> {
343361
root: &'a Node<'a, T>,
344362
next: Option<NodeEdge<&'a Node<'a, T>>>,
345363
}
346364

365+
impl<'a, T: 'a> fmt::Debug for $name<'a, RefCell<T>>
366+
where
367+
T: fmt::Debug,
368+
{
369+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370+
f.debug_struct(stringify!($name))
371+
.field("root", &self.root)
372+
.field("next", &self.next)
373+
.finish()
374+
}
375+
}
376+
347377
impl<'a, T> Iterator for $name<'a, T> {
348378
type Item = NodeEdge<&'a Node<'a, T>>;
349379

@@ -434,19 +464,19 @@ fn it_works() {
434464
assert_eq!(drop_counter.get(), 10);
435465
}
436466

437-
impl<'a, T> Node<'a, std::cell::RefCell<T>> {
467+
impl<'a, T> Node<'a, RefCell<T>> {
438468
/// Shorthand for `node.data.borrow()`.
439-
pub fn data(&self) -> std::cell::Ref<'_, T> {
469+
pub fn data(&self) -> Ref<'_, T> {
440470
self.data.borrow()
441471
}
442472

443473
/// Shorthand for `node.data.try_borrow()`.
444-
pub fn try_data(&self) -> Result<std::cell::Ref<'_, T>, std::cell::BorrowError> {
474+
pub fn try_data(&self) -> Result<Ref<'_, T>, BorrowError> {
445475
self.data.try_borrow()
446476
}
447477

448478
/// Shorthand for `node.data.borrow_mut()`.
449-
pub fn data_mut(&self) -> std::cell::RefMut<'_, T> {
479+
pub fn data_mut(&self) -> RefMut<'_, T> {
450480
self.data.borrow_mut()
451481
}
452482
}

src/cm.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ impl<'a, 'o, 'c> CommonMarkFormatter<'a, 'o, 'c> {
143143
let mut it = s.char_indices();
144144

145145
while let Some((mut i, c)) = it.next() {
146-
// for (i, c) in s.char_indices() {
147146
if self.begin_line {
148147
self.output.push_str(&self.prefix);
149148
self.column = self.prefix.len();
@@ -261,7 +260,7 @@ impl<'a, 'o, 'c> CommonMarkFormatter<'a, 'o, 'c> {
261260
} else if ispunct_char(c) {
262261
write!(self.output, "\\{}", c)?;
263262
} else {
264-
write!(self, "&#{};", c as u8)?;
263+
write!(self.output, "&#{};", c as u8)?;
265264
}
266265
self.column += self.output.len() - len_before;
267266
} else {
@@ -516,7 +515,7 @@ impl<'a, 'o, 'c> CommonMarkFormatter<'a, 'o, 'c> {
516515
)?;
517516
let mut current_len = listmarker.len();
518517

519-
while current_len < self.options.render.ol_width {
518+
while current_len < self.options.render.ol_width.min(12) {
520519
write!(listmarker, " ").unwrap();
521520
current_len += 1;
522521
}

src/nodes.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,12 @@ pub enum NodeValue {
203203

204204
/// **Inline**. A character that has been [escaped](https://github.github.com/gfm/#backslash-escapes)
205205
///
206-
/// Enabled with [`escaped_char_spans`](crate::options::RenderBuilder::escaped_char_spans).
206+
/// Included in the document tree only if the `escaped_char_spans` [parse
207+
/// option](crate::options::ParseBuilder::escaped_char_spans) and/or [render
208+
/// option](crate::options::RenderBuilder::escaped_char_spans) is enabled.
209+
///
210+
/// If the render option is enabled, these are wrapped in distinct `<span>`
211+
/// tags in output HTML and XML.
207212
Escaped,
208213

209214
/// **Inline**. A wikilink to some URL.
@@ -675,7 +680,7 @@ impl NodeValue {
675680
///
676681
/// The struct contains metadata about the node's position in the original document, and the core
677682
/// enum, `NodeValue`.
678-
#[derive(Debug, Clone, PartialEq, Eq)]
683+
#[derive(Clone, PartialEq, Eq)]
679684
pub struct Ast {
680685
/// The node value itself.
681686
pub value: NodeValue,
@@ -690,6 +695,12 @@ pub struct Ast {
690695
pub(crate) line_offsets: Vec<usize>,
691696
}
692697

698+
impl std::fmt::Debug for Ast {
699+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
700+
write!(f, "<{:?} ({})>", self.value, self.sourcepos)
701+
}
702+
}
703+
693704
#[allow(dead_code)]
694705
#[cfg(target_pointer_width = "64")]
695706
/// Assert the size of Ast is 128 bytes. It's pretty big; let's stop it getting
@@ -706,14 +717,20 @@ const AST_SIZE_ASSERTION: [u8; 128] = [0; std::mem::size_of::<Ast>()];
706717
const AST_NODE_SIZE_ASSERTION: [u8; 176] = [0; std::mem::size_of::<AstNode<'_>>()];
707718

708719
/// Represents the position in the source Markdown this node was rendered from.
709-
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
720+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
710721
pub struct Sourcepos {
711722
/// The line and column of the first character of this node.
712723
pub start: LineColumn,
713724
/// The line and column of the last character of this node.
714725
pub end: LineColumn,
715726
}
716727

728+
impl std::fmt::Debug for Sourcepos {
729+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
730+
std::fmt::Display::fmt(self, f)
731+
}
732+
}
733+
717734
impl std::fmt::Display for Sourcepos {
718735
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
719736
write!(

src/parser/inlines.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -358,12 +358,14 @@ impl<'a, 'r, 'o, 'd, 'c, 'p> Subject<'a, 'r, 'o, 'd, 'c, 'p> {
358358

359359
fn handle_newline(&mut self) -> Node<'a> {
360360
let nlpos = self.scanner.pos;
361-
if self.input.as_bytes()[self.scanner.pos] == b'\r' {
361+
if self.peek_byte() == Some(b'\r') {
362362
self.scanner.pos += 1;
363363
}
364-
if self.input.as_bytes()[self.scanner.pos] == b'\n' {
364+
if self.peek_byte() == Some(b'\n') {
365365
self.scanner.pos += 1;
366366
}
367+
assert_ne!(nlpos, self.scanner.pos);
368+
367369
let inl = if nlpos > 1
368370
&& self.input.as_bytes()[nlpos - 1] == b' '
369371
&& self.input.as_bytes()[nlpos - 2] == b' '
@@ -429,17 +431,13 @@ impl<'a, 'r, 'o, 'd, 'c, 'p> Subject<'a, 'r, 'o, 'd, 'c, 'p> {
429431
self.scanner.pos - 1,
430432
);
431433

432-
if self.options.render.escaped_char_spans {
433-
inl = self.make_inline(
434-
NodeValue::Escaped,
435-
self.scanner.pos - 2,
436-
self.scanner.pos - 1,
437-
);
438-
inl.append(inline_text);
439-
inl
440-
} else {
441-
inline_text
442-
}
434+
inl = self.make_inline(
435+
NodeValue::Escaped,
436+
self.scanner.pos - 2,
437+
self.scanner.pos - 1,
438+
);
439+
inl.append(inline_text);
440+
inl
443441
} else if !self.eof() && self.skip_line_end() {
444442
let inl = self.make_inline(NodeValue::LineBreak, startpos, self.scanner.pos - 1);
445443
self.line += 1;
@@ -1016,10 +1014,22 @@ impl<'a, 'r, 'o, 'd, 'c, 'p> Subject<'a, 'r, 'o, 'd, 'c, 'p> {
10161014
);
10171015
// Build line_offsets by scanning for newlines in the content
10181016
para_ast.line_offsets = vec![0];
1019-
for (i, &byte) in content.as_bytes().iter().enumerate() {
1020-
if byte == b'\n' {
1021-
para_ast.line_offsets.push(i + 1);
1017+
1018+
let mut i = 0;
1019+
let bytes = content.as_bytes();
1020+
let len = content.len();
1021+
while i < len {
1022+
match bytes[i] {
1023+
b'\r' if i + 1 < len && bytes[i + 1] == b'\n' => {
1024+
i += 1;
1025+
para_ast.line_offsets.push(i + 1);
1026+
}
1027+
b'\n' | b'\r' => {
1028+
para_ast.line_offsets.push(i + 1);
1029+
}
1030+
_ => {}
10221031
}
1032+
i += 1;
10231033
}
10241034

10251035
let para_node = self.arena.alloc(para_ast.into());
@@ -2268,7 +2278,7 @@ pub(crate) fn manual_scan_link_url(input: &str) -> Option<(&str, usize)> {
22682278
break;
22692279
} else if b == b'\\' {
22702280
i += 2;
2271-
} else if b == b'\n' || b == b'<' {
2281+
} else if b == b'\n' || b == b'\r' || b == b'<' {
22722282
return None;
22732283
} else {
22742284
i += 1;

0 commit comments

Comments
 (0)