From 4ce1544cb0096299243a622f564cd9eb33f04c03 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Dec 2025 10:05:30 +0000 Subject: [PATCH 1/2] Initial plan From aa656942d64632b19e62ebece3ca49cf49140581 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 24 Dec 2025 10:11:05 +0000 Subject: [PATCH 2/2] Add implementation for new CSS viewport units Co-authored-by: rbri <2544132+rbri@users.noreply.github.com> --- .../java/org/htmlunit/css/CssStyleSheet.java | 44 +- .../host/css/CSSStyleDeclaration.java | 18 + .../css/ComputedCSSStyleDeclarationTest.java | 441 ++++++++++++++++++ 3 files changed, 501 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/htmlunit/css/CssStyleSheet.java b/src/main/java/org/htmlunit/css/CssStyleSheet.java index be33af879a..7ebc859edb 100644 --- a/src/main/java/org/htmlunit/css/CssStyleSheet.java +++ b/src/main/java/org/htmlunit/css/CssStyleSheet.java @@ -1464,7 +1464,9 @@ else if ("print".equalsIgnoreCase(mediaType)) { private static double pixelValue(final CSSValueImpl cssValue, final WebWindow webWindow) { if (cssValue == null) { LOG.warn("CSSValue is null but has to be a 'px', 'em', '%', 'ex', 'ch', " - + "'vw', 'vh', 'vmin', 'vmax', 'rem', 'mm', 'cm', 'Q', or 'pt' value."); + + "'vw', 'vh', 'vmin', 'vmax', 'dvw', 'dvh', 'dvmin', 'dvmax', " + + "'lvw', 'lvh', 'lvmin', 'lvmax', 'svw', 'svh', 'svmin', 'svmax', " + + "'rem', 'mm', 'cm', 'Q', or 'pt' value."); return -1; } @@ -1499,6 +1501,42 @@ private static double pixelValue(final CSSValueImpl cssValue, final WebWindow we case VMAX: // hard coded default for the moment 16px = 100% return 0.16f * cssValue.getDoubleValue(); + case DVW: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case DVH: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case DVMIN: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case DVMAX: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case LVW: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case LVH: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case LVMIN: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case LVMAX: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case SVW: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case SVH: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case SVMIN: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); + case SVMAX: + // hard coded default for the moment 16px = 100% + return 0.16f * cssValue.getDoubleValue(); case REM: // hard coded default for the moment 16px = 100% return 0.16f * cssValue.getDoubleValue(); @@ -1522,7 +1560,9 @@ private static double pixelValue(final CSSValueImpl cssValue, final WebWindow we if (LOG.isWarnEnabled()) { LOG.warn("CSSValue '" + cssValue.getCssText() + "' has to be a 'px', 'em', '%', 'ex', 'ch', " - + "'vw', 'vh', 'vmin', 'vmax', 'rem', 'mm', 'cm', 'Q', or 'pt' value."); + + "'vw', 'vh', 'vmin', 'vmax', 'dvw', 'dvh', 'dvmin', 'dvmax', " + + "'lvw', 'lvh', 'lvmin', 'lvmax', 'svw', 'svh', 'svmin', 'svmax', " + + "'rem', 'mm', 'cm', 'Q', or 'pt' value."); } return -1; } diff --git a/src/main/java/org/htmlunit/javascript/host/css/CSSStyleDeclaration.java b/src/main/java/org/htmlunit/javascript/host/css/CSSStyleDeclaration.java index 89415b8171..859a7a5f57 100644 --- a/src/main/java/org/htmlunit/javascript/host/css/CSSStyleDeclaration.java +++ b/src/main/java/org/htmlunit/javascript/host/css/CSSStyleDeclaration.java @@ -2008,6 +2008,24 @@ else if (valueString.endsWith("rem") unit = valueString.substring(valueString.length() - 3); valueString = valueString.substring(0, valueString.length() - 3); } + else if (valueString.endsWith("dvw") + || valueString.endsWith("dvh") + || valueString.endsWith("lvw") + || valueString.endsWith("lvh") + || valueString.endsWith("svw") + || valueString.endsWith("svh")) { + unit = valueString.substring(valueString.length() - 3); + valueString = valueString.substring(0, valueString.length() - 3); + } + else if (valueString.endsWith("dvmin") + || valueString.endsWith("dvmax") + || valueString.endsWith("lvmin") + || valueString.endsWith("lvmax") + || valueString.endsWith("svmin") + || valueString.endsWith("svmax")) { + unit = valueString.substring(valueString.length() - 5); + valueString = valueString.substring(0, valueString.length() - 5); + } else { return; } diff --git a/src/test/java/org/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java b/src/test/java/org/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java index 8aaa0d1890..bea002e1b5 100644 --- a/src/test/java/org/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java +++ b/src/test/java/org/htmlunit/javascript/host/css/ComputedCSSStyleDeclarationTest.java @@ -1225,6 +1225,447 @@ public void fontSizeVW() throws Exception { loadPageVerifyTitle2(html); } + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeVMin() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeVMax() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeDVW() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeDVH() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeDVMin() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeDVMax() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeLVW() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeLVH() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeLVMin() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeLVMax() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeSVW() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeSVH() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(DEFAULT = "4.03333px", + CHROME = "3.726px", + EDGE = "3.78px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeSVMin() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + + /** + * @throws Exception if an error occurs + */ + @Test + @Alerts(CHROME = "7.536px", + EDGE = "7.488px", + FF = "7.53333px", + FF_ESR = "7.53333px") + @HtmlUnitNYI(CHROME = "1px", + EDGE = "1px", + FF = "1px", + FF_ESR = "1px") + public void fontSizeSVMax() throws Exception { + final String html = DOCTYPE_HTML + + "\n" + + "
\n" + + "
inside
\n" + + "
\n" + + "\n" + + ""; + loadPageVerifyTitle2(html); + } + /** * @throws Exception if the test fails */