├── HISTORY.md ├── LICENSE ├── README.md ├── errors.md └── src ├── Grammar ├── Alternative.php ├── AnythingMatcher.php ├── BlockMatcher.php ├── CheckedMatcher.php ├── CustomPropertyMatcher.php ├── DelimMatcher.php ├── FunctionMatcher.php ├── GrammarMatch.php ├── Juxtaposition.php ├── KeywordMatcher.php ├── Matcher.php ├── MatcherFactory.php ├── NoWhitespace.php ├── NonEmpty.php ├── NothingMatcher.php ├── Quantifier.php ├── TokenMatcher.php ├── UnorderedGroup.php ├── UrangeMatcher.php ├── UrlMatcher.php └── WhitespaceMatcher.php ├── Objects ├── AtRule.php ├── CSSFunction.php ├── CSSObject.php ├── CSSObjectList.php ├── ComponentValue.php ├── ComponentValueList.php ├── Declaration.php ├── DeclarationList.php ├── DeclarationOrAtRule.php ├── DeclarationOrAtRuleList.php ├── QualifiedRule.php ├── Rule.php ├── RuleList.php ├── SimpleBlock.php ├── Stylesheet.php ├── Token.php └── TokenList.php ├── Parser ├── DataSource.php ├── DataSourceTokenizer.php ├── Encoder.php ├── Parser.php ├── StringDataSource.php ├── TokenListTokenizer.php └── Tokenizer.php ├── Sanitizer ├── FontFaceAtRuleSanitizer.php ├── ImportAtRuleSanitizer.php ├── KeyframesAtRuleSanitizer.php ├── MarginAtRuleSanitizer.php ├── MediaAtRuleSanitizer.php ├── NamespaceAtRuleSanitizer.php ├── PageAtRuleSanitizer.php ├── PropertySanitizer.php ├── RuleSanitizer.php ├── Sanitizer.php ├── StyleAttributeSanitizer.php ├── StylePropertySanitizer.php ├── StyleRuleSanitizer.php ├── StylesheetSanitizer.php └── SupportsAtRuleSanitizer.php └── Util.php /HISTORY.md: -------------------------------------------------------------------------------- 1 | # Release History 2 | 3 | ## css-sanitizer x.x.x (not yet released) 4 | * Add support for CSS Box Sizing Level 4 (as seen in draft from 2025-02-24) 5 | - values: stretch, fit-content, and contain; 6 | - properties: aspect-ratio, contain-intrinsic-* (size, width, height, block-size, inline-size), min-intrinsic-size; 7 | * Update Color to Level 4 (2025-04-24) 8 | 9 | ## css-sanizer 5.5.0 (2025-01-27) 10 | * Ensure <-token and identifiers are always separated as a security 11 | paranoia measure 12 | * Add support for prefers-reduced-motion, prefers-reduced-transparency, 13 | prefers-contrast and forced-colors media queries 14 | * Add support for light-dark() color function 15 | * [build] Bump dependencies 16 | 17 | ## css-sanitizer 5.4.0 (2024-10-30) 18 | * Add support for `:dir()` pseudo-class 19 | * Add support for CSS Logical 1 properties and values 20 | 21 | * code: Use explicit nullable type on parameter arguments 22 | * build: Phan must ignore EmptyIterator type in UnorderedGroup 23 | * build: Updating composer dependencies 24 | * build: Updating mediawiki/mediawiki-codesniffer to 44.0.0 25 | * build: Allow wikimedia/scopedcallback 5.0.0 26 | * build: Allow wikimedia/testing-access-wrapper 3.0.0 27 | * build: Remove use of `$PHPUNIT_ARGS` 28 | 29 | ## css-sanitizer 5.3.0 (2024-04-18) 30 | * Harden security by disallowing CSS custom properties for `border-color` 31 | * Add support for fallback values for CSS custom properties in color attributes. 32 | 33 | ## css-sanitizer 5.2.0 (2024-04-03) 34 | * Add support for CSS custom properties in color attributes 35 | * [build] Bump dependencies 36 | 37 | ## css-sanitizer 5.1.0 (2024-02-21) 38 | * Drop support for wikimedia/utfnormal 2.x 39 | * Change use of AtEase to at operator 40 | * Support @media (prefers-color-scheme:...) rule 41 | * [build] Bump dependencies 42 | 43 | ## css-sanitizer 5.0.0 (2023-08-29) 44 | * Drop support for PHP < 7.4 45 | * Support wikimedia/utfnormal ^4.0.0 46 | * [build] Bump dependencies 47 | 48 | ## css-sanitizer 4.0.1 (2022-07-09) 49 | * Allow wikimedia/scoped-callback 4.0.0 50 | 51 | ## css-sanitizer 4.0.0 (2022-07-03) 52 | * Update for new versions of various standards 53 | * Add return types to inbuilt interfaces 54 | * [build] Bump dependencies 55 | 56 | ## css-sanitizer 3.0.2 (2021-03-21) 57 | * Relax wikimedia/at-ease to ^2.0.0 58 | * [build] Bump dependencies 59 | 60 | ## css-sanitizer 3.0.1 (2021-01-30) 61 | * Support wikimedia/utfnormal ^3.0.1 62 | 63 | ## css-sanitizer 3.0.0 (2021-01-04) 64 | * Drop support for PHP < 7.2 and HHVM 65 | * Switch to PHPUnit 8; drop support for PHPUnit 4 66 | * Remove support for wikimedia/utfnormal 1.1.0 67 | * Make Parser::CV_DEPTH_LIMIT private 68 | * [BREAKING CHANGE] Rename match() and Match class for PHP 8.0 69 | * [build] Bump dependencies 70 | 71 | ## css-sanitizer 2.0.1 (2019-02-11) 72 | * [build] Bump dependencies 73 | 74 | ## css-sanitizer 2.0.0 (2018-08-24) 75 | * Update for new versions of various standards 76 | * Add CSS Intrinsic and Extrinsic Sizing Level 3 77 | * Add hoisting option to StyleRuleSanitizer selector handling 78 | 79 | ## css-sanitizer 1.0.6 (2018-04-18) 80 | * [build] Bump dependencies 81 | 82 | ## css-sanitizer 1.0.5 (2018-04-02) 83 | * Workaround IE parsing bug 84 | * [build] Bump dependencies 85 | 86 | ## css-sanitizer 1.0.4 (2018-02-27) 87 | * Optionally depend on wikimedia/utfnormal 2.0.0 88 | * [build] Bump dependencies 89 | 90 | ## css-sanitizer 1.0.3 (2018-01-17) 91 | * [build] Bump dependencies 92 | 93 | ## css-sanitizer 1.0.2 (2017-06-13) 94 | * [SECURITY] Escape angle brackets numerically in strings and identifiers 95 | 96 | ## css-sanitizer 1.0.1 (2017-06-06) 97 | * Fix escaping of various characters 98 | 99 | ## css-sanitizer 1.0.0 (2017-04-06) 100 | * Initial release. 101 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Latest Stable Version]](https://packagist.org/packages/wikimedia/css-sanitizer) [![License]](https://packagist.org/packages/wikimedia/css-sanitizer) 2 | 3 | Wikimedia CSS Parser & Sanitizer 4 | ================================ 5 | 6 | This library implements a CSS tokenizer, parser and grammar matcher in PHP. 7 | 8 | Usage 9 | ----- 10 | 11 | ```php 12 | use Wikimedia\CSS\Parser\Parser; 13 | use Wikimedia\CSS\Sanitizer\StylesheetSanitizer; 14 | 15 | /** Parse a stylesheet from a string **/ 16 | 17 | $parser = Parser::newFromString( $cssText ); 18 | $stylesheet = $parser->parseStylesheet(); 19 | 20 | /** Report any parser errors **/ 21 | 22 | foreach ( $parser->getParseErrors() as list( $code, $line, $pos ) ) { 23 | // $code is a string that should be suitable as a key for an i18n library. 24 | // See errors.md for details. 25 | $error = lookupI18nMessage( "css-parse-error-$code" ); 26 | echo "Parse error: $error at line $line character $pos\n"; 27 | } 28 | 29 | /** Apply sanitization to the stylesheet **/ 30 | 31 | // If you need to customize the defaults, copy the code of this method and 32 | // modify it. 33 | $sanitizer = StylesheetSanitizer::newDefault(); 34 | $newStylesheet = $sanitizer->sanitize( $stylesheet ); 35 | 36 | /** Report any sanitizer errors **/ 37 | 38 | foreach ( $sanitizer->getSanitizationErrors() as list( $code, $line, $pos ) ) { 39 | // $code is a string that should be suitable as a key for an i18n library. 40 | // See errors.md for details. 41 | $error = lookupI18nMessage( "css-sanitization-error-$code" ); 42 | echo "Sanitization error: $error at line $line character $pos\n"; 43 | } 44 | 45 | /** Convert the sanitized stylesheet back to text **/ 46 | 47 | $newText = (string)$newStylesheet; 48 | 49 | // Or if you'd rather have it minified too 50 | $minifiedText = Wikimedia\CSS\Util::stringify( $newStylesheet, [ 'minify' => true ] ); 51 | ``` 52 | 53 | Conformance 54 | ----------- 55 | 56 | The library follows the following grammar specifications: 57 | 58 | * [CSS Syntax Level 3, 2019-07-16][CSSSYN] 59 | * [CSS Values and Units Module Level 3, 2019-06-06][CSSVAL] 60 | * [CSS Selectors Level 3, 2018-11-06][CSSSEL] 61 | 62 | The sanitizer recognizes the following CSS modules: 63 | 64 | * [Align Level 3, 2018-12-06](https://www.w3.org/TR/2018/WD-css-align-3-20181206/) 65 | * [Animations Level 1, 2018-10-11](https://www.w3.org/TR/2018/WD-css-animations-1-20181011/) 66 | * [Backgrounds Level 3, 2017-10-17](https://www.w3.org/TR/2017/CR-css-backgrounds-3-20171017/) 67 | * [Break Level 3, 2018-12-04](https://www.w3.org/TR/2018/CR-css-break-3-20181204/) 68 | * [Cascade Level 4, 2018-08-28](https://www.w3.org/TR/2018/CR-css-cascade-4-20180828) 69 | * [Color Level 4, 2025-04-24](https://www.w3.org/TR/2025/CRD-css-color-4-20250424) 70 | * [Compositing Level 1, 2015-01-13](https://www.w3.org/TR/2015/CR-compositing-1-20150113/) 71 | * [CSS Level 2, 2011-06-07](https://www.w3.org/TR/2011/REC-CSS2-20110607/) 72 | * [Display Level 3, 2019-07-11](https://www.w3.org/TR/2019/CR-css-display-3-20190711) 73 | * [Filter Effects Level 1, 2018-12-18](https://www.w3.org/TR/2018/WD-filter-effects-1-20181218) 74 | * [Flexbox Level 1, 2018-11-19](https://www.w3.org/TR/2018/CR-css-flexbox-1-20181119) 75 | * [Fonts Level 3, 2018-09-20](https://www.w3.org/TR/2018/REC-css-fonts-3-20180920) 76 | * [Grid Level 1, 2017-12-14](https://www.w3.org/TR/2017/CR-css-grid-1-20171214/) 77 | * [Images Level 3, 2019-10-10](https://www.w3.org/TR/2019/CR-css-images-3-20191010) 78 | * [Masking Level 1, 2014-08-26](https://www.w3.org/TR/2014/CR-css-masking-1-20140826/) 79 | * [Multicol Level 1, 2019-10-15](https://www.w3.org/TR/2019/WD-css-multicol-1-20191015) 80 | * [Overflow Level 3, 2018-07-31](https://www.w3.org/TR/2018/WD-css-overflow-3-20180731) 81 | * [Page Level 3, 2018-10-18](https://www.w3.org/TR/2018/WD-css-page-3-20181018) 82 | * [Position Level 3, 2016-05-17](https://www.w3.org/TR/2016/WD-css-position-3-20160517/) 83 | * [Shapes Level 1, 2014-03-20](https://www.w3.org/TR/2014/CR-css-shapes-1-20140320/) 84 | * [Sizing Level 3, 2021-12-17](https://www.w3.org/TR/2021/WD-css-sizing-3-20211217/) 85 | * [Sizing Level 4, 2025-02-24](https://drafts.csswg.org/css-sizing-4/) 86 | * [Text Level 3, 2019-11-13](https://www.w3.org/TR/2019/WD-css-text-3-20191113) 87 | * [Text Decorations Level 3, 2019-08-13](https://www.w3.org/TR/2019/CR-css-text-decor-3-20190813) 88 | * [Easing Level 1, 2019-04-30](https://www.w3.org/TR/2019/CR-css-easing-1-20190430/) 89 | * [Transforms Level 1, 2019-02-14](https://www.w3.org/TR/2019/CR-css-transforms-1-20190214) 90 | * [Transitions Level 1, 2018-10-11](https://www.w3.org/TR/2018/WD-css-transitions-1-20181011) 91 | * [UI 3 Level 3, 2018-06-21](https://www.w3.org/TR/2018/REC-css-ui-3-20180621) 92 | * [UI 4 Level 4, 2020-01-02](https://www.w3.org/TR/2020/WD-css-ui-4-20200102) 93 | * [Writing Modes Level 4, 2019-07-30](https://www.w3.org/TR/2019/CR-css-writing-modes-4-20190730) 94 | * [Selectors Level 4, 2019-02-25](https://www.w3.org/TR/2019/WD-css-pseudo-4-20190225/) 95 | * [Logical Properties and Values Level 1, 2018-08-27](https://www.w3.org/TR/2018/WD-css-logical-1-20180827/) 96 | 97 | And also, 98 | * The `touch-action` property from 99 | [Pointer Events Level 2, 2019-04-04](https://www.w3.org/TR/2019/REC-pointerevents2-20190404/) 100 | * `:dir()` pseudo-class from [Selectors Level 4, 2022-11-11](https://www.w3.org/TR/2022/WD-selectors-4-20221111/#the-dir-pseudo) 101 | * Accessibility related media features from [Media Queries Level 5](https://drafts.csswg.org/mediaqueries-5/#mf-user-preferences) including prefers-reduced-motion, prefers-reduced-transparency, prefers-contrast and forced-colors. 102 | * `light-dark()` color function from [Color Module Level 5, 2024-02-29](https://www.w3.org/TR/2024/WD-css-color-5-20240229/#funcdef-light-dark) 103 | 104 | Running tests 105 | ------------- 106 | 107 | composer install --prefer-dist 108 | composer test 109 | 110 | Adding properties 111 | ----------------- 112 | 113 | CSS specifications typically contain a summary of value grammars in the property 114 | index section. These value grammars map directly to PHP code. 115 | 116 | [Component value types](https://www.w3.org/TR/css-values-4/#component-types) 117 | 118 | | Syntax | css-sanitizer code | 119 | |----------------|------------------------------------------| 120 | | `foo` | `new KeywordMatcher( 'foo' )` | 121 | | `foo \| bar` | `new KeywordMatcher( [ 'foo', 'bar' ] )` | 122 | | `` | `$matcherFactory->string()` | 123 | | `` | `$matcherFactory->url()` | 124 | | `` | `$matcherFactory->integer()` | 125 | | `` | `$matcherFactory->number()` | 126 | | `` | `$matcherFactory->ratio()` | 127 | | `` | `$matcherFactory->percentage()` | 128 | | `` | `$matcherFactory->length()` | 129 | | `` | `$matcherFactory->frequency()` | 130 | | `` | `$matcherFactory->angle()` | 131 | | `