mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-08-01 02:06:17 -04:00
Merge pull request #2823 from lightpanda-io/css_normalize_leading_zero
css: normalize fractions without leading 0
This commit is contained in:
@@ -159,6 +159,35 @@
|
||||
<div id=crash1 style="background-position: 5% .1em"></div>
|
||||
<script id="crash_case_1">
|
||||
{
|
||||
testing.expectEqual('5% .1em', $('#crash1').style.backgroundPosition);
|
||||
// Per CSSOM, bare ".1em" serializes with a leading zero -> "0.1em"
|
||||
testing.expectEqual('5% 0.1em', $('#crash1').style.backgroundPosition);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div id=opacity-detect style="opacity:.55"></div>
|
||||
<script id="leadingZeroNormalization">
|
||||
{
|
||||
// jQuery's support.opacity feature-detect reads an inline "opacity:.55"
|
||||
// back and matches it against /^0.55$/; bare ".55" must serialize as "0.55".
|
||||
testing.expectEqual('0.55', $('#opacity-detect').style.opacity);
|
||||
|
||||
const div = $('#test-div');
|
||||
div.style.cssText = '';
|
||||
|
||||
// leading-dot value via property assignment
|
||||
div.style.opacity = '.5';
|
||||
testing.expectEqual('0.5', div.style.opacity);
|
||||
|
||||
// negative leading-dot, with unit, preserved otherwise
|
||||
div.style.marginLeft = '-.5px';
|
||||
testing.expectEqual('-0.5px', div.style.marginLeft);
|
||||
|
||||
// existing leading digit is untouched
|
||||
div.style.lineHeight = '1.5';
|
||||
testing.expectEqual('1.5', div.style.lineHeight);
|
||||
|
||||
// multiple numbers in one value
|
||||
div.style.margin = '.5em .25em';
|
||||
testing.expectEqual('0.5em 0.25em', div.style.margin);
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -245,7 +245,9 @@ fn normalizePropertyName(name: []const u8, buf: []u8) []const u8 {
|
||||
}
|
||||
|
||||
// Normalize CSS property values for canonical serialization
|
||||
fn normalizePropertyValue(arena: Allocator, property_name: []const u8, value: []const u8) ![]const u8 {
|
||||
fn normalizePropertyValue(arena: Allocator, property_name: []const u8, raw_value: []const u8) ![]const u8 {
|
||||
const value = try normalizeLeadingZeros(arena, raw_value);
|
||||
|
||||
// Per CSSOM spec, unitless zero in length properties should serialize as "0px"
|
||||
if (std.mem.eql(u8, value, "0") and isLengthProperty(property_name)) {
|
||||
return "0px";
|
||||
@@ -286,6 +288,51 @@ fn normalizePropertyValue(arena: Allocator, property_name: []const u8, value: []
|
||||
return value;
|
||||
}
|
||||
|
||||
// Insert a leading "0" before any bare ".<digit>". A value might have multiple
|
||||
// such bare digits
|
||||
fn normalizeLeadingZeros(arena: Allocator, value: []const u8) ![]const u8 {
|
||||
// A bare ".<digit>" needs at least 2 chars, and a trailing "." can never be
|
||||
// followed by a digit. So we only ever scan up to value.len - 1, which lets
|
||||
// us index value[i + 1] without a bounds check.
|
||||
if (value.len < 2) {
|
||||
return value;
|
||||
}
|
||||
|
||||
var inserts: usize = 0;
|
||||
for (value[0 .. value.len - 1], 0..) |c, i| {
|
||||
if (c != '.') {
|
||||
continue;
|
||||
}
|
||||
if (!std.ascii.isDigit(value[i + 1])) {
|
||||
// next value isn't a digit
|
||||
continue;
|
||||
}
|
||||
if (i > 0 and std.ascii.isDigit(value[i - 1])) {
|
||||
// previous value is a digit
|
||||
continue;
|
||||
}
|
||||
inserts += 1;
|
||||
}
|
||||
if (inserts == 0) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const buf = try arena.alloc(u8, value.len + inserts);
|
||||
var w: usize = 0;
|
||||
for (value[0 .. value.len - 1], 0..) |c, i| {
|
||||
if (c == '.' and std.ascii.isDigit(value[i + 1]) and (i == 0 or !std.ascii.isDigit(value[i - 1]))) {
|
||||
buf[w] = '0';
|
||||
w += 1;
|
||||
}
|
||||
buf[w] = c;
|
||||
w += 1;
|
||||
}
|
||||
// The last char is copied unconditionally: it can't start a bare ".<digit>".
|
||||
buf[w] = value[value.len - 1];
|
||||
w += 1;
|
||||
return buf[0..w];
|
||||
}
|
||||
|
||||
// Canonicalize anchor-size() so that the dashed ident (anchor name) comes before the size keyword.
|
||||
// e.g. "anchor-size(width --foo)" -> "anchor-size(--foo width)"
|
||||
fn canonicalizeAnchorSize(arena: Allocator, value: []const u8, start_index: usize) ![]const u8 {
|
||||
|
||||
Reference in New Issue
Block a user