///|
/// Creates a sink that runs `f` before finishing downstream.
pub fn Sink::on_finish(self : Sink, f : (Sink) -> Unit) -> Sink {
Sink(fn(event) { self.emit(event) }, finish=fn() {
f(self)
self.finish()
})
}
///|
/// Creates a sink that maps every event before forwarding it downstream.
pub fn Sink::map(self : Sink, f : (Event) -> Event) -> Sink {
Sink(fn(event) { self.emit(copy_event(f(event))) }, finish=fn() {
self.finish()
})
}
///|
/// Creates a sink that merges adjacent `Text` events before forwarding.
pub fn Sink::text_merge(self : Sink) -> Sink {
let mut pending : String? = None
Sink(
fn(event) {
match event {
Text(text) =>
match pending {
Some(prev) => pending = Some(prev + text)
None => pending = Some(text)
}
_ => {
match pending {
Some(text) => self.emit(Text(text))
None => ()
}
pending = None
self.emit(event)
}
}
},
finish=fn() {
match pending {
Some(text) => self.emit(Text(text))
None => ()
}
pending = None
self.finish()
},
)
}
///|
/// Creates a sink that rewrites every `SoftBreak` event to `HardBreak`.
pub fn Sink::softbreak_to_hardbreak(self : Sink) -> Sink {
self.map(fn(event) {
match event {
SoftBreak => HardBreak
_ => event
}
})
}
///|
/// Creates a sink that renames matching `Enter` and `Exit` tags.
pub fn Sink::rename_tag(self : Sink, from : Tag, to : Tag) -> Sink {
self.map(fn(event) {
match event {
Enter(el) =>
if el.tag == from {
Enter({ tag: to, attrs: el.attrs, range: el.range })
} else {
event
}
Exit(tag) => if tag == from { Exit(to) } else { event }
_ => event
}
})
}
///|
/// Creates a sink that appends an attribute to matching `Enter` elements.
pub fn Sink::inject_attr(self : Sink, tag : Tag, attr : Attr) -> Sink {
self.map(fn(event) {
match event {
Enter(el) =>
if el.tag == tag {
let attrs : Array[Attr] = []
for old in el.attrs {
attrs.push(old)
}
attrs.push(attr)
Enter({ tag: el.tag, attrs, range: el.range })
} else {
event
}
_ => event
}
})
}