blitz-pdf 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (370) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +355 -2
  3. package/THIRD_PARTY_NOTICES.md +25 -0
  4. package/assets/icon.svg +4 -0
  5. package/dist/api.d.ts +7 -0
  6. package/dist/api.d.ts.map +1 -0
  7. package/dist/api.js +46 -0
  8. package/dist/api.js.map +1 -0
  9. package/dist/assets.d.ts +7 -0
  10. package/dist/assets.d.ts.map +1 -0
  11. package/dist/assets.js +52 -0
  12. package/dist/assets.js.map +1 -0
  13. package/dist/browser.d.ts +3 -0
  14. package/dist/browser.d.ts.map +1 -0
  15. package/dist/browser.js +3 -0
  16. package/dist/browser.js.map +1 -0
  17. package/dist/node.d.ts +3 -0
  18. package/dist/node.d.ts.map +1 -0
  19. package/dist/node.js +10 -0
  20. package/dist/node.js.map +1 -0
  21. package/dist/options.d.ts +24 -0
  22. package/dist/options.d.ts.map +1 -0
  23. package/dist/options.js +135 -0
  24. package/dist/options.js.map +1 -0
  25. package/dist/types.d.ts +51 -0
  26. package/dist/types.d.ts.map +1 -0
  27. package/dist/types.js +2 -0
  28. package/dist/types.js.map +1 -0
  29. package/examples/bun.ts +8 -0
  30. package/examples/german-invoice/README.md +70 -0
  31. package/examples/german-invoice/data.mjs +83 -0
  32. package/examples/german-invoice/invoice.css +59 -0
  33. package/examples/german-invoice/template.mjs +49 -0
  34. package/examples/german-invoice.mjs +20 -0
  35. package/examples/invoice.html +29 -0
  36. package/examples/node.mjs +8 -0
  37. package/examples/pagination.html +40 -0
  38. package/examples/pagination.mjs +8 -0
  39. package/licenses/DejaVu.txt +187 -0
  40. package/licenses/RUST_DEPENDENCIES.txt +11577 -0
  41. package/package.json +89 -4
  42. package/src/api.ts +44 -0
  43. package/src/assets.ts +43 -0
  44. package/src/browser.ts +6 -0
  45. package/src/node.ts +12 -0
  46. package/src/options.ts +101 -0
  47. package/src/types.ts +49 -0
  48. package/vendor/README.md +17 -0
  49. package/vendor/stylo/.cargo-ok +1 -0
  50. package/vendor/stylo/.cargo_vcs_info.json +6 -0
  51. package/vendor/stylo/Cargo.lock +1485 -0
  52. package/vendor/stylo/Cargo.toml +274 -0
  53. package/vendor/stylo/LICENSE +373 -0
  54. package/vendor/stylo/README.md +6 -0
  55. package/vendor/stylo/applicable_declarations.rs +328 -0
  56. package/vendor/stylo/author_styles.rs +79 -0
  57. package/vendor/stylo/bezier.rs +176 -0
  58. package/vendor/stylo/bloom.rs +414 -0
  59. package/vendor/stylo/build.rs +91 -0
  60. package/vendor/stylo/build_gecko.rs +393 -0
  61. package/vendor/stylo/color/color_function.rs +601 -0
  62. package/vendor/stylo/color/component.rs +207 -0
  63. package/vendor/stylo/color/convert.rs +935 -0
  64. package/vendor/stylo/color/gamut/raytrace.rs +265 -0
  65. package/vendor/stylo/color/gamut.rs +227 -0
  66. package/vendor/stylo/color/mix.rs +645 -0
  67. package/vendor/stylo/color/mod.rs +750 -0
  68. package/vendor/stylo/color/parsing.rs +770 -0
  69. package/vendor/stylo/color/to_css.rs +297 -0
  70. package/vendor/stylo/context.rs +716 -0
  71. package/vendor/stylo/counter_style/mod.rs +754 -0
  72. package/vendor/stylo/counter_style/predefined.rs +61 -0
  73. package/vendor/stylo/counter_style/update_predefined.py +35 -0
  74. package/vendor/stylo/custom_properties.rs +2023 -0
  75. package/vendor/stylo/custom_properties_map.rs +220 -0
  76. package/vendor/stylo/data.rs +693 -0
  77. package/vendor/stylo/device/gecko.rs +486 -0
  78. package/vendor/stylo/device/mod.rs +304 -0
  79. package/vendor/stylo/device/servo.rs +507 -0
  80. package/vendor/stylo/dom.rs +1164 -0
  81. package/vendor/stylo/dom_apis.rs +937 -0
  82. package/vendor/stylo/driver.rs +172 -0
  83. package/vendor/stylo/error_reporting.rs +484 -0
  84. package/vendor/stylo/font_face.rs +558 -0
  85. package/vendor/stylo/font_metrics.rs +124 -0
  86. package/vendor/stylo/gecko/anon_boxes.toml +113 -0
  87. package/vendor/stylo/gecko/arc_types.rs +211 -0
  88. package/vendor/stylo/gecko/conversions.rs +59 -0
  89. package/vendor/stylo/gecko/data.rs +222 -0
  90. package/vendor/stylo/gecko/media_features.rs +971 -0
  91. package/vendor/stylo/gecko/mod.rs +20 -0
  92. package/vendor/stylo/gecko/non_ts_pseudo_class_list.rs +119 -0
  93. package/vendor/stylo/gecko/pseudo_element.rs +640 -0
  94. package/vendor/stylo/gecko/pseudo_element_definition.mako.rs +298 -0
  95. package/vendor/stylo/gecko/pseudo_elements.py +137 -0
  96. package/vendor/stylo/gecko/pseudo_elements.toml +197 -0
  97. package/vendor/stylo/gecko/regen_pseudo_elements.py +33 -0
  98. package/vendor/stylo/gecko/restyle_damage.rs +127 -0
  99. package/vendor/stylo/gecko/selector_parser.rs +627 -0
  100. package/vendor/stylo/gecko/snapshot.rs +202 -0
  101. package/vendor/stylo/gecko/snapshot_helpers.rs +334 -0
  102. package/vendor/stylo/gecko/traversal.rs +52 -0
  103. package/vendor/stylo/gecko/wrapper.rs +2258 -0
  104. package/vendor/stylo/gecko_bindings/mod.rs +34 -0
  105. package/vendor/stylo/gecko_bindings/sugar/mod.rs +12 -0
  106. package/vendor/stylo/gecko_bindings/sugar/ns_com_ptr.rs +15 -0
  107. package/vendor/stylo/gecko_bindings/sugar/ns_compatibility.rs +19 -0
  108. package/vendor/stylo/gecko_bindings/sugar/ns_style_auto_array.rs +111 -0
  109. package/vendor/stylo/gecko_bindings/sugar/origin_flags.rs +31 -0
  110. package/vendor/stylo/gecko_bindings/sugar/ownership.rs +70 -0
  111. package/vendor/stylo/gecko_bindings/sugar/refptr.rs +299 -0
  112. package/vendor/stylo/gecko_string_cache/mod.rs +543 -0
  113. package/vendor/stylo/gecko_string_cache/namespace.rs +106 -0
  114. package/vendor/stylo/global_style_data.rs +224 -0
  115. package/vendor/stylo/invalidation/element/document_state.rs +156 -0
  116. package/vendor/stylo/invalidation/element/element_wrapper.rs +432 -0
  117. package/vendor/stylo/invalidation/element/invalidation_map.rs +1631 -0
  118. package/vendor/stylo/invalidation/element/invalidator.rs +1470 -0
  119. package/vendor/stylo/invalidation/element/mod.rs +13 -0
  120. package/vendor/stylo/invalidation/element/relative_selector.rs +1399 -0
  121. package/vendor/stylo/invalidation/element/restyle_hints.rs +226 -0
  122. package/vendor/stylo/invalidation/element/state_and_attributes.rs +756 -0
  123. package/vendor/stylo/invalidation/media_queries.rs +144 -0
  124. package/vendor/stylo/invalidation/mod.rs +10 -0
  125. package/vendor/stylo/invalidation/stylesheets.rs +745 -0
  126. package/vendor/stylo/invalidation/viewport_units.rs +71 -0
  127. package/vendor/stylo/lib.rs +336 -0
  128. package/vendor/stylo/logical_geometry.rs +1684 -0
  129. package/vendor/stylo/macros.rs +70 -0
  130. package/vendor/stylo/matching.rs +1226 -0
  131. package/vendor/stylo/media_queries/media_list.rs +168 -0
  132. package/vendor/stylo/media_queries/media_query.rs +190 -0
  133. package/vendor/stylo/media_queries/mod.rs +13 -0
  134. package/vendor/stylo/parallel.rs +205 -0
  135. package/vendor/stylo/parser.rs +276 -0
  136. package/vendor/stylo/piecewise_linear.rs +282 -0
  137. package/vendor/stylo/prefs.rs +33 -0
  138. package/vendor/stylo/properties/build.py +119 -0
  139. package/vendor/stylo/properties/cascade.rs +2704 -0
  140. package/vendor/stylo/properties/computed_value_flags.rs +206 -0
  141. package/vendor/stylo/properties/counted_unknown_properties.py +104 -0
  142. package/vendor/stylo/properties/counter_style_descriptors.toml +45 -0
  143. package/vendor/stylo/properties/data.py +1375 -0
  144. package/vendor/stylo/properties/declaration_block.rs +1788 -0
  145. package/vendor/stylo/properties/font_face_descriptors.toml +50 -0
  146. package/vendor/stylo/properties/gecko.mako.rs +1555 -0
  147. package/vendor/stylo/properties/helpers/animated_properties.mako.rs +800 -0
  148. package/vendor/stylo/properties/helpers.mako.rs +812 -0
  149. package/vendor/stylo/properties/longhands.toml +4305 -0
  150. package/vendor/stylo/properties/mod.rs +1857 -0
  151. package/vendor/stylo/properties/properties.html.mako +31 -0
  152. package/vendor/stylo/properties/properties.mako.rs +3103 -0
  153. package/vendor/stylo/properties/property_descriptors.toml +18 -0
  154. package/vendor/stylo/properties/shorthands.rs +4241 -0
  155. package/vendor/stylo/properties/shorthands.toml +575 -0
  156. package/vendor/stylo/properties/vendored_python/mako-1.3.10-py3-none-any.whl +0 -0
  157. package/vendor/stylo/properties/vendored_python/markupsafe/LICENSE.txt +28 -0
  158. package/vendor/stylo/properties/vendored_python/markupsafe/__init__.py +384 -0
  159. package/vendor/stylo/properties/vendored_python/toml-0.10.2-py2.py3-none-any.whl +0 -0
  160. package/vendor/stylo/properties/view_transition_descriptors.toml +11 -0
  161. package/vendor/stylo/properties_and_values/mod.rs +12 -0
  162. package/vendor/stylo/properties_and_values/registry.rs +65 -0
  163. package/vendor/stylo/properties_and_values/rule.rs +331 -0
  164. package/vendor/stylo/properties_and_values/syntax/ascii.rs +60 -0
  165. package/vendor/stylo/properties_and_values/syntax/data_type.rs +146 -0
  166. package/vendor/stylo/properties_and_values/syntax/mod.rs +437 -0
  167. package/vendor/stylo/properties_and_values/value.rs +758 -0
  168. package/vendor/stylo/queries/condition.rs +996 -0
  169. package/vendor/stylo/queries/feature.rs +199 -0
  170. package/vendor/stylo/queries/feature_expression.rs +1170 -0
  171. package/vendor/stylo/queries/mod.rs +19 -0
  172. package/vendor/stylo/queries/values.rs +46 -0
  173. package/vendor/stylo/rule_cache.rs +267 -0
  174. package/vendor/stylo/rule_collector.rs +554 -0
  175. package/vendor/stylo/rule_tree/core.rs +787 -0
  176. package/vendor/stylo/rule_tree/level.rs +396 -0
  177. package/vendor/stylo/rule_tree/map.rs +201 -0
  178. package/vendor/stylo/rule_tree/mod.rs +427 -0
  179. package/vendor/stylo/rule_tree/source.rs +80 -0
  180. package/vendor/stylo/rule_tree/unsafe_box.rs +78 -0
  181. package/vendor/stylo/scoped_tls.rs +80 -0
  182. package/vendor/stylo/selector_map.rs +1050 -0
  183. package/vendor/stylo/selector_parser.rs +305 -0
  184. package/vendor/stylo/servo/animation.rs +1922 -0
  185. package/vendor/stylo/servo/attr.rs +714 -0
  186. package/vendor/stylo/servo/encoding_support.rs +81 -0
  187. package/vendor/stylo/servo/media_features.rs +254 -0
  188. package/vendor/stylo/servo/mod.rs +16 -0
  189. package/vendor/stylo/servo/restyle_damage.rs +215 -0
  190. package/vendor/stylo/servo/selector_parser.rs +1036 -0
  191. package/vendor/stylo/servo/shadow_parts.rs +207 -0
  192. package/vendor/stylo/shared_lock.rs +271 -0
  193. package/vendor/stylo/sharing/checks.rs +281 -0
  194. package/vendor/stylo/sharing/mod.rs +1000 -0
  195. package/vendor/stylo/simple_buckets_map.rs +52 -0
  196. package/vendor/stylo/str.rs +168 -0
  197. package/vendor/stylo/style_adjuster.rs +1086 -0
  198. package/vendor/stylo/style_resolver.rs +658 -0
  199. package/vendor/stylo/stylesheet_set.rs +658 -0
  200. package/vendor/stylo/stylesheets/appearance_base_rule.rs +51 -0
  201. package/vendor/stylo/stylesheets/container_rule.rs +769 -0
  202. package/vendor/stylo/stylesheets/counter_style_rule.rs +7 -0
  203. package/vendor/stylo/stylesheets/document_rule.rs +272 -0
  204. package/vendor/stylo/stylesheets/font_face_rule.rs +7 -0
  205. package/vendor/stylo/stylesheets/font_feature_values_rule.rs +481 -0
  206. package/vendor/stylo/stylesheets/font_palette_values_rule.rs +304 -0
  207. package/vendor/stylo/stylesheets/import_rule.rs +259 -0
  208. package/vendor/stylo/stylesheets/keyframes_rule.rs +733 -0
  209. package/vendor/stylo/stylesheets/layer_rule.rs +221 -0
  210. package/vendor/stylo/stylesheets/loader.rs +29 -0
  211. package/vendor/stylo/stylesheets/margin_rule.rs +190 -0
  212. package/vendor/stylo/stylesheets/media_rule.rs +191 -0
  213. package/vendor/stylo/stylesheets/mod.rs +918 -0
  214. package/vendor/stylo/stylesheets/namespace_rule.rs +43 -0
  215. package/vendor/stylo/stylesheets/nested_declarations_rule.rs +51 -0
  216. package/vendor/stylo/stylesheets/origin.rs +249 -0
  217. package/vendor/stylo/stylesheets/page_rule.rs +354 -0
  218. package/vendor/stylo/stylesheets/position_try_rule.rs +68 -0
  219. package/vendor/stylo/stylesheets/property_rule.rs +5 -0
  220. package/vendor/stylo/stylesheets/rule_list.rs +167 -0
  221. package/vendor/stylo/stylesheets/rule_parser.rs +1189 -0
  222. package/vendor/stylo/stylesheets/rules_iterator.rs +397 -0
  223. package/vendor/stylo/stylesheets/scope_rule.rs +511 -0
  224. package/vendor/stylo/stylesheets/starting_style_rule.rs +54 -0
  225. package/vendor/stylo/stylesheets/style_rule.rs +80 -0
  226. package/vendor/stylo/stylesheets/stylesheet.rs +570 -0
  227. package/vendor/stylo/stylesheets/supports_rule.rs +486 -0
  228. package/vendor/stylo/stylesheets/view_transition_rule.rs +81 -0
  229. package/vendor/stylo/stylist.rs +5076 -0
  230. package/vendor/stylo/thread_state.rs +87 -0
  231. package/vendor/stylo/traversal.rs +765 -0
  232. package/vendor/stylo/traversal_flags.rs +68 -0
  233. package/vendor/stylo/typed_om/mod.rs +981 -0
  234. package/vendor/stylo/typed_om/numeric.rs +128 -0
  235. package/vendor/stylo/typed_om/numeric_declaration.rs +93 -0
  236. package/vendor/stylo/typed_om/numeric_type.rs +640 -0
  237. package/vendor/stylo/typed_om/sum_value.rs +426 -0
  238. package/vendor/stylo/url/gecko.rs +367 -0
  239. package/vendor/stylo/url/mod.rs +71 -0
  240. package/vendor/stylo/url/servo.rs +239 -0
  241. package/vendor/stylo/use_counters/mod.rs +137 -0
  242. package/vendor/stylo/values/animated/color.rs +103 -0
  243. package/vendor/stylo/values/animated/effects.rs +26 -0
  244. package/vendor/stylo/values/animated/font.rs +37 -0
  245. package/vendor/stylo/values/animated/grid.rs +161 -0
  246. package/vendor/stylo/values/animated/lists.rs +141 -0
  247. package/vendor/stylo/values/animated/mod.rs +550 -0
  248. package/vendor/stylo/values/animated/svg.rs +46 -0
  249. package/vendor/stylo/values/animated/text.rs +58 -0
  250. package/vendor/stylo/values/animated/transform.rs +1592 -0
  251. package/vendor/stylo/values/computed/align.rs +90 -0
  252. package/vendor/stylo/values/computed/angle.rs +130 -0
  253. package/vendor/stylo/values/computed/animation.rs +124 -0
  254. package/vendor/stylo/values/computed/background.rs +13 -0
  255. package/vendor/stylo/values/computed/basic_shape.rs +267 -0
  256. package/vendor/stylo/values/computed/border.rs +163 -0
  257. package/vendor/stylo/values/computed/box.rs +267 -0
  258. package/vendor/stylo/values/computed/calc.rs +334 -0
  259. package/vendor/stylo/values/computed/color.rs +161 -0
  260. package/vendor/stylo/values/computed/column.rs +11 -0
  261. package/vendor/stylo/values/computed/corner_shape.rs +155 -0
  262. package/vendor/stylo/values/computed/counters.rs +26 -0
  263. package/vendor/stylo/values/computed/easing.rs +109 -0
  264. package/vendor/stylo/values/computed/effects.rs +30 -0
  265. package/vendor/stylo/values/computed/flex.rs +19 -0
  266. package/vendor/stylo/values/computed/font.rs +1517 -0
  267. package/vendor/stylo/values/computed/image.rs +273 -0
  268. package/vendor/stylo/values/computed/length.rs +576 -0
  269. package/vendor/stylo/values/computed/length_percentage.rs +1055 -0
  270. package/vendor/stylo/values/computed/list.rs +16 -0
  271. package/vendor/stylo/values/computed/mod.rs +1141 -0
  272. package/vendor/stylo/values/computed/motion.rs +73 -0
  273. package/vendor/stylo/values/computed/outline.rs +7 -0
  274. package/vendor/stylo/values/computed/page.rs +77 -0
  275. package/vendor/stylo/values/computed/param.rs +9 -0
  276. package/vendor/stylo/values/computed/percentage.rs +143 -0
  277. package/vendor/stylo/values/computed/position.rs +273 -0
  278. package/vendor/stylo/values/computed/ratio.rs +88 -0
  279. package/vendor/stylo/values/computed/rect.rs +19 -0
  280. package/vendor/stylo/values/computed/resolution.rs +76 -0
  281. package/vendor/stylo/values/computed/svg.rs +66 -0
  282. package/vendor/stylo/values/computed/table.rs +7 -0
  283. package/vendor/stylo/values/computed/text.rs +199 -0
  284. package/vendor/stylo/values/computed/time.rs +83 -0
  285. package/vendor/stylo/values/computed/transform.rs +559 -0
  286. package/vendor/stylo/values/computed/tree_counting.rs +30 -0
  287. package/vendor/stylo/values/computed/ui.rs +23 -0
  288. package/vendor/stylo/values/computed/url.rs +12 -0
  289. package/vendor/stylo/values/distance.rs +139 -0
  290. package/vendor/stylo/values/generics/animation.rs +363 -0
  291. package/vendor/stylo/values/generics/background.rs +65 -0
  292. package/vendor/stylo/values/generics/basic_shape.rs +1389 -0
  293. package/vendor/stylo/values/generics/border.rs +303 -0
  294. package/vendor/stylo/values/generics/box.rs +552 -0
  295. package/vendor/stylo/values/generics/calc.rs +2986 -0
  296. package/vendor/stylo/values/generics/color.rs +318 -0
  297. package/vendor/stylo/values/generics/column.rs +44 -0
  298. package/vendor/stylo/values/generics/counters.rs +320 -0
  299. package/vendor/stylo/values/generics/easing.rs +132 -0
  300. package/vendor/stylo/values/generics/effects.rs +131 -0
  301. package/vendor/stylo/values/generics/flex.rs +34 -0
  302. package/vendor/stylo/values/generics/font.rs +376 -0
  303. package/vendor/stylo/values/generics/grid.rs +962 -0
  304. package/vendor/stylo/values/generics/image.rs +653 -0
  305. package/vendor/stylo/values/generics/length.rs +656 -0
  306. package/vendor/stylo/values/generics/mod.rs +303 -0
  307. package/vendor/stylo/values/generics/motion.rs +274 -0
  308. package/vendor/stylo/values/generics/page.rs +167 -0
  309. package/vendor/stylo/values/generics/position.rs +669 -0
  310. package/vendor/stylo/values/generics/ratio.rs +88 -0
  311. package/vendor/stylo/values/generics/rect.rs +147 -0
  312. package/vendor/stylo/values/generics/size.rs +102 -0
  313. package/vendor/stylo/values/generics/svg.rs +226 -0
  314. package/vendor/stylo/values/generics/text.rs +268 -0
  315. package/vendor/stylo/values/generics/transform.rs +1157 -0
  316. package/vendor/stylo/values/generics/ui.rs +147 -0
  317. package/vendor/stylo/values/generics/url.rs +51 -0
  318. package/vendor/stylo/values/mod.rs +820 -0
  319. package/vendor/stylo/values/resolved/animation.rs +33 -0
  320. package/vendor/stylo/values/resolved/color.rs +53 -0
  321. package/vendor/stylo/values/resolved/counters.rs +45 -0
  322. package/vendor/stylo/values/resolved/mod.rs +316 -0
  323. package/vendor/stylo/values/specified/align.rs +711 -0
  324. package/vendor/stylo/values/specified/angle.rs +407 -0
  325. package/vendor/stylo/values/specified/animation.rs +921 -0
  326. package/vendor/stylo/values/specified/background.rs +270 -0
  327. package/vendor/stylo/values/specified/basic_shape.rs +986 -0
  328. package/vendor/stylo/values/specified/border.rs +430 -0
  329. package/vendor/stylo/values/specified/box.rs +2231 -0
  330. package/vendor/stylo/values/specified/calc.rs +1657 -0
  331. package/vendor/stylo/values/specified/color.rs +1210 -0
  332. package/vendor/stylo/values/specified/column.rs +11 -0
  333. package/vendor/stylo/values/specified/corner_shape.rs +152 -0
  334. package/vendor/stylo/values/specified/counters.rs +242 -0
  335. package/vendor/stylo/values/specified/easing.rs +225 -0
  336. package/vendor/stylo/values/specified/effects.rs +421 -0
  337. package/vendor/stylo/values/specified/flex.rs +42 -0
  338. package/vendor/stylo/values/specified/font.rs +2103 -0
  339. package/vendor/stylo/values/specified/frequency.rs +39 -0
  340. package/vendor/stylo/values/specified/grid.rs +407 -0
  341. package/vendor/stylo/values/specified/image.rs +1385 -0
  342. package/vendor/stylo/values/specified/intersection_observer.rs +80 -0
  343. package/vendor/stylo/values/specified/length.rs +2024 -0
  344. package/vendor/stylo/values/specified/list.rs +190 -0
  345. package/vendor/stylo/values/specified/mod.rs +531 -0
  346. package/vendor/stylo/values/specified/motion.rs +316 -0
  347. package/vendor/stylo/values/specified/number.rs +603 -0
  348. package/vendor/stylo/values/specified/outline.rs +69 -0
  349. package/vendor/stylo/values/specified/page.rs +94 -0
  350. package/vendor/stylo/values/specified/param.rs +121 -0
  351. package/vendor/stylo/values/specified/percentage.rs +364 -0
  352. package/vendor/stylo/values/specified/position.rs +2247 -0
  353. package/vendor/stylo/values/specified/ratio.rs +29 -0
  354. package/vendor/stylo/values/specified/rect.rs +28 -0
  355. package/vendor/stylo/values/specified/resolution.rs +237 -0
  356. package/vendor/stylo/values/specified/source_size_list.rs +135 -0
  357. package/vendor/stylo/values/specified/svg.rs +427 -0
  358. package/vendor/stylo/values/specified/svg_path.rs +1115 -0
  359. package/vendor/stylo/values/specified/table.rs +38 -0
  360. package/vendor/stylo/values/specified/text.rs +1561 -0
  361. package/vendor/stylo/values/specified/time.rs +313 -0
  362. package/vendor/stylo/values/specified/transform.rs +599 -0
  363. package/vendor/stylo/values/specified/tree_counting.rs +32 -0
  364. package/vendor/stylo/values/specified/ui.rs +344 -0
  365. package/vendor/stylo/values/specified/url.rs +12 -0
  366. package/vendor/stylo/values/tagged_numeric.rs +253 -0
  367. package/wasm/blitz_pdf.d.ts +67 -0
  368. package/wasm/blitz_pdf.js +699 -0
  369. package/wasm/blitz_pdf_bg.wasm +0 -0
  370. package/wasm/blitz_pdf_bg.wasm.d.ts +20 -0
