Add tests for Selection.toString() and text-transform (#41012)
* Add tests for Selection.toString() and text-transform
This is a variation of the test added in [1] verifying how selection
works on the single char 'ß' with text-transform: uppercase. This is
special because the transformed text is 'SS' which has length 2. Instead
of using a reftest to check the rendered selection really spans the 2
characters, we use a JS test to directly check the returned value of
Selection.toString().
We generalize this approach to characters that are converted to their
italic equivalent via text-transform: math-auto. Note that for most of
them, the transformed text is a character in the Mathematical
Alphanumeric Symbols block, which is represented as a surrogate pair in
UTF-16. So it has length 2 as a UTF-16 string, although it's really
rendered as one character. The new approach works better than the reftest
approach in order to exhibit Chromium's bug 750990 [2].
A similar test is added for single-char <mi> elements, which perform
the same transformations as math-auto. That way it could work with
browsers implementing this MathML feature without relying on math-auto.
[1] https://chromium-review.googlesource.com/c/chromium/src/+/2987819
[2] https://bugs.chromium.org/p/chromium/issues/detail?id=750990
* Update mathvariant-transforms.py
diff --git a/css/css-text/text-transform/math/italic-mapping.js b/css/css-text/text-transform/math/italic-mapping.js
new file mode 100644
index 0000000..ba17d3f
--- /dev/null
+++ b/css/css-text/text-transform/math/italic-mapping.js
@@ -0,0 +1,115 @@
+// Generated by mathml/tools/mathvariant.py; DO NOT EDIT.
+let italic_mapping = {
+ 0x41: 0x1D434,
+ 0x42: 0x1D435,
+ 0x43: 0x1D436,
+ 0x44: 0x1D437,
+ 0x45: 0x1D438,
+ 0x46: 0x1D439,
+ 0x47: 0x1D43A,
+ 0x48: 0x1D43B,
+ 0x49: 0x1D43C,
+ 0x4A: 0x1D43D,
+ 0x4B: 0x1D43E,
+ 0x4C: 0x1D43F,
+ 0x4D: 0x1D440,
+ 0x4E: 0x1D441,
+ 0x4F: 0x1D442,
+ 0x50: 0x1D443,
+ 0x51: 0x1D444,
+ 0x52: 0x1D445,
+ 0x53: 0x1D446,
+ 0x54: 0x1D447,
+ 0x55: 0x1D448,
+ 0x56: 0x1D449,
+ 0x57: 0x1D44A,
+ 0x58: 0x1D44B,
+ 0x59: 0x1D44C,
+ 0x5A: 0x1D44D,
+ 0x61: 0x1D44E,
+ 0x62: 0x1D44F,
+ 0x63: 0x1D450,
+ 0x64: 0x1D451,
+ 0x65: 0x1D452,
+ 0x66: 0x1D453,
+ 0x67: 0x1D454,
+ 0x68: 0x210E,
+ 0x69: 0x1D456,
+ 0x6A: 0x1D457,
+ 0x6B: 0x1D458,
+ 0x6C: 0x1D459,
+ 0x6D: 0x1D45A,
+ 0x6E: 0x1D45B,
+ 0x6F: 0x1D45C,
+ 0x70: 0x1D45D,
+ 0x71: 0x1D45E,
+ 0x72: 0x1D45F,
+ 0x73: 0x1D460,
+ 0x74: 0x1D461,
+ 0x75: 0x1D462,
+ 0x76: 0x1D463,
+ 0x77: 0x1D464,
+ 0x78: 0x1D465,
+ 0x79: 0x1D466,
+ 0x7A: 0x1D467,
+ 0x131: 0x1D6A4,
+ 0x237: 0x1D6A5,
+ 0x391: 0x1D6E2,
+ 0x392: 0x1D6E3,
+ 0x393: 0x1D6E4,
+ 0x394: 0x1D6E5,
+ 0x395: 0x1D6E6,
+ 0x396: 0x1D6E7,
+ 0x397: 0x1D6E8,
+ 0x398: 0x1D6E9,
+ 0x399: 0x1D6EA,
+ 0x39A: 0x1D6EB,
+ 0x39B: 0x1D6EC,
+ 0x39C: 0x1D6ED,
+ 0x39D: 0x1D6EE,
+ 0x39E: 0x1D6EF,
+ 0x39F: 0x1D6F0,
+ 0x3A0: 0x1D6F1,
+ 0x3A1: 0x1D6F2,
+ 0x3F4: 0x1D6F3,
+ 0x3A3: 0x1D6F4,
+ 0x3A4: 0x1D6F5,
+ 0x3A5: 0x1D6F6,
+ 0x3A6: 0x1D6F7,
+ 0x3A7: 0x1D6F8,
+ 0x3A8: 0x1D6F9,
+ 0x3A9: 0x1D6FA,
+ 0x2207: 0x1D6FB,
+ 0x3B1: 0x1D6FC,
+ 0x3B2: 0x1D6FD,
+ 0x3B3: 0x1D6FE,
+ 0x3B4: 0x1D6FF,
+ 0x3B5: 0x1D700,
+ 0x3B6: 0x1D701,
+ 0x3B7: 0x1D702,
+ 0x3B8: 0x1D703,
+ 0x3B9: 0x1D704,
+ 0x3BA: 0x1D705,
+ 0x3BB: 0x1D706,
+ 0x3BC: 0x1D707,
+ 0x3BD: 0x1D708,
+ 0x3BE: 0x1D709,
+ 0x3BF: 0x1D70A,
+ 0x3C0: 0x1D70B,
+ 0x3C1: 0x1D70C,
+ 0x3C2: 0x1D70D,
+ 0x3C3: 0x1D70E,
+ 0x3C4: 0x1D70F,
+ 0x3C5: 0x1D710,
+ 0x3C6: 0x1D711,
+ 0x3C7: 0x1D712,
+ 0x3C8: 0x1D713,
+ 0x3C9: 0x1D714,
+ 0x2202: 0x1D715,
+ 0x3F5: 0x1D716,
+ 0x3D1: 0x1D717,
+ 0x3F0: 0x1D718,
+ 0x3D5: 0x1D719,
+ 0x3F1: 0x1D71A,
+ 0x3D6: 0x1D71B,
+}
diff --git a/css/css-text/text-transform/math/text-transform-math-auto-003.html b/css/css-text/text-transform/math/text-transform-math-auto-003.html
new file mode 100644
index 0000000..eff01b0
--- /dev/null
+++ b/css/css-text/text-transform/math/text-transform-math-auto-003.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>text-transform math-auto</title>
+ <link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+ <link rel="help" href="https://w3c.github.io/mathml-core/#italic-mappings">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="italic-mapping.js"></script>
+ <meta name="assert" content="Verify Selection.toString() on a character with 'text-transform: math-auto' returns the transformed unicode character.">
+ <style>
+ #container {
+ text-transform: math-auto;
+ }
+ </style>
+ </head>
+ <body>
+ <span id="container"></span>
+ <script>
+ add_completion_callback(() => {
+ container.remove();
+ });
+ for (let code_point in italic_mapping) {
+ test(() => {
+ container.textContent = String.fromCodePoint(code_point);
+ window
+ .getSelection()
+ .setBaseAndExtent(container.firstChild, 0, container.firstChild, 1);
+ assert_equals(
+ window.getSelection().toString(),
+ String.fromCodePoint(italic_mapping[code_point])
+ );
+ }, `Selection.toString() for math-auto '${String.fromCodePoint(code_point)}' returns the transformed character.`);
+ }
+ </script>
+ </body>
+</html>
diff --git a/css/css-text/text-transform/text-transform-upperlower-107.html b/css/css-text/text-transform/text-transform-upperlower-107.html
new file mode 100644
index 0000000..791edd1
--- /dev/null
+++ b/css/css-text/text-transform/text-transform-upperlower-107.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Text Test: text-transform uppercase German sharp S and selection</title>
+<link rel="author" title="Frédéric Wang" href="mailto:fwang@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-text/#propdef-text-transform">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<meta name="assert" content="text-transform: uppercase will uppercase the German sharp S as SS, the whole 2 characters is selectable and should be returned when retriving the selected string.">
+<style>
+ #target {
+ text-transform: uppercase;
+ }
+</style>
+
+<span id="target" lang="de">ß</span>
+
+<script>
+ test(() => {
+ window.getSelection().setBaseAndExtent(target, 0, target, 1);
+ assert_equals(window.getSelection().toString(), "SS");
+ }, "Selection.toString() for 'ß' with text-transform: uppercase");
+</script>
diff --git a/mathml/relations/css-styling/mathvariant-auto-selection.html b/mathml/relations/css-styling/mathvariant-auto-selection.html
new file mode 100644
index 0000000..f915c44
--- /dev/null
+++ b/mathml/relations/css-styling/mathvariant-auto-selection.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8"/>
+ <title>text-transform math-auto</title>
+ <link rel="help" href="https://w3c.github.io/mathml-core/#new-text-transform-values">
+ <link rel="help" href="https://w3c.github.io/mathml-core/#italic-mappings">
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/css/css-text/text-transform/math/italic-mapping.js"></script>
+ <meta name="assert" content="Verify Selection.toString() on a single character <mi> within returns the transformed unicode character.">
+ </head>
+ <body>
+ <math><mi id="container"></mi></math>
+ <script>
+ add_completion_callback(() => {
+ container.remove();
+ });
+ for (let code_point in italic_mapping) {
+ test(() => {
+ container.textContent = String.fromCodePoint(code_point);
+ window
+ .getSelection()
+ .setBaseAndExtent(container.firstChild, 0, container.firstChild, 1);
+ assert_equals(
+ window.getSelection().toString(),
+ String.fromCodePoint(italic_mapping[code_point])
+ );
+ }, `Selection.toString() for <mi>${String.fromCodePoint(code_point)}</mi> returns the transformed character.`);
+ }
+ </script>
+ </body>
+</html>
diff --git a/mathml/tools/mathvariant-transforms.py b/mathml/tools/mathvariant-transforms.py
index e4857d2..dca85b5 100755
--- a/mathml/tools/mathvariant-transforms.py
+++ b/mathml/tools/mathvariant-transforms.py
@@ -195,6 +195,18 @@
generateTestFor(mathvariant="auto", mathml=False)
generateTestFor(mathvariant="auto", mathml=True)
+# Generate italic_mapping.js file used by selection tests.
+print("Generating italic_mapping.js...", end="")
+italic_mapping = open("../../css/css-text/text-transform/math/italic-mapping.js", "w")
+italic_mapping.write("// Generated by mathml/tools/mathvariant.py; DO NOT EDIT.\n");
+italic_mapping.write("let italic_mapping = {\n");
+for baseChar in mathvariantTransforms["italic"]:
+ transformedChar = mathvariantTransforms[mathvariant][baseChar]
+ italic_mapping.write(" 0x%0X: 0x%0X,\n" % (baseChar, transformedChar));
+italic_mapping.write("}\n");
+italic_mapping.close()
+print(" done.")
+
# Other mathvariant tests can be generated by the following command. They are
# still use internally by browsers implementing full mathvariant support.
# See https://github.com/w3c/mathml-core/issues/182