presentation-attributes.js (9055B)
1 const PROPERTIES = { 2 "alignment-baseline": { 3 value: "middle", 4 relevantElement: "text", 5 irrelevantElement: "rect", 6 }, 7 "baseline-shift": { 8 value: "1", 9 relevantElement: "text", 10 irrelevantElement: "rect", 11 }, 12 "clip-path": { 13 value: "url(#e)", 14 relevantElement: "g", 15 irrelevantElement: "linearGradient", 16 }, 17 "clip-rule": { 18 value: "evenodd", 19 relevantElement: "g", 20 irrelevantElement: "linearGradient", 21 }, 22 "color": { 23 value: "blue", 24 relevantElement: "g", 25 irrelevantElement: "image", 26 }, 27 "color-interpolation-filters": { 28 value: "sRGB", 29 relevantElement: "filter", 30 irrelevantElement: "linearGradient", 31 }, 32 "color-interpolation": { 33 value: "linearRGB", 34 relevantElement: "linearGradient", 35 irrelevantElement: "image", 36 }, 37 "cursor": { 38 value: "pointer", 39 relevantElement: "g", 40 irrelevantElement: "defs", 41 }, 42 "cx": { 43 value: "1", 44 relevantElement: "circle", 45 irrelevantElement: null, 46 }, 47 "cy": { 48 value: "1", 49 relevantElement: "circle", 50 irrelevantElement: null, 51 }, 52 "direction": { 53 value: "rtl", 54 relevantElement: "text", 55 irrelevantElement: "rect", 56 }, 57 "display": { 58 value: "block", 59 relevantElement: "g", 60 irrelevantElement: "linearGradient", 61 }, 62 "d": { 63 value: "M0,0 L1,1", 64 relevantElement: "path", 65 irrelevantElement: null, 66 }, 67 "dominant-baseline": { 68 value: "middle", 69 relevantElement: "text", 70 irrelevantElement: "rect", 71 }, 72 "fill": { 73 value: "blue", 74 relevantElement: "g", 75 irrelevantElement: "image", 76 }, 77 "fill-opacity": { 78 value: "0.5", 79 relevantElement: "g", 80 irrelevantElement: "image", 81 }, 82 "fill-rule": { 83 value: "evenodd", 84 relevantElement: "path", 85 irrelevantElement: "image", 86 }, 87 "filter": { 88 value: "url(#e)", 89 relevantElement: "g", 90 irrelevantElement: "linearGradient", 91 }, 92 "flood-color": { 93 value: "blue", 94 relevantElement: "feFlood", 95 irrelevantElement: "rect", 96 }, 97 "flood-opacity": { 98 value: "0.5", 99 relevantElement: "feFlood", 100 irrelevantElement: "rect", 101 }, 102 "font-family": { 103 value: "Test Family", 104 relevantElement: "text", 105 irrelevantElement: "rect", 106 }, 107 "font-size": { 108 value: "50", 109 relevantElement: "text", 110 irrelevantElement: "rect", 111 }, 112 "font-size-adjust": { 113 value: "0.5", 114 relevantElement: "text", 115 irrelevantElement: "rect", 116 }, 117 "font-stretch": { 118 value: "expanded", 119 relevantElement: "text", 120 irrelevantElement: "rect", 121 }, 122 "font-style": { 123 value: "italic", 124 relevantElement: "text", 125 irrelevantElement: "rect", 126 }, 127 "font-variant": { 128 value: "small-caps", 129 relevantElement: "text", 130 irrelevantElement: "rect", 131 }, 132 "font-weight": { 133 value: "900", 134 relevantElement: "text", 135 irrelevantElement: "rect", 136 }, 137 "glyph-orientation-vertical": { 138 value: "90", 139 relevantElement: "text", 140 irrelevantElement: "rect", 141 }, 142 "height": { 143 value: "1", 144 relevantElement: "rect", 145 irrelevantElement: null, 146 }, 147 "image-rendering": { 148 value: ["optimizeSpeed", "pixelated"], 149 relevantElement: "image", 150 irrelevantElement: "path", 151 }, 152 "letter-spacing": { 153 value: "1px", 154 relevantElement: "text", 155 irrelevantElement: "rect", 156 }, 157 "lighting-color": { 158 value: "blue", 159 relevantElement: "feDiffuseLighting", 160 irrelevantElement: "rect", 161 }, 162 "marker-end": { 163 value: "url(#e)", 164 relevantElement: "path", 165 irrelevantElement: "image", 166 }, 167 "marker-mid": { 168 value: "url(#e)", 169 relevantElement: "path", 170 irrelevantElement: "image", 171 }, 172 "marker-start": { 173 value: "url(#e)", 174 relevantElement: "path", 175 irrelevantElement: "image", 176 }, 177 "mask-type": { 178 value: "alpha", 179 relevantElement: "mask", 180 irrelevantElement: "rect", 181 }, 182 "mask": { 183 value: "url(#e)", 184 relevantElement: "g", 185 irrelevantElement: "linearGradient", 186 }, 187 "opacity": { 188 value: "0.5", 189 relevantElement: "g", 190 irrelevantElement: "linearGradient", 191 }, 192 "overflow": { 193 value: "scroll", 194 relevantElement: "svg", 195 irrelevantElement: "rect", 196 }, 197 "paint-order": { 198 value: "fill stroke", 199 relevantElement: "path", 200 irrelevantElement: "image", 201 }, 202 "pointer-events": { 203 value: "none", 204 relevantElement: "g", 205 irrelevantElement: "linearGradient", 206 }, 207 "r": { 208 value: "1", 209 relevantElement: "circle", 210 irrelevantElement: null, 211 }, 212 "rx": { 213 value: "1", 214 relevantElement: "rect", 215 irrelevantElement: null, 216 }, 217 "ry": { 218 value: "1", 219 relevantElement: "rect", 220 irrelevantElement: null, 221 }, 222 "shape-rendering": { 223 value: "geometricPrecision", 224 relevantElement: "path", 225 irrelevantElement: "image", 226 }, 227 "stop-color": { 228 value: "blue", 229 relevantElement: "stop", 230 irrelevantElement: "rect", 231 }, 232 "stop-opacity": { 233 value: "0.5", 234 relevantElement: "stop", 235 irrelevantElement: "rect", 236 }, 237 "stroke": { 238 value: "blue", 239 relevantElement: "path", 240 irrelevantElement: "image", 241 }, 242 "stroke-dasharray": { 243 value: "1 1", 244 relevantElement: "path", 245 irrelevantElement: "image", 246 }, 247 "stroke-dashoffset": { 248 value: "1", 249 relevantElement: "path", 250 irrelevantElement: "image", 251 }, 252 "stroke-linecap": { 253 value: "round", 254 relevantElement: "path", 255 irrelevantElement: "image", 256 }, 257 "stroke-linejoin": { 258 value: "round", 259 relevantElement: "path", 260 irrelevantElement: "image", 261 }, 262 "stroke-miterlimit": { 263 value: "1", 264 relevantElement: "path", 265 irrelevantElement: "image", 266 }, 267 "stroke-opacity": { 268 value: "0.5", 269 relevantElement: "path", 270 irrelevantElement: "image", 271 }, 272 "stroke-width": { 273 value: "2", 274 relevantElement: "path", 275 irrelevantElement: "image", 276 }, 277 "text-anchor": { 278 value: "middle", 279 relevantElement: "text", 280 irrelevantElement: "rect", 281 }, 282 "text-decoration": { 283 value: "underline", 284 relevantElement: "text", 285 irrelevantElement: "rect", 286 }, 287 "text-overflow": { 288 value: "ellipsis", 289 relevantElement: "text", 290 irrelevantElement: "rect", 291 }, 292 "text-rendering": { 293 value: "geometricPrecision", 294 relevantElement: "text", 295 irrelevantElement: "rect", 296 }, 297 "transform-origin": { 298 value: "1px 1px", 299 relevantElement: "g", 300 irrelevantElement: "linearGradient", 301 }, 302 "transform": { 303 value: "scale(2)", 304 relevantElement: "g", 305 irrelevantElement: null, 306 }, 307 "unicode-bidi": { 308 value: "embed", 309 relevantElement: "text", 310 irrelevantElement: "rect", 311 }, 312 "vector-effect": { 313 value: "non-scaling-stroke", 314 relevantElement: "g", 315 irrelevantElement: "linearGradient", 316 }, 317 "visibility": { 318 value: "hidden", 319 relevantElement: "g", 320 irrelevantElement: "linearGradient", 321 }, 322 "white-space": { 323 value: "pre", 324 relevantElement: "text", 325 irrelevantElement: "rect", 326 }, 327 "width": { 328 value: "1", 329 relevantElement: "rect", 330 irrelevantElement: null, 331 }, 332 "word-spacing": { 333 value: "1", 334 relevantElement: "text", 335 irrelevantElement: "rect", 336 }, 337 "writing-mode": { 338 value: "vertical-rl", 339 relevantElement: "text", 340 irrelevantElement: "rect", 341 }, 342 "x": { 343 value: "1", 344 relevantElement: "rect", 345 irrelevantElement: null, 346 }, 347 "y": { 348 value: "1", 349 relevantElement: "rect", 350 irrelevantElement: null, 351 }, 352 }; 353 354 function presentationAttributeIsSupported(element, attribute, value, property) { 355 let e = document.createElementNS("http://www.w3.org/2000/svg", element); 356 svg.append(e); 357 let propertyValueBefore = getComputedStyle(e).getPropertyValue(property); 358 e.setAttribute(attribute, value); 359 // Also set another attribute that is likely to be a presentation attribute, 360 // in order to provoke bugs. 361 const otherAttribute = attribute === 'stroke' ? 'fill' : 'stroke'; 362 e.setAttribute(otherAttribute, 'red'); 363 let propertyValueAfter = getComputedStyle(e).getPropertyValue(property); 364 e.remove(); 365 return propertyValueBefore != propertyValueAfter; 366 } 367 368 function assertPresentationAttributeIsSupported(element, attribute, values, property) { 369 if (typeof values === 'string') 370 values = [values]; 371 let supported = values.some( 372 value => presentationAttributeIsSupported(element, attribute, value, property)); 373 assert_true( 374 supported, 375 `Presentation attribute ${attribute}="${values.join(" | ")}" should be supported on ${element} element` 376 ); 377 } 378 379 function assertPresentationAttributeIsNotSupported(element, attribute, values, property) { 380 if (typeof values === 'string') 381 values = [values]; 382 let supported = values.some( 383 value => presentationAttributeIsSupported(element, attribute, value, property)); 384 assert_false( 385 supported, 386 `Presentation attribute ${attribute}="${values.join(" | ")}" should not be supported on ${element} element` 387 ); 388 } 389 390 function propertiesAreSupported(properties) { 391 for (let p of properties) { 392 if (!CSS.supports(p, "initial")) { 393 return false; 394 } 395 } 396 return true; 397 }