@@ -0,0 +1,1170 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+
5
+ //! Parsing for query feature expressions, like `(foo: bar)` or
6
+ //! `(width >= 400px)`.
7
+
8
+ use super::feature::{Evaluator, QueryFeatureDescription};
9
+ use super::feature::{FeatureFlags, KeywordDiscriminant};
10
+ use crate::context::QuirksMode;
11
+ use crate::custom_properties::{
12
+ self, ComputedSubstitutionFunctions, SubstitutionFunctionKind,
13
+ VariableValue as CustomVariableValue,
14
+ };
15
+ use crate::derives::*;
16
+ use crate::dom::AttributeTracker;
17
+ use crate::parser::{Parse, ParserContext};
18
+ use crate::properties::CSSWideKeyword;
19
+ use crate::properties_and_values::value::{ComputedValueComponent as Component, ValueInner};
20
+ use crate::selector_map::PrecomputedHashSet;
21
+ use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase};
22
+ use crate::stylesheets::container_rule::AttrReferenceSet;
23
+ use crate::stylesheets::{CssRuleType, Origin, UrlExtraData};
24
+ use crate::values::computed::{self, CSSPixelLength, ToComputedValue};
25
+ use crate::values::specified::{
26
+ Angle, Integer, Length, Number, Percentage, Ratio, Resolution, Time,
27
+ };
28
+ use crate::values::DashedIdent;
29
+ use crate::{Atom, Zero};
30
+ use cssparser::{Parser, Token};
31
+ use selectors::kleene_value::KleeneValue;
32
+ use std::cmp::Ordering;
33
+ use std::fmt::{self, Write};
34
+ use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss};
35
+
36
+ /// Whether we're parsing a media or container query feature.
37
+ #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
38
+ pub enum FeatureType {
39
+ /// We're parsing a media feature.
40
+ Media,
41
+ /// We're parsing a container feature.
42
+ Container,
43
+ }
44
+
45
+ impl FeatureType {
46
+ fn features(&self) -> &'static [QueryFeatureDescription] {
47
+ #[cfg(feature = "gecko")]
48
+ use crate::gecko::media_features::MEDIA_FEATURES;
49
+ #[cfg(feature = "servo")]
50
+ use crate::servo::media_features::MEDIA_FEATURES;
51
+
52
+ use crate::stylesheets::container_rule::CONTAINER_FEATURES;
53
+
54
+ match *self {
55
+ FeatureType::Media => &MEDIA_FEATURES,
56
+ FeatureType::Container => &CONTAINER_FEATURES,
57
+ }
58
+ }
59
+
60
+ fn find_feature(&self, name: &Atom) -> Option<(usize, &'static QueryFeatureDescription)> {
61
+ self.features()
62
+ .iter()
63
+ .enumerate()
64
+ .find(|(_, f)| f.name == *name)
65
+ }
66
+ }
67
+
68
+ /// The kind of matching that should be performed on a feature value.
69
+ #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
70
+ enum LegacyRange {
71
+ /// At least the specified value.
72
+ Min,
73
+ /// At most the specified value.
74
+ Max,
75
+ }
76
+
77
+ /// The operator that was specified in this feature.
78
+ #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
79
+ pub enum Operator {
80
+ /// =
81
+ Equal,
82
+ /// >
83
+ GreaterThan,
84
+ /// >=
85
+ GreaterThanEqual,
86
+ /// <
87
+ LessThan,
88
+ /// <=
89
+ LessThanEqual,
90
+ }
91
+
92
+ impl ToCss for Operator {
93
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
94
+ where
95
+ W: fmt::Write,
96
+ {
97
+ dest.write_str(match *self {
98
+ Self::Equal => "=",
99
+ Self::LessThan => "<",
100
+ Self::LessThanEqual => "<=",
101
+ Self::GreaterThan => ">",
102
+ Self::GreaterThanEqual => ">=",
103
+ })
104
+ }
105
+ }
106
+
107
+ impl Operator {
108
+ fn is_compatible_with(self, right_op: Self) -> bool {
109
+ // Some operators are not compatible with each other in multi-range
110
+ // context.
111
+ match self {
112
+ Self::Equal => false,
113
+ Self::GreaterThan | Self::GreaterThanEqual => {
114
+ matches!(right_op, Self::GreaterThan | Self::GreaterThanEqual)
115
+ },
116
+ Self::LessThan | Self::LessThanEqual => {
117
+ matches!(right_op, Self::LessThan | Self::LessThanEqual)
118
+ },
119
+ }
120
+ }
121
+
122
+ fn evaluate(&self, cmp: Ordering) -> bool {
123
+ match *self {
124
+ Self::Equal => cmp == Ordering::Equal,
125
+ Self::GreaterThan => cmp == Ordering::Greater,
126
+ Self::GreaterThanEqual => cmp == Ordering::Equal || cmp == Ordering::Greater,
127
+ Self::LessThan => cmp == Ordering::Less,
128
+ Self::LessThanEqual => cmp == Ordering::Equal || cmp == Ordering::Less,
129
+ }
130
+ }
131
+
132
+ fn parse(input: &mut Parser) -> Result<Self, ParseError> {
133
+ let operator = match *input.next()? {
134
+ Token::Delim('=') => return Ok(Operator::Equal),
135
+ Token::Delim('>') => Operator::GreaterThan,
136
+ Token::Delim('<') => Operator::LessThan,
137
+ _ => return Err(ParseError::unexpected_token()),
138
+ };
139
+
140
+ // https://drafts.csswg.org/mediaqueries-4/#mq-syntax:
141
+ //
142
+ // No whitespace is allowed between the “<” or “>”
143
+ // <delim-token>s and the following “=” <delim-token>, if it’s
144
+ // present.
145
+ //
146
+ // TODO(emilio): Maybe we should ignore comments as well?
147
+ // https://github.com/w3c/csswg-drafts/issues/6248
148
+ let parsed_equal = input
149
+ .try_parse(|i| {
150
+ let t = i.next_including_whitespace().map_err(|_| ())?;
151
+ if !matches!(t, Token::Delim('=')) {
152
+ return Err(());
153
+ }
154
+ Ok(())
155
+ })
156
+ .is_ok();
157
+
158
+ if !parsed_equal {
159
+ return Ok(operator);
160
+ }
161
+
162
+ Ok(match operator {
163
+ Operator::GreaterThan => Operator::GreaterThanEqual,
164
+ Operator::LessThan => Operator::LessThanEqual,
165
+ _ => unreachable!(),
166
+ })
167
+ }
168
+ }
169
+
170
+ #[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)]
171
+ enum QueryFeatureExpressionKind {
172
+ /// Just the media feature name.
173
+ Empty,
174
+
175
+ /// A single value.
176
+ Single(QueryExpressionValue),
177
+
178
+ /// Legacy range syntax (min-*: value) or so.
179
+ LegacyRange(LegacyRange, QueryExpressionValue),
180
+
181
+ /// Modern range context syntax:
182
+ /// https://drafts.csswg.org/mediaqueries-5/#mq-range-context
183
+ Range {
184
+ left: Option<(Operator, QueryExpressionValue)>,
185
+ right: Option<(Operator, QueryExpressionValue)>,
186
+ },
187
+ }
188
+
189
+ impl QueryFeatureExpressionKind {
190
+ /// Evaluate a given range given an optional query value and a value from
191
+ /// the browser.
192
+ fn evaluate<T>(
193
+ &self,
194
+ context_value: T,
195
+ mut compute: impl FnMut(&QueryExpressionValue) -> T,
196
+ ) -> bool
197
+ where
198
+ T: PartialOrd + Zero,
199
+ {
200
+ match *self {
201
+ Self::Empty => !context_value.is_zero(),
202
+ Self::Single(ref value) => {
203
+ let value = compute(value);
204
+ let cmp = match context_value.partial_cmp(&value) {
205
+ Some(c) => c,
206
+ None => return false,
207
+ };
208
+ cmp == Ordering::Equal
209
+ },
210
+ Self::LegacyRange(ref range, ref value) => {
211
+ let value = compute(value);
212
+ let cmp = match context_value.partial_cmp(&value) {
213
+ Some(c) => c,
214
+ None => return false,
215
+ };
216
+ cmp == Ordering::Equal
217
+ || match range {
218
+ LegacyRange::Min => cmp == Ordering::Greater,
219
+ LegacyRange::Max => cmp == Ordering::Less,
220
+ }
221
+ },
222
+ Self::Range {
223
+ ref left,
224
+ ref right,
225
+ } => {
226
+ debug_assert!(left.is_some() || right.is_some());
227
+ if let Some((op, value)) = left {
228
+ let value = compute(value);
229
+ let cmp = match value.partial_cmp(&context_value) {
230
+ Some(c) => c,
231
+ None => return false,
232
+ };
233
+ if !op.evaluate(cmp) {
234
+ return false;
235
+ }
236
+ }
237
+ if let Some((op, value)) = right {
238
+ let value = compute(value);
239
+ let cmp = match context_value.partial_cmp(&value) {
240
+ Some(c) => c,
241
+ None => return false,
242
+ };
243
+ if !op.evaluate(cmp) {
244
+ return false;
245
+ }
246
+ }
247
+ true
248
+ },
249
+ }
250
+ }
251
+
252
+ /// Non-ranged features only need to compare to one value at most.
253
+ fn non_ranged_value(&self) -> Option<&QueryExpressionValue> {
254
+ match *self {
255
+ Self::Empty => None,
256
+ Self::Single(ref v) => Some(v),
257
+ Self::LegacyRange(..) | Self::Range { .. } => {
258
+ debug_assert!(false, "Unexpected ranged value in non-ranged feature!");
259
+ None
260
+ },
261
+ }
262
+ }
263
+ }
264
+
265
+ /// A feature expression contains a reference to the feature, the value the
266
+ /// query contained, and the range to evaluate.
267
+ #[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)]
268
+ pub struct QueryFeatureExpression {
269
+ feature_type: FeatureType,
270
+ feature_index: usize,
271
+ kind: QueryFeatureExpressionKind,
272
+ }
273
+
274
+ impl ToCss for QueryFeatureExpression {
275
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
276
+ where
277
+ W: fmt::Write,
278
+ {
279
+ dest.write_char('(')?;
280
+
281
+ match self.kind {
282
+ QueryFeatureExpressionKind::Empty => self.write_name(dest)?,
283
+ QueryFeatureExpressionKind::Single(ref v)
284
+ | QueryFeatureExpressionKind::LegacyRange(_, ref v) => {
285
+ self.write_name(dest)?;
286
+ dest.write_str(": ")?;
287
+ v.to_css(dest, Some(self))?;
288
+ },
289
+ QueryFeatureExpressionKind::Range {
290
+ ref left,
291
+ ref right,
292
+ } => {
293
+ if let Some((op, val)) = left {
294
+ val.to_css(dest, Some(self))?;
295
+ dest.write_char(' ')?;
296
+ op.to_css(dest)?;
297
+ dest.write_char(' ')?;
298
+ }
299
+ self.write_name(dest)?;
300
+ if let Some((op, val)) = right {
301
+ dest.write_char(' ')?;
302
+ op.to_css(dest)?;
303
+ dest.write_char(' ')?;
304
+ val.to_css(dest, Some(self))?;
305
+ }
306
+ },
307
+ }
308
+ dest.write_char(')')
309
+ }
310
+ }
311
+
312
+ fn consume_operation_or_colon(input: &mut Parser) -> Result<Option<Operator>, ParseError> {
313
+ if input.try_parse(|input| input.expect_colon()).is_ok() {
314
+ return Ok(None);
315
+ }
316
+ Operator::parse(input).map(Some)
317
+ }
318
+
319
+ #[allow(unused_variables)]
320
+ fn disabled_by_pref(feature: &Atom, context: &ParserContext) -> bool {
321
+ #[cfg(feature = "gecko")]
322
+ {
323
+ // prefers-reduced-transparency is always enabled in the ua and chrome. On
324
+ // the web it is hidden behind a preference (see Bug 1822176).
325
+ if *feature == atom!("prefers-reduced-transparency") {
326
+ return !context.chrome_rules_enabled()
327
+ && !crate::pref!("layout.css.prefers-reduced-transparency.enabled");
328
+ }
329
+
330
+ // inverted-colors is always enabled in the ua and chrome. On
331
+ // the web it is hidden behind a preference.
332
+ if *feature == atom!("inverted-colors") {
333
+ return !context.chrome_rules_enabled()
334
+ && !crate::pref!("layout.css.inverted-colors.enabled");
335
+ }
336
+ }
337
+ false
338
+ }
339
+
340
+ impl QueryFeatureExpression {
341
+ fn new(
342
+ feature_type: FeatureType,
343
+ feature_index: usize,
344
+ kind: QueryFeatureExpressionKind,
345
+ ) -> Self {
346
+ debug_assert!(feature_index < feature_type.features().len());
347
+ Self {
348
+ feature_type,
349
+ feature_index,
350
+ kind,
351
+ }
352
+ }
353
+
354
+ fn write_name<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
355
+ where
356
+ W: fmt::Write,
357
+ {
358
+ let feature = self.feature();
359
+ if feature.flags.contains(FeatureFlags::WEBKIT_PREFIX) {
360
+ dest.write_str("-webkit-")?;
361
+ }
362
+
363
+ if let QueryFeatureExpressionKind::LegacyRange(range, _) = self.kind {
364
+ match range {
365
+ LegacyRange::Min => dest.write_str("min-")?,
366
+ LegacyRange::Max => dest.write_str("max-")?,
367
+ }
368
+ }
369
+
370
+ // NB: CssStringWriter not needed, feature names are under control.
371
+ write!(dest, "{}", feature.name)?;
372
+
373
+ Ok(())
374
+ }
375
+
376
+ fn feature(&self) -> &'static QueryFeatureDescription {
377
+ &self.feature_type.features()[self.feature_index]
378
+ }
379
+
380
+ /// Returns the feature flags for our feature.
381
+ pub fn feature_flags(&self) -> FeatureFlags {
382
+ self.feature().flags
383
+ }
384
+
385
+ fn parse_feature_name(
386
+ context: &ParserContext,
387
+ input: &mut Parser,
388
+ feature_type: FeatureType,
389
+ ) -> Result<(usize, Option<LegacyRange>), ParseError> {
390
+ let mut flags = FeatureFlags::empty();
391
+ let ident = input.expect_ident()?;
392
+
393
+ if context.chrome_rules_enabled() {
394
+ flags.insert(FeatureFlags::CHROME_AND_UA_ONLY);
395
+ }
396
+
397
+ let mut feature_name = &**ident;
398
+ if starts_with_ignore_ascii_case(feature_name, "-webkit-") {
399
+ feature_name = &feature_name[8..];
400
+ flags.insert(FeatureFlags::WEBKIT_PREFIX);
401
+ }
402
+
403
+ let range = if starts_with_ignore_ascii_case(feature_name, "min-") {
404
+ feature_name = &feature_name[4..];
405
+ Some(LegacyRange::Min)
406
+ } else if starts_with_ignore_ascii_case(feature_name, "max-") {
407
+ feature_name = &feature_name[4..];
408
+ Some(LegacyRange::Max)
409
+ } else {
410
+ None
411
+ };
412
+
413
+ let atom = Atom::from(string_as_ascii_lowercase(feature_name));
414
+ let (feature_index, feature) = match feature_type.find_feature(&atom) {
415
+ Some((i, f)) => (i, f),
416
+ None => {
417
+ return Err(ParseError::custom(
418
+ StyleParseErrorKind::MediaQueryExpectedFeatureName,
419
+ ))
420
+ },
421
+ };
422
+
423
+ if disabled_by_pref(&feature.name, context)
424
+ || !flags.contains(feature.flags.parsing_requirements())
425
+ || (range.is_some() && !feature.allows_ranges())
426
+ {
427
+ return Err(ParseError::custom(
428
+ StyleParseErrorKind::MediaQueryExpectedFeatureName,
429
+ ));
430
+ }
431
+
432
+ Ok((feature_index, range))
433
+ }
434
+
435
+ /// Parses the following range syntax:
436
+ ///
437
+ /// (feature-value <operator> feature-name)
438
+ /// (feature-value <operator> feature-name <operator> feature-value)
439
+ fn parse_multi_range_syntax(
440
+ context: &ParserContext,
441
+ input: &mut Parser,
442
+ feature_type: FeatureType,
443
+ ) -> Result<Self, ParseError> {
444
+ let start = input.state();
445
+
446
+ // To parse the values, we first need to find the feature name. We rely
447
+ // on feature values for ranged features not being able to be top-level
448
+ // <ident>s, which holds.
449
+ let feature_index = loop {
450
+ // NOTE: parse_feature_name advances the input.
451
+ if let Ok((index, range)) = Self::parse_feature_name(context, input, feature_type) {
452
+ if range.is_some() {
453
+ // Ranged names are not allowed here.
454
+ return Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError));
455
+ }
456
+ break index;
457
+ }
458
+ if input.is_exhausted() {
459
+ return Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError));
460
+ }
461
+ };
462
+
463
+ input.reset(&start);
464
+
465
+ let feature = &feature_type.features()[feature_index];
466
+ let left_val = QueryExpressionValue::parse(feature, context, input)?;
467
+ let left_op = Operator::parse(input)?;
468
+
469
+ {
470
+ let (parsed_index, _) = Self::parse_feature_name(context, input, feature_type)?;
471
+ debug_assert_eq!(
472
+ parsed_index, feature_index,
473
+ "How did we find a different feature?"
474
+ );
475
+ }
476
+
477
+ let right_op = input.try_parse(Operator::parse).ok();
478
+ let right = match right_op {
479
+ Some(op) => {
480
+ if !left_op.is_compatible_with(op) {
481
+ return Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError));
482
+ }
483
+ Some((op, QueryExpressionValue::parse(feature, context, input)?))
484
+ },
485
+ None => None,
486
+ };
487
+ Ok(Self::new(
488
+ feature_type,
489
+ feature_index,
490
+ QueryFeatureExpressionKind::Range {
491
+ left: Some((left_op, left_val)),
492
+ right,
493
+ },
494
+ ))
495
+ }
496
+
497
+ /// Parse a feature expression where we've already consumed the parenthesis.
498
+ pub fn parse_in_parenthesis_block(
499
+ context: &ParserContext,
500
+ input: &mut Parser,
501
+ feature_type: FeatureType,
502
+ ) -> Result<Self, ParseError> {
503
+ let (feature_index, range) =
504
+ match input.try_parse(|input| Self::parse_feature_name(context, input, feature_type)) {
505
+ Ok(v) => v,
506
+ Err(e) => {
507
+ if let Ok(expr) = Self::parse_multi_range_syntax(context, input, feature_type) {
508
+ return Ok(expr);
509
+ }
510
+ return Err(e);
511
+ },
512
+ };
513
+ let operator = input.try_parse(consume_operation_or_colon);
514
+ let operator = match operator {
515
+ Err(..) => {
516
+ // If there's no colon, this is a query of the form
517
+ // '(<feature>)', that is, there's no value specified.
518
+ //
519
+ // Gecko doesn't allow ranged expressions without a
520
+ // value, so just reject them here too.
521
+ if range.is_some() {
522
+ return Err(ParseError::custom(
523
+ StyleParseErrorKind::RangedExpressionWithNoValue,
524
+ ));
525
+ }
526
+
527
+ return Ok(Self::new(
528
+ feature_type,
529
+ feature_index,
530
+ QueryFeatureExpressionKind::Empty,
531
+ ));
532
+ },
533
+ Ok(operator) => operator,
534
+ };
535
+
536
+ let feature = &feature_type.features()[feature_index];
537
+
538
+ let value = QueryExpressionValue::parse(feature, context, input)
539
+ .map_err(|_| ParseError::custom(StyleParseErrorKind::MediaQueryExpectedFeatureValue))?;
540
+
541
+ let kind = match range {
542
+ Some(range) => {
543
+ if operator.is_some() {
544
+ return Err(ParseError::custom(
545
+ StyleParseErrorKind::MediaQueryUnexpectedOperator,
546
+ ));
547
+ }
548
+ QueryFeatureExpressionKind::LegacyRange(range, value)
549
+ },
550
+ None => match operator {
551
+ Some(operator) => {
552
+ if !feature.allows_ranges() {
553
+ return Err(ParseError::custom(
554
+ StyleParseErrorKind::MediaQueryUnexpectedOperator,
555
+ ));
556
+ }
557
+ QueryFeatureExpressionKind::Range {
558
+ left: None,
559
+ right: Some((operator, value)),
560
+ }
561
+ },
562
+ None => QueryFeatureExpressionKind::Single(value),
563
+ },
564
+ };
565
+
566
+ Ok(Self::new(feature_type, feature_index, kind))
567
+ }
568
+
569
+ /// Returns whether this "plain" feature query evaluates to true for the given device.
570
+ pub fn matches(&self, context: &computed::Context) -> KleeneValue {
571
+ macro_rules! expect {
572
+ ($variant:ident, $v:expr) => {
573
+ match *$v {
574
+ QueryExpressionValue::$variant(ref v) => v,
575
+ _ => unreachable!("Unexpected QueryExpressionValue"),
576
+ }
577
+ };
578
+ }
579
+
580
+ KleeneValue::from(match self.feature().evaluator {
581
+ Evaluator::Length(eval) => {
582
+ let v = eval(context);
583
+ self.kind
584
+ .evaluate(v, |v| expect!(Length, v).to_computed_value(context))
585
+ },
586
+ Evaluator::OptionalLength(eval) => {
587
+ let v = match eval(context) {
588
+ Some(v) => v,
589
+ None => return KleeneValue::Unknown,
590
+ };
591
+ self.kind
592
+ .evaluate(v, |v| expect!(Length, v).to_computed_value(context))
593
+ },
594
+ Evaluator::Integer(eval) => {
595
+ let v = eval(context);
596
+ self.kind
597
+ .evaluate(v, |v| expect!(Integer, v).to_computed_value(context))
598
+ },
599
+ Evaluator::Float(eval) => {
600
+ let v = eval(context);
601
+ self.kind
602
+ .evaluate(v, |v| expect!(Float, v).to_computed_value(context))
603
+ },
604
+ Evaluator::NumberRatio(eval) => {
605
+ let ratio = eval(context);
606
+ // A ratio of 0/0 behaves as the ratio 1/0, so we need to call used_value()
607
+ // to convert it if necessary.
608
+ // FIXME: we may need to update here once
609
+ // https://github.com/w3c/csswg-drafts/issues/4954 got resolved.
610
+ self.kind.evaluate(ratio, |v| {
611
+ expect!(NumberRatio, v)
612
+ .to_computed_value(context)
613
+ .used_value()
614
+ })
615
+ },
616
+ Evaluator::OptionalNumberRatio(eval) => {
617
+ let ratio = match eval(context) {
618
+ Some(v) => v,
619
+ None => return KleeneValue::Unknown,
620
+ };
621
+ // See above for subtleties here.
622
+ self.kind.evaluate(ratio, |v| {
623
+ expect!(NumberRatio, v)
624
+ .to_computed_value(context)
625
+ .used_value()
626
+ })
627
+ },
628
+ Evaluator::Resolution(eval) => {
629
+ let v = eval(context).dppx();
630
+ self.kind.evaluate(v, |v| {
631
+ expect!(Resolution, v).to_computed_value(context).dppx()
632
+ })
633
+ },
634
+ Evaluator::Enumerated { evaluator, .. } => {
635
+ let computed = self
636
+ .kind
637
+ .non_ranged_value()
638
+ .map(|v| *expect!(Enumerated, v));
639
+ return evaluator(context, computed);
640
+ },
641
+ Evaluator::BoolInteger(eval) => {
642
+ let computed = self
643
+ .kind
644
+ .non_ranged_value()
645
+ .map(|v| expect!(BoolInteger, v).to_computed_value(context));
646
+ let boolean = eval(context);
647
+ computed.map_or(boolean, |v| v == boolean as i32)
648
+ },
649
+ })
650
+ }
651
+ }
652
+
653
+ /// A value found or expected in a expression.
654
+ ///
655
+ /// FIXME(emilio): How should calc() serialize in the Number / Integer /
656
+ /// BoolInteger / NumberRatio case, as computed or as specified value?
657
+ ///
658
+ /// If the first, this would need to store the relevant values.
659
+ ///
660
+ /// See: https://github.com/w3c/csswg-drafts/issues/1968
661
+ #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
662
+ pub enum QueryExpressionValue {
663
+ /// A length.
664
+ Length(Length),
665
+ /// An integer.
666
+ Integer(Integer),
667
+ /// A floating point value.
668
+ Float(Number),
669
+ /// A boolean value, specified as an integer (i.e., either 0 or 1).
670
+ BoolInteger(Integer),
671
+ /// A single non-negative number or two non-negative numbers separated by '/',
672
+ /// with optional whitespace on either side of the '/'.
673
+ NumberRatio(Ratio),
674
+ /// A resolution.
675
+ Resolution(Resolution),
676
+ /// An enumerated value, defined by the variant keyword table in the
677
+ /// feature's `mData` member.
678
+ Enumerated(KeywordDiscriminant),
679
+ /// Value types only used by style-range query expressions, not feature queries.
680
+ /// A CSS-wide keyword.
681
+ Keyword(CSSWideKeyword),
682
+ /// A percentage.
683
+ Percentage(Percentage),
684
+ /// An angle.
685
+ Angle(Angle),
686
+ /// A time value.
687
+ Time(Time),
688
+ /// A custom property name.
689
+ Custom(DashedIdent),
690
+ /// An arbitrary substitution function (var(), attr(), env()), stored as a string
691
+ /// for later evaluation. We store this as a custom-property value to make it easy
692
+ /// to resolve later.
693
+ Function(Box<CustomVariableValue>),
694
+ }
695
+
696
+ impl QueryExpressionValue {
697
+ fn to_css<W>(
698
+ &self,
699
+ dest: &mut CssWriter<W>,
700
+ for_expr: Option<&QueryFeatureExpression>,
701
+ ) -> fmt::Result
702
+ where
703
+ W: fmt::Write,
704
+ {
705
+ match *self {
706
+ QueryExpressionValue::Length(ref l) => l.to_css(dest),
707
+ QueryExpressionValue::Integer(ref v) => v.to_css(dest),
708
+ QueryExpressionValue::Float(ref v) => v.to_css(dest),
709
+ QueryExpressionValue::BoolInteger(ref v) => v.to_css(dest),
710
+ QueryExpressionValue::NumberRatio(ref ratio) => ratio.to_css(dest),
711
+ QueryExpressionValue::Resolution(ref r) => r.to_css(dest),
712
+ QueryExpressionValue::Keyword(k) => k.to_css(dest),
713
+ QueryExpressionValue::Percentage(ref v) => v.to_css(dest),
714
+ QueryExpressionValue::Angle(ref v) => v.to_css(dest),
715
+ QueryExpressionValue::Time(ref v) => v.to_css(dest),
716
+ QueryExpressionValue::Custom(ref v) => v.to_css(dest),
717
+ QueryExpressionValue::Function(ref f) => f.to_css(dest),
718
+ QueryExpressionValue::Enumerated(value) => match for_expr
719
+ .expect("caller should have passed for_expr")
720
+ .feature()
721
+ .evaluator
722
+ {
723
+ Evaluator::Enumerated { serializer, .. } => dest.write_str(&serializer(value)),
724
+ _ => unreachable!(),
725
+ },
726
+ }
727
+ }
728
+
729
+ fn parse(
730
+ for_feature: &QueryFeatureDescription,
731
+ context: &ParserContext,
732
+ input: &mut Parser,
733
+ ) -> Result<QueryExpressionValue, ParseError> {
734
+ Ok(match for_feature.evaluator {
735
+ Evaluator::OptionalLength(..) | Evaluator::Length(..) => {
736
+ let length = Length::parse(context, input)?;
737
+ QueryExpressionValue::Length(length)
738
+ },
739
+ Evaluator::Integer(..) => {
740
+ let integer = Integer::parse(context, input)?;
741
+ QueryExpressionValue::Integer(integer)
742
+ },
743
+ Evaluator::BoolInteger(..) => {
744
+ let integer = Integer::parse(context, input)?;
745
+ if matches!(integer.resolve(), Some(v) if v != 0 && v != 1) {
746
+ return Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError));
747
+ }
748
+ QueryExpressionValue::BoolInteger(integer)
749
+ },
750
+ Evaluator::Float(..) => {
751
+ let number = Number::parse(context, input)?;
752
+ QueryExpressionValue::Float(number)
753
+ },
754
+ Evaluator::OptionalNumberRatio(..) | Evaluator::NumberRatio(..) => {
755
+ use crate::values::specified::Ratio as SpecifiedRatio;
756
+ let ratio = SpecifiedRatio::parse(context, input)?;
757
+ QueryExpressionValue::NumberRatio(ratio)
758
+ },
759
+ Evaluator::Resolution(..) => {
760
+ QueryExpressionValue::Resolution(Resolution::parse(context, input)?)
761
+ },
762
+ Evaluator::Enumerated { parser, .. } => {
763
+ QueryExpressionValue::Enumerated(parser(context, input)?)
764
+ },
765
+ })
766
+ }
767
+
768
+ // Parse any of the types that can occur in a <style-range> query:
769
+ // <number>, <percentage>, <length>, <angle>, <time>, <frequency> or <resolution>,
770
+ // or a custom property name.
771
+ // NB: we don't currently implement the <frequency> type anywhere, so it is not
772
+ // parsed here.
773
+ fn parse_for_style_range(
774
+ context: &ParserContext,
775
+ input: &mut Parser,
776
+ ) -> Result<Self, ParseError> {
777
+ if let Ok(number) = input.try_parse(|i| Number::parse(context, i)) {
778
+ return Ok(Self::Float(number));
779
+ }
780
+ if let Ok(percent) = input.try_parse(|i| Percentage::parse(context, i)) {
781
+ return Ok(Self::Percentage(percent));
782
+ }
783
+ if let Ok(length) = input.try_parse(|i| Length::parse(context, i)) {
784
+ return Ok(Self::Length(length));
785
+ }
786
+ if let Ok(angle) = input.try_parse(|i| Angle::parse(context, i)) {
787
+ return Ok(Self::Angle(angle));
788
+ }
789
+ if let Ok(time) = input.try_parse(|i| Time::parse(context, i)) {
790
+ return Ok(Self::Time(time));
791
+ }
792
+ if let Ok(resolution) = input.try_parse(|i| Resolution::parse(context, i)) {
793
+ return Ok(Self::Resolution(resolution));
794
+ }
795
+ if let Ok(ident) = input.try_parse(|i| DashedIdent::parse(context, i)) {
796
+ return Ok(Self::Custom(ident));
797
+ }
798
+ if let Ok(keyword) = input.try_parse(|i| CSSWideKeyword::parse(i)) {
799
+ return Ok(Self::Keyword(keyword));
800
+ }
801
+ input.skip_whitespace();
802
+ let start = input.position();
803
+ if let Ok(Token::Function(name)) = input.next() {
804
+ // Helper to parse the function arg and store the complete expression (function
805
+ // name and parenthesized argument) into a CustomVariableValue.
806
+ let parse_func = |input: &mut Parser| -> Result<CustomVariableValue, ParseError> {
807
+ input.parse_nested_block(|i| i.expect_no_error_token().map_err(Into::into))?;
808
+ CustomVariableValue::parse(
809
+ &mut Parser::new(input.slice_from(start)),
810
+ Some(&context.namespaces.prefixes),
811
+ context.url_data,
812
+ )
813
+ };
814
+
815
+ if SubstitutionFunctionKind::from_ident(name).is_ok() {
816
+ return Ok(Self::Function(Box::new(parse_func(input)?)));
817
+ }
818
+ }
819
+ Err(ParseError::custom(StyleParseErrorKind::UnspecifiedError))
820
+ }
821
+
822
+ fn collect_attribute_references(&self, references: &mut AttrReferenceSet) {
823
+ if let Self::Function(f) = self {
824
+ f.collect_attribute_references(references)
825
+ }
826
+ }
827
+ }
828
+
829
+ /// https://drafts.csswg.org/css-conditional-5/#typedef-style-range
830
+ #[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)]
831
+ pub enum QueryStyleRange {
832
+ /// A style-range for style container queries with two values
833
+ /// (val1 OP val2).
834
+ #[allow(missing_docs)]
835
+ StyleRange2 {
836
+ value1: QueryExpressionValue,
837
+ op1: Operator,
838
+ value2: QueryExpressionValue,
839
+ },
840
+
841
+ /// A style-range for style container queries with three values
842
+ /// (val1 OP val2 OP val3).
843
+ #[allow(missing_docs)]
844
+ StyleRange3 {
845
+ value1: QueryExpressionValue,
846
+ op1: Operator,
847
+ value2: QueryExpressionValue,
848
+ op2: Operator,
849
+ value3: QueryExpressionValue,
850
+ },
851
+ }
852
+
853
+ impl ToCss for QueryStyleRange {
854
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
855
+ where
856
+ W: fmt::Write,
857
+ {
858
+ match self {
859
+ Self::StyleRange2 {
860
+ value1,
861
+ op1,
862
+ value2,
863
+ } => {
864
+ value1.to_css(dest, None)?;
865
+ dest.write_char(' ')?;
866
+ op1.to_css(dest)?;
867
+ dest.write_char(' ')?;
868
+ value2.to_css(dest, None)
869
+ },
870
+ Self::StyleRange3 {
871
+ value1,
872
+ op1,
873
+ value2,
874
+ op2,
875
+ value3,
876
+ } => {
877
+ value1.to_css(dest, None)?;
878
+ dest.write_char(' ')?;
879
+ op1.to_css(dest)?;
880
+ dest.write_char(' ')?;
881
+ value2.to_css(dest, None)?;
882
+ dest.write_char(' ')?;
883
+ op2.to_css(dest)?;
884
+ dest.write_char(' ')?;
885
+ value3.to_css(dest, None)
886
+ },
887
+ }
888
+ }
889
+ }
890
+
891
+ impl QueryStyleRange {
892
+ /// Parses the following range syntax:
893
+ ///
894
+ /// value <operator> value
895
+ /// value <operator> value <operator> value
896
+ ///
897
+ /// This is only used when parsing @container style() queries; the feature_type
898
+ /// and index is hardcoded (and ignored).
899
+ pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Self, ParseError> {
900
+ let value1 = QueryExpressionValue::parse_for_style_range(context, input)?;
901
+ let op1 = Operator::parse(input)?;
902
+ let value2 = QueryExpressionValue::parse_for_style_range(context, input)?;
903
+
904
+ if let Ok(op2) = input.try_parse(|i| Operator::parse(i)) {
905
+ if op1.is_compatible_with(op2) {
906
+ let value3 = QueryExpressionValue::parse_for_style_range(context, input)?;
907
+ return Ok(Self::StyleRange3 {
908
+ value1,
909
+ op1,
910
+ value2,
911
+ op2,
912
+ value3,
913
+ });
914
+ }
915
+ }
916
+
917
+ Ok(Self::StyleRange2 {
918
+ value1,
919
+ op1,
920
+ value2,
921
+ })
922
+ }
923
+
924
+ /// Returns whether this style-range query evaluates to true for the given context.
925
+ pub fn evaluate(
926
+ &self,
927
+ context: &computed::Context,
928
+ attribute_tracker: &mut AttributeTracker,
929
+ ) -> KleeneValue {
930
+ match self {
931
+ QueryStyleRange::StyleRange2 {
932
+ value1,
933
+ op1,
934
+ value2,
935
+ } => Self::compare_values(
936
+ Self::resolve_value(
937
+ value1,
938
+ context,
939
+ attribute_tracker,
940
+ &mut PrecomputedHashSet::default(),
941
+ )
942
+ .as_ref(),
943
+ Self::resolve_value(
944
+ value2,
945
+ context,
946
+ attribute_tracker,
947
+ &mut PrecomputedHashSet::default(),
948
+ )
949
+ .as_ref(),
950
+ )
951
+ .is_some_and(|c| op1.evaluate(c))
952
+ .into(),
953
+
954
+ QueryStyleRange::StyleRange3 {
955
+ value1,
956
+ op1,
957
+ value2,
958
+ op2,
959
+ value3,
960
+ } => {
961
+ let v1 = Self::resolve_value(
962
+ value1,
963
+ context,
964
+ attribute_tracker,
965
+ &mut PrecomputedHashSet::default(),
966
+ );
967
+ let v2 = Self::resolve_value(
968
+ value2,
969
+ context,
970
+ attribute_tracker,
971
+ &mut PrecomputedHashSet::default(),
972
+ );
973
+ Self::compare_values(v1.as_ref(), v2.as_ref())
974
+ .is_some_and(|c1| {
975
+ op1.evaluate(c1)
976
+ && Self::compare_values(
977
+ v2.as_ref(),
978
+ Self::resolve_value(
979
+ value3,
980
+ context,
981
+ attribute_tracker,
982
+ &mut PrecomputedHashSet::default(),
983
+ )
984
+ .as_ref(),
985
+ )
986
+ .is_some_and(|c2| op2.evaluate(c2))
987
+ })
988
+ .into()
989
+ },
990
+ }
991
+ }
992
+
993
+ // Resolve a QueryExpressionValue to its computed value for comparison.
994
+ fn resolve_value(
995
+ value: &QueryExpressionValue,
996
+ context: &computed::Context,
997
+ attribute_tracker: &mut AttributeTracker,
998
+ visited_set: &mut PrecomputedHashSet<DashedIdent>,
999
+ ) -> Option<Component> {
1000
+ match value {
1001
+ QueryExpressionValue::Custom(ident) => {
1002
+ // `ident` is the dashed ident, but we need the name
1003
+ // without "--" for custom-property lookup.
1004
+ let name = ident.undashed();
1005
+ let stylist = context
1006
+ .builder
1007
+ .stylist
1008
+ .expect("container queries should have a stylist around");
1009
+ let registration = stylist.get_custom_property_registration(&name);
1010
+ let current_value = context
1011
+ .inherited_custom_properties()
1012
+ .get(registration, &name)?;
1013
+ match &current_value.v {
1014
+ ValueInner::Component(component) => Some(component.clone()),
1015
+ ValueInner::Universal(v) => {
1016
+ // If visited_set.insert() returns false, ident was already seen
1017
+ // and we risk infinite recursion, so instead return None
1018
+ // (i.e. the value cannot be resolved).
1019
+ if visited_set.insert(ident.clone()) {
1020
+ Self::resolve_universal(
1021
+ &v.css,
1022
+ &v.url_data,
1023
+ context,
1024
+ attribute_tracker,
1025
+ visited_set,
1026
+ )
1027
+ } else {
1028
+ None
1029
+ }
1030
+ },
1031
+ ValueInner::List(_) => {
1032
+ debug_assert!(false, "We don't parse list values in style queries");
1033
+ None
1034
+ },
1035
+ }
1036
+ },
1037
+ QueryExpressionValue::Function(value) => {
1038
+ let sub_funcs = ComputedSubstitutionFunctions::new(
1039
+ Some(context.inherited_custom_properties().clone()),
1040
+ None,
1041
+ );
1042
+ let stylist = context
1043
+ .builder
1044
+ .stylist
1045
+ .expect("container queries should have a stylist around");
1046
+ let substituted = custom_properties::substitute(
1047
+ value,
1048
+ &sub_funcs,
1049
+ stylist,
1050
+ context,
1051
+ attribute_tracker,
1052
+ )
1053
+ .ok()?;
1054
+ Self::resolve_universal(
1055
+ &substituted.css,
1056
+ &value.url_data,
1057
+ context,
1058
+ attribute_tracker,
1059
+ visited_set,
1060
+ )
1061
+ },
1062
+ QueryExpressionValue::Length(v) => {
1063
+ Some(Component::Length(v.to_computed_value(context)))
1064
+ },
1065
+ QueryExpressionValue::Float(v) => Some(Component::Number(v.to_computed_value(context))),
1066
+ QueryExpressionValue::Resolution(v) => {
1067
+ Some(Component::Resolution(v.to_computed_value(context)))
1068
+ },
1069
+ QueryExpressionValue::Percentage(v) => {
1070
+ Some(Component::Percentage(v.to_computed_value(context)))
1071
+ },
1072
+ QueryExpressionValue::Angle(v) => Some(Component::Angle(v.to_computed_value(context))),
1073
+ QueryExpressionValue::Time(v) => Some(Component::Time(v.to_computed_value(context))),
1074
+ // It's unclear to me what CSS-wide keywords would mean in a style-range query;
1075
+ // for now, at least, they'll just fail to resolve.
1076
+ QueryExpressionValue::Keyword(_) => None,
1077
+ _ => {
1078
+ debug_assert!(false, "unexpected value type in style range");
1079
+ None
1080
+ },
1081
+ }
1082
+ }
1083
+
1084
+ // If a custom-property QueryExpressionValue has a "universal-syntax" value, we need to
1085
+ // send the current CSS text of the value to QueryExpressionValue::parse_for_style_range
1086
+ // to try and resolve to a specific typed value.
1087
+ // After parsing, this will call back to QueryExpressionValue::resolve_value with the
1088
+ // parsed result, which has the potential for mutual recursion; we keep track of a
1089
+ // visited_set of custom property names to protect against this.
1090
+ fn resolve_universal(
1091
+ css_text: &str,
1092
+ url_data: &UrlExtraData,
1093
+ context: &computed::Context,
1094
+ attribute_tracker: &mut AttributeTracker,
1095
+ visited_set: &mut PrecomputedHashSet<DashedIdent>,
1096
+ ) -> Option<Component> {
1097
+ let parser_context = ParserContext::new(
1098
+ Origin::Author,
1099
+ url_data,
1100
+ Some(CssRuleType::Container),
1101
+ ParsingMode::DEFAULT,
1102
+ QuirksMode::NoQuirks,
1103
+ /* namespaces = */ Default::default(),
1104
+ /* error_reporter = */ None,
1105
+ /* use_counters = */ None,
1106
+ /* attr_taint */ Default::default(),
1107
+ );
1108
+ QueryExpressionValue::parse_for_style_range(&parser_context, &mut Parser::new(css_text))
1109
+ .ok()
1110
+ .and_then(|parsed| {
1111
+ Self::resolve_value(&parsed, context, attribute_tracker, visited_set)
1112
+ })
1113
+ }
1114
+
1115
+ fn compare_values(value1: Option<&Component>, value2: Option<&Component>) -> Option<Ordering> {
1116
+ let value1 = value1?;
1117
+ let value2 = value2?;
1118
+ match (value1, value2) {
1119
+ (Component::Length(v1), Component::Length(v2)) => v1.partial_cmp(v2),
1120
+ (Component::Number(v1), Component::Number(v2)) => v1.partial_cmp(v2),
1121
+ (Component::Resolution(v1), Component::Resolution(v2)) => {
1122
+ v1.dppx().partial_cmp(&v2.dppx())
1123
+ },
1124
+ (Component::Percentage(v1), Component::Percentage(v2)) => v1.partial_cmp(v2),
1125
+ (Component::Angle(v1), Component::Angle(v2)) => v1.partial_cmp(v2),
1126
+ (Component::Time(v1), Component::Time(v2)) => v1.partial_cmp(v2),
1127
+ (Component::Length(v1), Component::Number(v2)) => {
1128
+ if v2.is_zero() {
1129
+ v1.partial_cmp(&CSSPixelLength::zero())
1130
+ } else {
1131
+ None
1132
+ }
1133
+ },
1134
+ (Component::Number(v1), Component::Length(v2)) => {
1135
+ if v1.is_zero() {
1136
+ CSSPixelLength::zero().partial_cmp(v2)
1137
+ } else {
1138
+ None
1139
+ }
1140
+ },
1141
+ _ => None,
1142
+ }
1143
+ }
1144
+
1145
+ /// Get all the attributes referenced inside of an attr() function within
1146
+ /// all our QueryExpressionValues.
1147
+ pub fn collect_attribute_references(&self, references: &mut AttrReferenceSet) {
1148
+ match self {
1149
+ QueryStyleRange::StyleRange2 {
1150
+ value1,
1151
+ op1: _,
1152
+ value2,
1153
+ } => {
1154
+ value1.collect_attribute_references(references);
1155
+ value2.collect_attribute_references(references);
1156
+ },
1157
+ QueryStyleRange::StyleRange3 {
1158
+ value1,
1159
+ op1: _,
1160
+ value2,
1161
+ op2: _,
1162
+ value3,
1163
+ } => {
1164
+ value1.collect_attribute_references(references);
1165
+ value2.collect_attribute_references(references);
1166
+ value3.collect_attribute_references(references);
1167
+ },
1168
+ }
1169
+ }
1170
+ }