mirror of
https://github.com/lexmount/moli.git
synced 2026-10-07 08:01:00 +00:00
fix(svg): preserve paths before parse errors
This commit is contained in:
@@ -3095,8 +3095,7 @@ pub(super) fn svg_geometry_get_total_length_callback<'s>(
|
||||
) {
|
||||
let length = svg_geometry_segments(scope, args.this())
|
||||
.iter()
|
||||
.map(SvgGeometrySegment::length)
|
||||
.sum::<f64>();
|
||||
.fold(0.0, |total, segment| total + segment.length());
|
||||
rv.set(v8::Number::new(scope, length).into());
|
||||
}
|
||||
|
||||
|
||||
@@ -2728,6 +2728,47 @@ fn svg_geometry_queries_use_computed_paths_live_tree_and_kurbo_bounds() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn svg_path_errors_keep_valid_prefix_and_positive_zero_length() {
|
||||
let mut vm = new_parsed_test_vm(
|
||||
"https://svg-path-error-handling.test/",
|
||||
r##"<!doctype html>
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<path id="invalid" d="M 10 10 L 30 10 X 50 10"/>
|
||||
<path id="empty" d=""/>
|
||||
<path id="none" d="none"/>
|
||||
<path id="missing_move" d="L 20 20"/>
|
||||
</svg>"##,
|
||||
);
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const byId = id => document.getElementById(id);
|
||||
const invalid = byId("invalid");
|
||||
const end = invalid.getPointAtLength(invalid.getTotalLength());
|
||||
return JSON.stringify({
|
||||
length: invalid.getTotalLength(),
|
||||
end: [end.x, end.y],
|
||||
emptyIsPositiveZero: Object.is(byId("empty").getTotalLength(), 0),
|
||||
noneIsPositiveZero: Object.is(byId("none").getTotalLength(), 0),
|
||||
missingMoveIsPositiveZero: Object.is(
|
||||
byId("missing_move").getTotalLength(),
|
||||
0,
|
||||
),
|
||||
});
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("SVG path error handling probe should evaluate");
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
r#"{"length":20,"end":[30,10],"emptyIsPositiveZero":true,"noneIsPositiveZero":true,"missingMoveIsPositiveZero":true}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn element_methods_and_dataset_live_on_owner_prototypes() {
|
||||
let mut vm = new_storage_test_vm("https://example.com/");
|
||||
|
||||
@@ -81,6 +81,17 @@ mod tests {
|
||||
assert_close(point.y, -20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_geometry_preserves_complete_segments_before_a_parse_error() {
|
||||
let invalid_command = path_segments("M 10 10 L 30 10 X 50 10");
|
||||
assert_eq!(invalid_command.len(), 1);
|
||||
assert_close(invalid_command[0].length(), 20.0);
|
||||
|
||||
let incomplete_curve = path_segments("M 10 10 L 30 10 C 40 0 50 20");
|
||||
assert_eq!(incomplete_curve.len(), 1);
|
||||
assert_close(incomplete_curve[0].length(), 20.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn path_geometry_handles_relative_commands_and_close_path() {
|
||||
let segments = path_segments("m 1 1 l 3 0 v 4 h -3 z");
|
||||
|
||||
@@ -4,7 +4,10 @@ use svgtypes::{SimplePathSegment, SimplifyingPathParser};
|
||||
pub(crate) fn path_geometry(raw: &str) -> Option<BezPath> {
|
||||
let mut path = BezPath::new();
|
||||
for segment in SimplifyingPathParser::from(raw) {
|
||||
match segment.ok()? {
|
||||
let Ok(segment) = segment else {
|
||||
break;
|
||||
};
|
||||
match segment {
|
||||
SimplePathSegment::MoveTo { x, y } => path.move_to((x, y)),
|
||||
SimplePathSegment::LineTo { x, y } => path.line_to((x, y)),
|
||||
SimplePathSegment::CurveTo {
|
||||
|
||||
Reference in New Issue
Block a user