font-valid.html (5126B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>CSS Fonts Module Level 4: parsing font with valid values</title> 6 <link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-prop"> 7 <meta name="assert" content="font supports the full grammar '[ [ <'font-style'> || <font-variant-css2> || <'font-weight'> || <font-stretch-css3> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar'."> 8 <script src="/resources/testharness.js"></script> 9 <script src="/resources/testharnessreport.js"></script> 10 <script src="/css/support/parsing-testcommon.js"></script> 11 </head> 12 <body> 13 <div id="target"></div> 14 <script> 15 'use strict'; 16 17 // Firefox and Edge 18 serialize these as supplied. 18 // Blink and Safari have implementation-dependent or platform-dependent serializations. 19 function test_system_font(keyword) { 20 test(() => { 21 const target = document.getElementById('target'); 22 const previousValue = 'italic xx-large/0px fantasy'; 23 target.style.font = previousValue; 24 target.style.font = keyword; 25 const readValue = target.style.getPropertyValue('font'); 26 assert_not_equals(readValue, '', 'font should be set'); 27 assert_not_equals(readValue, previousValue, 'font should be updated'); 28 target.style.font = previousValue; 29 target.style.font = readValue; 30 assert_equals(target.style.getPropertyValue('font'), readValue, "serialization should round-trip"); 31 }, keyword + ' should be a supported system font.'); 32 } 33 34 test_system_font('caption'); 35 test_system_font('icon'); 36 test_system_font('menu'); 37 test_system_font('message-box'); 38 test_system_font('small-caption'); 39 test_system_font('status-bar'); 40 41 // values other than normal 42 const generate_style = (() => { 43 const alternatives = [ 44 'italic', 45 'oblique' 46 ]; 47 let counter = 0; 48 return () => alternatives[counter++ % alternatives.length]; 49 })(); 50 51 // value other than normal 52 const generate_variant = () => 'small-caps'; 53 54 // values other than normal 55 const generate_weight = (() => { 56 const alternatives = [ 57 'bold', 58 'bolder', 59 'lighter', 60 '100', 61 '900' 62 ]; 63 let counter = 0; 64 return () => alternatives[counter++ % alternatives.length]; 65 })(); 66 67 // values other than normal 68 const generate_stretch = (() => { 69 const alternatives = [ 70 'ultra-condensed', 71 'extra-condensed', 72 'condensed', 73 'semi-condensed', 74 'semi-expanded', 75 'expanded', 76 'extra-expanded', 77 'ultra-expanded' 78 ]; 79 let counter = 0; 80 return () => alternatives[counter++ % alternatives.length]; 81 })(); 82 83 const generate_size = (() => { 84 const alternatives = [ 85 // <absolute-size> 86 'xx-small', 87 'medium', 88 'xx-large', 89 90 // <relative-size> 91 'larger', 92 'smaller', 93 94 // <length-percentage> 95 '10px', 96 '20%', 97 'calc(30% - 40px)', 98 ]; 99 let counter = 0; 100 return () => alternatives[counter++ % alternatives.length]; 101 })(); 102 103 const generate_line_height = (() => { 104 const alternatives = [ 105 null, 106 'normal', 107 '1.2', 108 'calc(120% + 1.2em)' 109 ]; 110 let counter = 0; 111 return () => alternatives[counter++ % alternatives.length]; 112 })(); 113 114 const generate_family = (() => { 115 const alternatives = [ 116 'serif', 117 'sans-serif', 118 'cursive', 119 'fantasy', 120 'monospace', 121 'Menu', 122 '"FB Armada"' 123 ]; 124 let counter = 0; 125 return () => alternatives[counter++ % alternatives.length]; 126 })(); 127 128 function test_specific(prefix) { 129 let parts = []; 130 let canonical = []; 131 let style = null; 132 let variant = null; 133 let weight = null; 134 let stretch = null; 135 for (let entry of prefix) { 136 if (entry === 'style') { 137 style = generate_style(); 138 parts.push(style); 139 } else if (entry === 'variant') { 140 variant = generate_variant(); 141 parts.push(variant); 142 } else if (entry === 'weight') { 143 weight = generate_weight(); 144 parts.push(weight); 145 } else if (entry === 'stretch') { 146 stretch = generate_stretch(); 147 parts.push(stretch); 148 } else { 149 // normal 150 parts.push('normal'); 151 } 152 } 153 154 if (style) 155 canonical.push(style); 156 if (variant) 157 canonical.push(variant); 158 if (weight) 159 canonical.push(weight); 160 if (stretch) 161 canonical.push(stretch); 162 163 const size = generate_size(); 164 const lineHeight = generate_line_height(); 165 if (lineHeight) { 166 parts.push(size + '/' + lineHeight); 167 if (lineHeight === 'normal') 168 canonical.push(size); 169 else 170 canonical.push(size + ' / ' + lineHeight); 171 } else { 172 parts.push(size); 173 canonical.push(size); 174 } 175 176 const family = generate_family(); 177 parts.push(family); 178 canonical.push(family); 179 180 test_valid_value('font', parts.join(' '), canonical.join(' ')); 181 } 182 183 function test_various(prefix) { 184 test_specific(prefix); 185 if (prefix.length === 4) 186 return; 187 188 const alternatives = [ 189 'normal', 190 'style', 191 'variant', 192 'weight', 193 'stretch' 194 ]; 195 for (let alternative of alternatives) { 196 if (alternative === 'normal' || !prefix.includes(alternative)) 197 test_various(prefix.concat(alternative)); 198 // else we would have two styles or two variants, etc. 199 } 200 } 201 202 test_various([]); 203 </script> 204 </body> 205 </html>