mod.rs 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044
  1. //! A module to type styles.
  2. // TODO most stuff here is on the stack, but there are a few heap-allocs here and there. It would
  3. // be good if we could just to allocate them in the bump arena when using bumpalo.
  4. mod calc;
  5. mod codegen;
  6. mod color;
  7. pub mod string;
  8. mod syn_parse;
  9. use std::{
  10. fmt,
  11. ops::{Deref, DerefMut},
  12. };
  13. pub use calc::*;
  14. pub use color::{Color, DynamicColor};
  15. // pub use crate::{
  16. // calc::*,
  17. // color::{Color, DynamicColor},
  18. // };
  19. pub struct DynamicStyles {
  20. pub rules: Vec<DynamicStyle>,
  21. }
  22. impl From<Vec<DynamicStyle>> for DynamicStyles {
  23. fn from(v: Vec<DynamicStyle>) -> Self {
  24. Self { rules: v }
  25. }
  26. }
  27. impl fmt::Display for DynamicStyles {
  28. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  29. for style in self
  30. .rules
  31. .iter()
  32. .filter(|style| !(style.is_dynamic() || style.is_dummy()))
  33. {
  34. write!(f, "{};", style)?;
  35. }
  36. Ok(())
  37. }
  38. }
  39. // TODO make container generic over heap (e.g. support bumpalo)
  40. #[derive(Debug, Clone, PartialEq)]
  41. pub struct Styles {
  42. pub rules: Vec<Style>,
  43. }
  44. impl Styles {
  45. pub fn new() -> Self {
  46. Styles { rules: Vec::new() }
  47. }
  48. pub fn add(&mut self, style: Style) {
  49. self.rules.push(style);
  50. }
  51. pub fn merge(&mut self, other: Styles) {
  52. self.rules.extend(other.rules.into_iter())
  53. }
  54. }
  55. impl From<DynamicStyles> for Styles {
  56. fn from(dy: DynamicStyles) -> Self {
  57. Styles {
  58. rules: dy
  59. .rules
  60. .into_iter()
  61. .filter_map(|dy_sty| match dy_sty {
  62. DynamicStyle::Dynamic(_) => None,
  63. DynamicStyle::Literal(l) => Some(l),
  64. })
  65. .collect(),
  66. }
  67. }
  68. }
  69. impl Deref for Styles {
  70. type Target = Vec<Style>;
  71. fn deref(&self) -> &Self::Target {
  72. &self.rules
  73. }
  74. }
  75. impl DerefMut for Styles {
  76. fn deref_mut(&mut self) -> &mut Self::Target {
  77. &mut self.rules
  78. }
  79. }
  80. impl From<Vec<Style>> for Styles {
  81. fn from(v: Vec<Style>) -> Self {
  82. Self { rules: v }
  83. }
  84. }
  85. impl From<Styles> for Vec<Style> {
  86. fn from(v: Styles) -> Self {
  87. v.rules
  88. }
  89. }
  90. impl fmt::Display for Styles {
  91. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  92. for style in self.rules.iter().filter(|style| !style.is_dummy()) {
  93. write!(f, "{};", style)?;
  94. }
  95. Ok(())
  96. }
  97. }
  98. #[derive(Debug, Clone, PartialEq)]
  99. pub enum DynamicStyle {
  100. /// A literal style.
  101. Literal(Style),
  102. /// Tokens to pass through directly to codegen.
  103. Dynamic(syn::Block),
  104. }
  105. impl DynamicStyle {
  106. pub fn is_dynamic(&self) -> bool {
  107. match self {
  108. DynamicStyle::Literal(style) => style.is_dynamic(),
  109. DynamicStyle::Dynamic(_) => true,
  110. }
  111. }
  112. pub fn is_dummy(&self) -> bool {
  113. match self {
  114. DynamicStyle::Literal(style) => style.is_dummy(),
  115. DynamicStyle::Dynamic(_) => false,
  116. }
  117. }
  118. }
  119. impl From<Style> for DynamicStyle {
  120. fn from(style: Style) -> Self {
  121. DynamicStyle::Literal(style)
  122. }
  123. }
  124. impl fmt::Display for DynamicStyle {
  125. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  126. match self {
  127. DynamicStyle::Literal(style) => style.fmt(f),
  128. DynamicStyle::Dynamic(_) => Ok(()),
  129. }
  130. }
  131. }
  132. /// a `Style` is one of the css key/value pairs, also sometimes known as rules.
  133. #[derive(Debug, Clone, PartialEq)]
  134. #[non_exhaustive]
  135. pub enum Style {
  136. /// For when you don't want to include any style at all (useful in expressions like `if`)
  137. Dummy,
  138. /// For when you want to use some unimplemented css. This is not type checked!
  139. Unchecked(String),
  140. // *From w3 spec:*
  141. /// align-content
  142. AlignContent(AlignContent),
  143. /// align-items
  144. AlignItems(AlignItems),
  145. /// align-self
  146. AlignSelf(AlignSelf),
  147. // all - todo when doing global values
  148. // background
  149. /// background-attachment
  150. BackgroundAttachment(BackgroundAttachment),
  151. /// background-blend-mode
  152. BackgroundBlendMode(NonemptyCommaList<BlendMode>),
  153. /// background-clip
  154. BackgroundClip(BackgroundBox),
  155. /// background-color
  156. BackgroundColor(DynamicColor),
  157. /// background-image
  158. BackgroundImage(NonemptyCommaList<BackgroundImage>),
  159. /// background-origin
  160. BackgroundOrigin(BackgroundBox),
  161. /// background-position
  162. BackgroundPosition(BackgroundPosition),
  163. /// background-repeat
  164. BackgroundRepeat(NonemptyCommaList<BackgroundRepeat>),
  165. /// background-size
  166. BackgroundSize(BackgroundSize),
  167. /// border
  168. Border(Border),
  169. /// border-bottom
  170. BorderBottom(Border),
  171. /// border-bottom-color
  172. BorderBottomColor(Color),
  173. /// border-bottom-left-radius
  174. BorderBottomLeftRadius(SingleOrDouble<LengthPercentage>),
  175. /// border-bottom-right-radius
  176. BorderBottomRightRadius(SingleOrDouble<LengthPercentage>),
  177. /// border-bottom-style
  178. BorderBottomStyle(LineStyle),
  179. /// border-bottom-width
  180. BorderBottomWidth(LineWidth),
  181. /// border-collapse
  182. BorderCollapse(BorderCollapse),
  183. /// border-color
  184. BorderColor(Rect<Color>),
  185. // border-image
  186. // border-image-outset
  187. // border-image-repeat
  188. // border-image-slice
  189. // border-image-source
  190. // border-image-width
  191. /// border-left
  192. BorderLeft(Border),
  193. /// border-left-color
  194. BorderLeftColor(Color),
  195. /// border-left-style
  196. BorderLeftStyle(LineStyle),
  197. /// border-left-width
  198. BorderLeftWidth(LineWidth),
  199. /// border-radius
  200. BorderRadius(BorderRadius),
  201. /// border-right
  202. BorderRight(Border),
  203. /// border-right-color
  204. BorderRightColor(Color),
  205. /// border-right-style
  206. BorderRightStyle(LineStyle),
  207. /// border-right-width
  208. BorderRightWidth(LineWidth),
  209. // border-spacing
  210. /// border-style
  211. BorderStyle(BorderStyle),
  212. /// border-top
  213. BorderTop(Border),
  214. /// border-top-color
  215. BorderTopColor(Color),
  216. /// border-top-left-radius
  217. BorderTopLeftRadius(SingleOrDouble<LengthPercentage>),
  218. /// border-top-right-radius
  219. BorderTopRightRadius(SingleOrDouble<LengthPercentage>),
  220. /// border-top-style
  221. BorderTopStyle(LineStyle),
  222. /// border-top-width
  223. BorderTopWidth(LineWidth),
  224. /// border-width
  225. BorderWidth(BorderWidth),
  226. /// bottom
  227. Bottom(AutoLengthPercentage),
  228. // box-decoration-break
  229. /// box-shadow
  230. BoxShadow(BoxShadow),
  231. /// box-sizing
  232. BoxSizing(BoxSizing),
  233. // break-after
  234. // break-before
  235. // break-inside
  236. // caption-side
  237. // caret-color
  238. /// clear
  239. Clear(Clear),
  240. // clip
  241. // clip-path
  242. // clip-rule
  243. /// color
  244. Color(DynamicColor),
  245. /// column-count (manually added)
  246. ColumnCount(ColumnCount),
  247. // contain
  248. // content
  249. // counter-increment
  250. // counter-reset
  251. // cue
  252. // cue-after
  253. // cue-before
  254. /// cursor
  255. Cursor(Cursor),
  256. // direction
  257. /// display https://www.w3.org/TR/css-display-3/#typedef-display-outside
  258. Display(Display),
  259. // elevation
  260. // empty-cells
  261. // flex
  262. /// flex-basis
  263. FlexBasis(FlexBasis),
  264. /// flex-direction
  265. FlexDirection(FlexDirection),
  266. // flex-flow
  267. /// flex-grow
  268. FlexGrow(f64),
  269. /// flex-shrink
  270. FlexShrink(f64),
  271. /// flex-wrap
  272. FlexWrap(FlexWrap),
  273. /// float
  274. Float(Float),
  275. // font
  276. /// font-family
  277. FontFamily(FontFamily),
  278. // font-feature-settings
  279. // font-kerning
  280. /// font-size
  281. FontSize(FontSize),
  282. // font-size-adjust
  283. // font-stretch
  284. /// font-style
  285. FontStyle(FontStyle),
  286. // font-synthesis
  287. // font-variant
  288. // font-variant-caps
  289. // font-variant-east-asian
  290. // font-variant-ligatures
  291. // font-variant-numeric
  292. // font-variant-position
  293. /// font-weight
  294. FontWeight(FontWeight),
  295. // glyph-orientation-vertical
  296. // grid
  297. // grid-area
  298. // grid-auto-columns
  299. // grid-auto-flow
  300. // grid-auto-rows
  301. // grid-column
  302. // grid-column-end
  303. // grid-column-start
  304. // grid-row
  305. // grid-row-end
  306. // grid-row-start
  307. // grid-template
  308. // grid-template-areas
  309. // grid-template-columns
  310. // grid-template-rows
  311. /// height
  312. Height(WidthHeight),
  313. // image-orientation
  314. // image-rendering
  315. // isolation
  316. /// justify-content
  317. JustifyContent(JustifyContent),
  318. /// left
  319. Left(AutoLengthPercentage),
  320. // letter-spacing
  321. /// line-height
  322. LineHeight(LineHeight),
  323. // list-style
  324. // list-style-image
  325. // list-style-position
  326. /// list-style-type
  327. ListStyleType(ListStyleType),
  328. /// margin
  329. Margin(Margin),
  330. /// margin-bottom
  331. MarginBottom(MarginWidth),
  332. /// margin-left
  333. MarginLeft(MarginWidth),
  334. /// margin-right
  335. MarginRight(MarginWidth),
  336. /// margin-top
  337. MarginTop(MarginWidth),
  338. // mask
  339. // mask-border
  340. // mask-border-mode
  341. // mask-border-outset
  342. // mask-border-repeat
  343. // mask-border-slice
  344. // mask-border-source
  345. // mask-border-width
  346. // mask-clip
  347. // mask-composite
  348. // mask-image
  349. // mask-mode
  350. // mask-origin
  351. // mask-position
  352. // mask-repeat
  353. // mask-size
  354. // mask-type
  355. /// max-height
  356. MaxHeight(MaxWidthHeight),
  357. /// max-width
  358. MaxWidth(MaxWidthHeight),
  359. /// min-height - current implementing CSS2 spec
  360. MinHeight(Calc),
  361. /// min-width - current implementing CSS2 spec
  362. MinWidth(Calc),
  363. // mix-blend-mode
  364. /// object-fit - https://drafts.csswg.org/css-images-4/#the-object-fit
  365. ObjectFit(ObjectFit),
  366. // object-position
  367. // opacity
  368. // order
  369. // orphans
  370. // outline
  371. // outline-color
  372. // outline-offset
  373. // outline-style
  374. // outline-width
  375. /// overflow - https://drafts.csswg.org/css-overflow-3/#propdef-overflow
  376. Overflow(Overflow),
  377. /// overflow-x manually added
  378. OverflowX(OverflowXY),
  379. /// overflow-y manually added
  380. OverflowY(OverflowXY),
  381. /// padding
  382. Padding(Padding),
  383. /// padding-bottom
  384. PaddingBottom(PaddingWidth),
  385. /// padding-left
  386. PaddingLeft(PaddingWidth),
  387. /// padding-right
  388. PaddingRight(PaddingWidth),
  389. /// padding-top
  390. PaddingTop(PaddingWidth),
  391. // page-break-after
  392. // page-break-before
  393. // page-break-inside
  394. // pause
  395. // pause-after
  396. // pause-before
  397. // pitch
  398. // pitch-range
  399. // play-during
  400. /// position
  401. Position(Position),
  402. // quotes
  403. /// resize
  404. Resize(Resize),
  405. // richness
  406. /// right
  407. Right(AutoLengthPercentage),
  408. // scroll-margin
  409. // scroll-margin-block
  410. // scroll-margin-block-end
  411. // scroll-margin-block-start
  412. // scroll-margin-bottom
  413. // scroll-margin-inline
  414. // scroll-margin-inline-end
  415. // scroll-margin-inline-start
  416. // scroll-margin-left
  417. // scroll-margin-right
  418. // scroll-margin-top
  419. // scroll-padding
  420. // scroll-padding-block
  421. // scroll-padding-block-end
  422. // scroll-padding-block-start
  423. // scroll-padding-bottom
  424. // scroll-padding-inline
  425. // scroll-padding-inline-end
  426. // scroll-padding-inline-start
  427. // scroll-padding-left
  428. // scroll-padding-right
  429. // scroll-padding-top
  430. // scroll-snap-align
  431. // scroll-snap-stop
  432. // scroll-snap-type
  433. // shape-image-threshold
  434. // shape-margin
  435. // shape-outside
  436. // speak
  437. // speak-header
  438. // speak-numeral
  439. // speak-punctuation
  440. // speech-rate
  441. // stress
  442. // table-layout
  443. /// text-align
  444. TextAlign(TextAlign),
  445. // text-combine-upright
  446. // text-decoration
  447. // text-decoration-color
  448. // text-decoration-line
  449. // text-decoration-style
  450. // text-emphasis
  451. // text-emphasis-color
  452. // text-emphasis-position
  453. // text-emphasis-style
  454. // text-indent
  455. // text-orientation
  456. // text-overflow
  457. // text-shadow
  458. // text-transform
  459. // text-underline-position
  460. /// top
  461. Top(AutoLengthPercentage),
  462. // transform
  463. // transform-box
  464. // transform-origin
  465. // unicode-bidi
  466. // vertical-align
  467. // visibility
  468. // voice-family
  469. // volume
  470. /// white-space
  471. WhiteSpace(WhiteSpace),
  472. /// widows
  473. Widows(u32),
  474. /// width
  475. Width(WidthHeight),
  476. // will-change
  477. // word-spacing
  478. // writing-mode
  479. // z-index
  480. }
  481. impl Style {
  482. fn is_dummy(&self) -> bool {
  483. match self {
  484. Style::Dummy => true,
  485. _ => false,
  486. }
  487. }
  488. fn is_dynamic(&self) -> bool {
  489. match self {
  490. Style::BackgroundColor(value) => value.is_dynamic(),
  491. Style::Color(value) => value.is_dynamic(),
  492. _ => false,
  493. }
  494. }
  495. }
  496. impl fmt::Display for Style {
  497. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  498. match self {
  499. Style::Dummy => Ok(()),
  500. Style::Unchecked(v) => write!(f, "{}", v),
  501. Style::AlignContent(v) => write!(f, "align-content:{}", v),
  502. Style::AlignItems(v) => write!(f, "align-items:{}", v),
  503. Style::AlignSelf(v) => write!(f, "align-self:{}", v),
  504. // all - deferred
  505. // background
  506. Style::BackgroundAttachment(v) => write!(f, "background-attachment:{}", v),
  507. Style::BackgroundBlendMode(v) => write!(f, "background-blend-mode:{}", v),
  508. Style::BackgroundClip(v) => write!(f, "background-clip:{}", v),
  509. Style::BackgroundColor(v) => write!(f, "background-color:{}", v),
  510. Style::BackgroundImage(v) => write!(f, "background-image:{}", v),
  511. Style::BackgroundOrigin(v) => write!(f, "background-origin:{}", v),
  512. Style::BackgroundPosition(v) => write!(f, "background-position:{}", v),
  513. Style::BackgroundRepeat(v) => write!(f, "background-repeat:{}", v),
  514. Style::BackgroundSize(v) => write!(f, "background-size:{}", v),
  515. Style::Border(v) => write!(f, "border:{}", v),
  516. Style::BorderBottom(v) => write!(f, "border-bottom:{}", v),
  517. Style::BorderBottomColor(v) => write!(f, "border-bottom-color:{}", v),
  518. Style::BorderBottomLeftRadius(v) => write!(f, "border-bottom-left-radius:{}", v),
  519. Style::BorderBottomRightRadius(v) => write!(f, "border-bottom-right-radius:{}", v),
  520. Style::BorderBottomStyle(v) => write!(f, "border-bottom-style:{}", v),
  521. Style::BorderBottomWidth(v) => write!(f, "border-bottom-width:{}", v),
  522. Style::BorderCollapse(v) => write!(f, "border-collapse:{}", v),
  523. Style::BorderColor(v) => write!(f, "border-color:{}", v),
  524. // border-image
  525. // border-image-outset
  526. // border-image-repeat
  527. // border-image-slice
  528. // border-image-source
  529. // border-image-width
  530. Style::BorderLeft(v) => write!(f, "border-left:{}", v),
  531. Style::BorderLeftColor(v) => write!(f, "border-left-color:{}", v),
  532. Style::BorderLeftStyle(v) => write!(f, "border-left-style:{}", v),
  533. Style::BorderLeftWidth(v) => write!(f, "border-left-width:{}", v),
  534. Style::BorderRadius(v) => write!(f, "border-radius:{}", v),
  535. Style::BorderRight(v) => write!(f, "border-right:{}", v),
  536. Style::BorderRightColor(v) => write!(f, "border-right-color:{}", v),
  537. Style::BorderRightStyle(v) => write!(f, "border-right-style:{}", v),
  538. Style::BorderRightWidth(v) => write!(f, "border-right-width:{}", v),
  539. // border-spacing
  540. Style::BorderStyle(v) => write!(f, "border-style:{}", v),
  541. Style::BorderTop(v) => write!(f, "border-top:{}", v),
  542. Style::BorderTopColor(v) => write!(f, "border-top-color:{}", v),
  543. Style::BorderTopLeftRadius(v) => write!(f, "border-top-left-radius:{}", v),
  544. Style::BorderTopRightRadius(v) => write!(f, "border-top-right-radius:{}", v),
  545. Style::BorderTopStyle(v) => write!(f, "border-top-style:{}", v),
  546. Style::BorderTopWidth(v) => write!(f, "border-top-width:{}", v),
  547. Style::BorderWidth(v) => write!(f, "border-width:{}", v),
  548. Style::Bottom(v) => write!(f, "bottom:{}", v),
  549. // box-decoration-break
  550. Style::BoxShadow(v) => write!(f, "box-shadow:{}", v),
  551. Style::BoxSizing(v) => write!(f, "box-sizing:{}", v),
  552. // break-after
  553. // break-before
  554. // break-inside
  555. // caption-side
  556. // caret-color
  557. Style::Clear(v) => write!(f, "clear:{}", v),
  558. // clip
  559. // clip-path
  560. // clip-rule
  561. Style::Color(v) => write!(f, "color:{}", v),
  562. Style::ColumnCount(v) => write!(f, "column-count:{}", v),
  563. // contain
  564. // content
  565. // counter-increment
  566. // counter-reset
  567. // cue
  568. // cue-after
  569. // cue-before
  570. Style::Cursor(v) => write!(f, "cursor:{}", v),
  571. // direction
  572. Style::Display(v) => write!(f, "display:{}", v),
  573. // elevation
  574. // empty-cells
  575. // flex
  576. Style::FlexBasis(v) => write!(f, "flex-basis:{}", v),
  577. Style::FlexDirection(v) => write!(f, "flex-direction:{}", v),
  578. // flex-flow
  579. Style::FlexGrow(v) => write!(f, "flex-grow:{}", v),
  580. Style::FlexShrink(v) => write!(f, "flex-shrink:{}", v),
  581. Style::FlexWrap(v) => write!(f, "flex-wrap:{}", v),
  582. Style::Float(v) => write!(f, "float:{}", v),
  583. // font
  584. Style::FontFamily(v) => write!(f, "font-family:{}", v),
  585. // font-feature-settings
  586. // font-kerning
  587. Style::FontSize(v) => write!(f, "font-size:{}", v),
  588. // font-size-adjust
  589. // font-stretch
  590. Style::FontStyle(v) => write!(f, "font-style:{}", v),
  591. // font-synthesis
  592. // font-variant
  593. // font-variant-caps
  594. // font-variant-east-asian
  595. // font-variant-ligatures
  596. // font-variant-numeric
  597. // font-variant-position
  598. Style::FontWeight(v) => write!(f, "font-weight:{}", v),
  599. // glyph-orientation-vertical
  600. // grid
  601. // grid-area
  602. // grid-auto-columns
  603. // grid-auto-flow
  604. // grid-auto-rows
  605. // grid-column
  606. // grid-column-end
  607. // grid-column-start
  608. // grid-row
  609. // grid-row-end
  610. // grid-row-start
  611. // grid-template
  612. // grid-template-areas
  613. // grid-template-columns
  614. // grid-template-rows
  615. Style::Height(v) => write!(f, "height:{}", v),
  616. // image-orientation
  617. // image-rendering
  618. // isolation
  619. Style::JustifyContent(v) => write!(f, "justify-content:{}", v),
  620. // left
  621. Style::Left(v) => write!(f, "left:{}", v),
  622. // letter-spacing
  623. // line-height
  624. Style::LineHeight(v) => write!(f, "line-height:{}", v),
  625. // list-style
  626. // list-style-image
  627. // list-style-position
  628. Style::ListStyleType(v) => write!(f, "list-style-type:{}", v),
  629. Style::Margin(v) => write!(f, "margin:{}", v),
  630. Style::MarginBottom(v) => write!(f, "margin-bottom:{}", v),
  631. Style::MarginLeft(v) => write!(f, "margin-left:{}", v),
  632. Style::MarginRight(v) => write!(f, "margin-right:{}", v),
  633. Style::MarginTop(v) => write!(f, "margin-top:{}", v),
  634. // mask
  635. // mask-border
  636. // mask-border-mode
  637. // mask-border-outset
  638. // mask-border-repeat
  639. // mask-border-slice
  640. // mask-border-source
  641. // mask-border-width
  642. // mask-clip
  643. // mask-composite
  644. // mask-image
  645. // mask-mode
  646. // mask-origin
  647. // mask-position
  648. // mask-repeat
  649. // mask-size
  650. // mask-type
  651. Style::MaxHeight(v) => write!(f, "max-height:{}", v),
  652. Style::MaxWidth(v) => write!(f, "max-width:{}", v),
  653. Style::MinHeight(v) => write!(f, "min-height:{}", v),
  654. Style::MinWidth(v) => write!(f, "min-width:{}", v),
  655. // mix-blend-mode
  656. Style::ObjectFit(v) => write!(f, "object-fit:{}", v),
  657. // object-position
  658. // opacity
  659. // order
  660. // orphans
  661. // outline
  662. // outline-color
  663. // outline-offset
  664. // outline-style
  665. // outline-width
  666. Style::Overflow(v) => write!(f, "overflow:{}", v),
  667. Style::OverflowX(v) => write!(f, "overflow-x:{}", v),
  668. Style::OverflowY(v) => write!(f, "overflow-y:{}", v),
  669. Style::Padding(v) => write!(f, "padding:{}", v),
  670. Style::PaddingBottom(v) => write!(f, "padding-bottom:{}", v),
  671. Style::PaddingLeft(v) => write!(f, "padding-left:{}", v),
  672. Style::PaddingRight(v) => write!(f, "padding-right:{}", v),
  673. Style::PaddingTop(v) => write!(f, "padding-top:{}", v),
  674. // padding-bottom
  675. // padding-left
  676. // padding-right
  677. // padding-top
  678. // page-break-after
  679. // page-break-before
  680. // page-break-inside
  681. // pause
  682. // pause-after
  683. // pause-before
  684. // pitch
  685. // pitch-range
  686. // play-during
  687. Style::Position(v) => write!(f, "position:{}", v),
  688. // uotes
  689. Style::Resize(v) => write!(f, "resize:{}", v),
  690. // richness
  691. Style::Right(v) => write!(f, "right:{}", v),
  692. // scroll-margin
  693. // scroll-margin-block
  694. // scroll-margin-block-end
  695. // scroll-margin-block-start
  696. // scroll-margin-bottom
  697. // scroll-margin-inline
  698. // scroll-margin-inline-end
  699. // scroll-margin-inline-start
  700. // scroll-margin-left
  701. // scroll-margin-right
  702. // scroll-margin-top
  703. // scroll-padding
  704. // scroll-padding-block
  705. // scroll-padding-block-end
  706. // scroll-padding-block-start
  707. // scroll-padding-bottom
  708. // scroll-padding-inline
  709. // scroll-padding-inline-end
  710. // scroll-padding-inline-start
  711. // scroll-padding-left
  712. // scroll-padding-right
  713. // scroll-padding-top
  714. // scroll-snap-align
  715. // scroll-snap-stop
  716. // scroll-snap-type
  717. // shape-image-threshold
  718. // shape-margin
  719. // shape-outside
  720. // speak
  721. // speak-header
  722. // speak-numeral
  723. // speak-punctuation
  724. // speech-rate
  725. // stress
  726. // table-layout
  727. Style::TextAlign(v) => write!(f, "text-align:{}", v),
  728. // text-combine-upright
  729. // text-decoration
  730. // text-decoration-color
  731. // text-decoration-line
  732. // text-decoration-style
  733. // text-emphasis
  734. // text-emphasis-color
  735. // text-emphasis-position
  736. // text-emphasis-style
  737. // text-indent
  738. // text-orientation
  739. // text-overflow
  740. // text-shadow
  741. // text-transform
  742. // text-underline-position
  743. // top
  744. Style::Top(v) => write!(f, "top:{}", v),
  745. // transform
  746. // transform-box
  747. // transform-origin
  748. // unicode-bidi
  749. // vertical-align
  750. // visibility
  751. // voice-family
  752. // volume
  753. Style::WhiteSpace(v) => write!(f, "white-space:{}", v),
  754. Style::Widows(v) => write!(f, "widows:{}", v),
  755. Style::Width(v) => write!(f, "width:{}", v),
  756. // will-change
  757. // word-spacing
  758. // writing-mode
  759. // z-index
  760. }
  761. }
  762. }
  763. /// https://www.w3.org/TR/css-flexbox-1/#propdef-justify-content
  764. #[derive(Debug, Clone, Copy, PartialEq)]
  765. pub enum AlignContent {
  766. FlexStart,
  767. Center,
  768. FlexEnd,
  769. SpaceBetween,
  770. SpaceAround,
  771. Stretch,
  772. }
  773. impl Default for AlignContent {
  774. fn default() -> Self {
  775. AlignContent::Stretch
  776. }
  777. }
  778. impl fmt::Display for AlignContent {
  779. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  780. match self {
  781. AlignContent::FlexStart => write!(f, "flex-start"),
  782. AlignContent::Center => write!(f, "center"),
  783. AlignContent::FlexEnd => write!(f, "flex-end"),
  784. AlignContent::SpaceAround => write!(f, "space-around"),
  785. AlignContent::SpaceBetween => write!(f, "space-between"),
  786. AlignContent::Stretch => write!(f, "stretch"),
  787. }
  788. }
  789. }
  790. /// https://developer.mozilla.org/en-US/docs/Web/CSS/align-items
  791. #[derive(Debug, Clone, Copy, PartialEq)]
  792. pub enum AlignItems {
  793. Normal,
  794. Stretch,
  795. Center,
  796. Start,
  797. End,
  798. FlexStart,
  799. FlexEnd,
  800. Baseline,
  801. FirstBaseline,
  802. LastBaseline,
  803. SafeCenter,
  804. UnsafeCenter,
  805. }
  806. impl fmt::Display for AlignItems {
  807. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  808. match self {
  809. AlignItems::Normal => write!(f, "normal"),
  810. AlignItems::Stretch => write!(f, "stretch"),
  811. AlignItems::Center => write!(f, "center"),
  812. AlignItems::Start => write!(f, "start"),
  813. AlignItems::End => write!(f, "end"),
  814. AlignItems::FlexStart => write!(f, "flex-start"),
  815. AlignItems::FlexEnd => write!(f, "flex-end"),
  816. AlignItems::Baseline => write!(f, "baseline"),
  817. AlignItems::FirstBaseline => write!(f, "first baseline"),
  818. AlignItems::LastBaseline => write!(f, "last baseline"),
  819. AlignItems::SafeCenter => write!(f, "safe center"),
  820. AlignItems::UnsafeCenter => write!(f, "unsafe center"),
  821. }
  822. }
  823. }
  824. /// https://developer.mozilla.org/en-US/docs/Web/CSS/align-self
  825. #[derive(Debug, Clone, Copy, PartialEq)]
  826. pub enum AlignSelf {
  827. Auto,
  828. Normal,
  829. Center,
  830. Start,
  831. End,
  832. SelfStart,
  833. SelfEnd,
  834. FlexStart,
  835. FlexEnd,
  836. Baseline,
  837. FirstBaseline,
  838. LastBaseline,
  839. Stretch,
  840. SafeCenter,
  841. UnsafeCenter,
  842. }
  843. impl fmt::Display for AlignSelf {
  844. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  845. match self {
  846. AlignSelf::Auto => write!(f, "auto"),
  847. AlignSelf::Normal => write!(f, "normal"),
  848. AlignSelf::Center => write!(f, "center"),
  849. AlignSelf::Start => write!(f, "start"),
  850. AlignSelf::End => write!(f, "end"),
  851. AlignSelf::SelfStart => write!(f, "self-start"),
  852. AlignSelf::SelfEnd => write!(f, "self-end"),
  853. AlignSelf::FlexStart => write!(f, "flex-start"),
  854. AlignSelf::FlexEnd => write!(f, "flex-end"),
  855. AlignSelf::Baseline => write!(f, "baseline"),
  856. AlignSelf::FirstBaseline => write!(f, "first baseline"),
  857. AlignSelf::LastBaseline => write!(f, "last baseline"),
  858. AlignSelf::Stretch => write!(f, "stretch"),
  859. AlignSelf::SafeCenter => write!(f, "safe center"),
  860. AlignSelf::UnsafeCenter => write!(f, "unsafe center"),
  861. }
  862. }
  863. }
  864. /// https://developer.mozilla.org/en-US/docs/Web/CSS/background-attachment
  865. #[derive(Debug, Clone, Copy, PartialEq)]
  866. pub enum BackgroundAttachment {
  867. Scroll,
  868. Fixed,
  869. Local,
  870. }
  871. impl fmt::Display for BackgroundAttachment {
  872. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  873. match self {
  874. BackgroundAttachment::Scroll => write!(f, "scroll"),
  875. BackgroundAttachment::Fixed => write!(f, "fixed"),
  876. BackgroundAttachment::Local => write!(f, "local"),
  877. }
  878. }
  879. }
  880. /// https://developer.mozilla.org/en-US/docs/Web/CSS/background-blend-mode
  881. #[derive(Debug, Clone, PartialEq)]
  882. pub enum BlendMode {
  883. Normal,
  884. Multiply,
  885. Screen,
  886. Overlay,
  887. Darken,
  888. Lighten,
  889. ColorDodge,
  890. ColorBurn,
  891. HardLight,
  892. SoftLight,
  893. Difference,
  894. Exclusion,
  895. Hue,
  896. Saturation,
  897. Color,
  898. Luminosity,
  899. }
  900. impl fmt::Display for BlendMode {
  901. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  902. match self {
  903. BlendMode::Normal => write!(f, "normal"),
  904. BlendMode::Multiply => write!(f, "multiply"),
  905. BlendMode::Screen => write!(f, "screen"),
  906. BlendMode::Overlay => write!(f, "overlay"),
  907. BlendMode::Darken => write!(f, "darken"),
  908. BlendMode::Lighten => write!(f, "lighten"),
  909. BlendMode::ColorDodge => write!(f, "color-dodge"),
  910. BlendMode::ColorBurn => write!(f, "color-burn"),
  911. BlendMode::HardLight => write!(f, "hard-light"),
  912. BlendMode::SoftLight => write!(f, "soft-light"),
  913. BlendMode::Difference => write!(f, "difference"),
  914. BlendMode::Exclusion => write!(f, "exclusion"),
  915. BlendMode::Hue => write!(f, "hue"),
  916. BlendMode::Saturation => write!(f, "saturation"),
  917. BlendMode::Color => write!(f, "color"),
  918. BlendMode::Luminosity => write!(f, "luminosity"),
  919. }
  920. }
  921. }
  922. #[derive(Debug, Clone, PartialEq)]
  923. pub enum BackgroundBox {
  924. BorderBox,
  925. PaddingBox,
  926. ContentBox,
  927. }
  928. impl fmt::Display for BackgroundBox {
  929. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  930. match self {
  931. BackgroundBox::BorderBox => write!(f, "border-box"),
  932. BackgroundBox::PaddingBox => write!(f, "padding-box"),
  933. BackgroundBox::ContentBox => write!(f, "content-box"),
  934. }
  935. }
  936. }
  937. #[derive(Debug, Clone, PartialEq)]
  938. pub enum BackgroundImage {
  939. None,
  940. Url(String),
  941. // TODO other variants
  942. }
  943. impl fmt::Display for BackgroundImage {
  944. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  945. match self {
  946. BackgroundImage::None => write!(f, "none"),
  947. BackgroundImage::Url(url) => write!(f, "url({})", url),
  948. }
  949. }
  950. }
  951. #[derive(Debug, Clone, PartialEq)]
  952. pub enum BackgroundPosition {
  953. Top,
  954. Bottom,
  955. Left,
  956. Right,
  957. Center,
  958. // TODO other variants
  959. }
  960. impl fmt::Display for BackgroundPosition {
  961. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  962. match self {
  963. BackgroundPosition::Top => write!(f, "top"),
  964. BackgroundPosition::Left => write!(f, "left"),
  965. BackgroundPosition::Bottom => write!(f, "bottom"),
  966. BackgroundPosition::Right => write!(f, "right"),
  967. BackgroundPosition::Center => write!(f, "center"),
  968. }
  969. }
  970. }
  971. #[derive(Debug, Clone, PartialEq)]
  972. pub enum BackgroundRepeat {
  973. RepeatX,
  974. RepeatY,
  975. SingleOrDouble(SingleOrDouble<BgRepeatPart>),
  976. }
  977. impl fmt::Display for BackgroundRepeat {
  978. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  979. match self {
  980. BackgroundRepeat::RepeatX => write!(f, "repeat-x"),
  981. BackgroundRepeat::RepeatY => write!(f, "repeat-y"),
  982. BackgroundRepeat::SingleOrDouble(v) => v.fmt(f),
  983. }
  984. }
  985. }
  986. #[derive(Debug, Clone, PartialEq)]
  987. pub enum BgRepeatPart {
  988. Repeat,
  989. Space,
  990. Round,
  991. NoRepeat,
  992. }
  993. impl fmt::Display for BgRepeatPart {
  994. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  995. match self {
  996. BgRepeatPart::Repeat => write!(f, "repeat"),
  997. BgRepeatPart::Space => write!(f, "space"),
  998. BgRepeatPart::Round => write!(f, "round"),
  999. BgRepeatPart::NoRepeat => write!(f, "no-repeat"),
  1000. }
  1001. }
  1002. }
  1003. #[derive(Debug, Clone, PartialEq)]
  1004. pub enum BackgroundSize {
  1005. Cover,
  1006. Contain,
  1007. SingleOrDouble(SingleOrDouble<AutoLengthPercentage>),
  1008. }
  1009. impl fmt::Display for BackgroundSize {
  1010. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1011. match self {
  1012. BackgroundSize::Cover => write!(f, "cover"),
  1013. BackgroundSize::Contain => write!(f, "contain"),
  1014. BackgroundSize::SingleOrDouble(v) => v.fmt(f),
  1015. }
  1016. }
  1017. }
  1018. #[derive(Debug, Clone, Copy, PartialEq)]
  1019. pub struct Border {
  1020. pub line_width: Option<LineWidth>,
  1021. pub line_style: Option<LineStyle>,
  1022. pub color: Option<Color>,
  1023. }
  1024. impl Border {
  1025. fn new() -> Self {
  1026. Border {
  1027. line_width: None,
  1028. line_style: None,
  1029. color: None,
  1030. }
  1031. }
  1032. fn is_full(&self) -> bool {
  1033. match (&self.line_width, &self.line_style, &self.color) {
  1034. (Some(_), Some(_), Some(_)) => true,
  1035. _ => false,
  1036. }
  1037. }
  1038. fn has_line_width(&self) -> bool {
  1039. self.line_width.is_some()
  1040. }
  1041. fn has_line_style(&self) -> bool {
  1042. self.line_style.is_some()
  1043. }
  1044. fn has_color(&self) -> bool {
  1045. self.color.is_some()
  1046. }
  1047. }
  1048. impl fmt::Display for Border {
  1049. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1050. fn space(yes: bool) -> &'static str {
  1051. if yes {
  1052. " "
  1053. } else {
  1054. ""
  1055. }
  1056. }
  1057. let mut cont = false;
  1058. if let Some(line_width) = self.line_width {
  1059. write!(f, "{}", line_width)?;
  1060. cont = true;
  1061. }
  1062. if let Some(line_style) = self.line_style {
  1063. write!(f, "{}{}", space(cont), line_style)?;
  1064. cont = true;
  1065. }
  1066. if let Some(color) = self.color {
  1067. write!(f, "{}{}", space(cont), color)?;
  1068. }
  1069. Ok(())
  1070. }
  1071. }
  1072. #[derive(Debug, Clone, PartialEq)]
  1073. pub enum BorderCollapse {
  1074. Collapse,
  1075. Separate,
  1076. }
  1077. impl fmt::Display for BorderCollapse {
  1078. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1079. match self {
  1080. BorderCollapse::Collapse => write!(f, "collapse"),
  1081. BorderCollapse::Separate => write!(f, "separate"),
  1082. }
  1083. }
  1084. }
  1085. pub type BorderRadius = Calc;
  1086. pub type BorderStyle = Rect<LineStyle>;
  1087. pub type BorderWidth = Rect<LineWidth>;
  1088. #[derive(Debug, Clone, PartialEq)]
  1089. pub enum BoxShadow {
  1090. None,
  1091. Shadows(NonemptyCommaList<Shadow>),
  1092. }
  1093. impl fmt::Display for BoxShadow {
  1094. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1095. match self {
  1096. BoxShadow::None => f.write_str("none"),
  1097. BoxShadow::Shadows(list) => write!(f, "{}", list),
  1098. }
  1099. }
  1100. }
  1101. #[derive(Debug, Clone, Copy, PartialEq)]
  1102. pub enum BoxSizing {
  1103. BorderBox,
  1104. ContentBox,
  1105. }
  1106. impl fmt::Display for BoxSizing {
  1107. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1108. match self {
  1109. BoxSizing::BorderBox => f.write_str("border-box"),
  1110. BoxSizing::ContentBox => f.write_str("content-box"),
  1111. }
  1112. }
  1113. }
  1114. #[derive(Debug, Clone, Copy, PartialEq)]
  1115. pub enum Clear {
  1116. None,
  1117. Left,
  1118. Right,
  1119. Both,
  1120. InlineStart,
  1121. InlineEnd,
  1122. }
  1123. impl fmt::Display for Clear {
  1124. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1125. match self {
  1126. Clear::None => f.write_str("none"),
  1127. Clear::Left => f.write_str("left"),
  1128. Clear::Right => f.write_str("right"),
  1129. Clear::Both => f.write_str("both"),
  1130. Clear::InlineStart => f.write_str("inline-start"),
  1131. Clear::InlineEnd => f.write_str("inline-end"),
  1132. }
  1133. }
  1134. }
  1135. #[derive(Debug, Clone, Copy, PartialEq)]
  1136. pub enum ColumnCount {
  1137. Auto,
  1138. Fixed(u32),
  1139. }
  1140. impl fmt::Display for ColumnCount {
  1141. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1142. match self {
  1143. ColumnCount::Auto => f.write_str("auto"),
  1144. ColumnCount::Fixed(inner) => write!(f, "{}", inner),
  1145. }
  1146. }
  1147. }
  1148. #[derive(Debug, Clone, Copy, PartialEq)]
  1149. pub enum Cursor {
  1150. // todo url
  1151. Auto,
  1152. Default,
  1153. None,
  1154. ContextMenu,
  1155. Help,
  1156. Pointer,
  1157. Progress,
  1158. Wait,
  1159. Cell,
  1160. Crosshair,
  1161. Text,
  1162. VerticalText,
  1163. Alias,
  1164. Copy,
  1165. Move,
  1166. NoDrop,
  1167. NotAllowed,
  1168. Grab,
  1169. Grabbing,
  1170. EResize,
  1171. NResize,
  1172. NEResize,
  1173. NWResize,
  1174. SResize,
  1175. SEResize,
  1176. SWResize,
  1177. WResize,
  1178. EWResize,
  1179. NSResize,
  1180. NESWResize,
  1181. NWSEResize,
  1182. ColResize,
  1183. RowResize,
  1184. AllScroll,
  1185. ZoomIn,
  1186. ZoomOut,
  1187. }
  1188. impl fmt::Display for Cursor {
  1189. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1190. match self {
  1191. Cursor::Auto => f.write_str("auto"),
  1192. Cursor::Default => f.write_str("default"),
  1193. Cursor::None => f.write_str("none"),
  1194. Cursor::ContextMenu => f.write_str("context-menu"),
  1195. Cursor::Help => f.write_str("help"),
  1196. Cursor::Pointer => f.write_str("pointer"),
  1197. Cursor::Progress => f.write_str("progress"),
  1198. Cursor::Wait => f.write_str("wait"),
  1199. Cursor::Cell => f.write_str("cell"),
  1200. Cursor::Crosshair => f.write_str("crosshair"),
  1201. Cursor::Text => f.write_str("text"),
  1202. Cursor::VerticalText => f.write_str("vertical-text"),
  1203. Cursor::Alias => f.write_str("alias"),
  1204. Cursor::Copy => f.write_str("copy"),
  1205. Cursor::Move => f.write_str("move"),
  1206. Cursor::NoDrop => f.write_str("no-drop"),
  1207. Cursor::NotAllowed => f.write_str("not-allowed"),
  1208. Cursor::Grab => f.write_str("grab"),
  1209. Cursor::Grabbing => f.write_str("grabbing"),
  1210. Cursor::EResize => f.write_str("e-resize"),
  1211. Cursor::NResize => f.write_str("n-resize"),
  1212. Cursor::NEResize => f.write_str("ne-resize"),
  1213. Cursor::NWResize => f.write_str("nw-resize"),
  1214. Cursor::SResize => f.write_str("s-resize"),
  1215. Cursor::SEResize => f.write_str("se-resize"),
  1216. Cursor::SWResize => f.write_str("sw-resize"),
  1217. Cursor::WResize => f.write_str("w-resize"),
  1218. Cursor::EWResize => f.write_str("ew-resize"),
  1219. Cursor::NSResize => f.write_str("ns-resize"),
  1220. Cursor::NESWResize => f.write_str("nesw-resize"),
  1221. Cursor::NWSEResize => f.write_str("nwse-resize"),
  1222. Cursor::ColResize => f.write_str("col-resize"),
  1223. Cursor::RowResize => f.write_str("row-resize"),
  1224. Cursor::AllScroll => f.write_str("all-scroll"),
  1225. Cursor::ZoomIn => f.write_str("zoom-in"),
  1226. Cursor::ZoomOut => f.write_str("zoom-out"),
  1227. }
  1228. }
  1229. }
  1230. #[derive(Debug, Clone, Copy, PartialEq)]
  1231. pub enum Display {
  1232. Block,
  1233. Flex,
  1234. Inline,
  1235. // todo incomplete
  1236. }
  1237. impl fmt::Display for Display {
  1238. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1239. match self {
  1240. Display::Block => f.write_str("block"),
  1241. Display::Flex => f.write_str("flex"),
  1242. Display::Inline => f.write_str("inline"),
  1243. }
  1244. }
  1245. }
  1246. #[derive(Debug, Clone, PartialEq)]
  1247. pub enum FlexBasis {
  1248. Width(Width21),
  1249. Content,
  1250. }
  1251. impl fmt::Display for FlexBasis {
  1252. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1253. match self {
  1254. FlexBasis::Width(v) => fmt::Display::fmt(v, f),
  1255. FlexBasis::Content => f.write_str("content"),
  1256. }
  1257. }
  1258. }
  1259. #[derive(Debug, Clone, Copy, PartialEq)]
  1260. pub enum FlexDirection {
  1261. Row,
  1262. Column,
  1263. }
  1264. impl fmt::Display for FlexDirection {
  1265. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1266. match self {
  1267. FlexDirection::Row => f.write_str("row"),
  1268. FlexDirection::Column => f.write_str("column"),
  1269. }
  1270. }
  1271. }
  1272. #[derive(Debug, Clone, Copy, PartialEq)]
  1273. pub enum FlexWrap {
  1274. Wrap,
  1275. Nowrap,
  1276. }
  1277. impl fmt::Display for FlexWrap {
  1278. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1279. match self {
  1280. FlexWrap::Wrap => write!(f, "wrap"),
  1281. FlexWrap::Nowrap => write!(f, "nowrap"),
  1282. }
  1283. }
  1284. }
  1285. #[derive(Debug, Clone, Copy, PartialEq)]
  1286. pub enum Float {
  1287. None,
  1288. Left,
  1289. Right,
  1290. InlineStart,
  1291. InlineEnd,
  1292. }
  1293. impl fmt::Display for Float {
  1294. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1295. match self {
  1296. Float::None => f.write_str("inline-end"),
  1297. Float::Left => f.write_str("left"),
  1298. Float::Right => f.write_str("right"),
  1299. Float::InlineStart => f.write_str("inline-start"),
  1300. Float::InlineEnd => f.write_str("inline-end"),
  1301. }
  1302. }
  1303. }
  1304. #[derive(Debug, Clone, PartialEq)]
  1305. pub enum Font {
  1306. // todo escape when `Display`ing
  1307. Named(String),
  1308. Serif,
  1309. SansSerif,
  1310. Cursive,
  1311. Fantasy,
  1312. Monospace,
  1313. }
  1314. impl fmt::Display for Font {
  1315. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1316. match self {
  1317. Font::Named(inner) => write!(f, "\"{}\"", inner),
  1318. Font::Serif => write!(f, "serif"),
  1319. Font::SansSerif => write!(f, "sans-serif"),
  1320. Font::Cursive => write!(f, "cursive"),
  1321. Font::Fantasy => write!(f, "fantasy"),
  1322. Font::Monospace => write!(f, "monospace"),
  1323. }
  1324. }
  1325. }
  1326. pub type FontFamily = NonemptyCommaList<Font>;
  1327. #[derive(Debug, Clone, PartialEq)]
  1328. pub enum FontSize {
  1329. XXSmall,
  1330. XSmall,
  1331. Small,
  1332. Medium,
  1333. Large,
  1334. XLarge,
  1335. XXLarge,
  1336. XXXLarge,
  1337. Larger,
  1338. Smaller,
  1339. LengthPercentage(Calc),
  1340. }
  1341. impl fmt::Display for FontSize {
  1342. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1343. match self {
  1344. FontSize::XXSmall => f.write_str("xx-small"),
  1345. FontSize::XSmall => f.write_str("x-small"),
  1346. FontSize::Small => f.write_str("small"),
  1347. FontSize::Medium => f.write_str("medium"),
  1348. FontSize::Large => f.write_str("large"),
  1349. FontSize::XLarge => f.write_str("x-large"),
  1350. FontSize::XXLarge => f.write_str("xx-large"),
  1351. FontSize::XXXLarge => f.write_str("xxx-large"),
  1352. FontSize::Larger => f.write_str("larger"),
  1353. FontSize::Smaller => f.write_str("smaller"),
  1354. FontSize::LengthPercentage(v) => fmt::Display::fmt(v, f),
  1355. }
  1356. }
  1357. }
  1358. #[derive(Debug, Clone, Copy, PartialEq)]
  1359. pub enum FontStyle {
  1360. Normal,
  1361. Italic,
  1362. Oblique,
  1363. }
  1364. impl fmt::Display for FontStyle {
  1365. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1366. match self {
  1367. FontStyle::Normal => f.write_str("normal"),
  1368. FontStyle::Italic => f.write_str("italic"),
  1369. FontStyle::Oblique => f.write_str("oblique"),
  1370. }
  1371. }
  1372. }
  1373. #[derive(Debug, Clone, Copy, PartialEq)]
  1374. pub enum FontWeight {
  1375. Normal,
  1376. Bold,
  1377. Lighter,
  1378. Bolder,
  1379. /// Between 1 and 1000
  1380. Number(f64),
  1381. }
  1382. impl fmt::Display for FontWeight {
  1383. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1384. match self {
  1385. FontWeight::Normal => f.write_str("normal"),
  1386. FontWeight::Bold => f.write_str("bold"),
  1387. FontWeight::Lighter => f.write_str("lighter"),
  1388. FontWeight::Bolder => f.write_str("bolder"),
  1389. FontWeight::Number(v) => fmt::Display::fmt(v, f),
  1390. }
  1391. }
  1392. }
  1393. /// https://www.w3.org/TR/css-flexbox-1/#propdef-justify-content
  1394. #[derive(Debug, Clone, Copy, PartialEq)]
  1395. pub enum JustifyContent {
  1396. FlexStart,
  1397. Center,
  1398. FlexEnd,
  1399. SpaceBetween,
  1400. SpaceAround,
  1401. }
  1402. impl fmt::Display for JustifyContent {
  1403. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1404. match self {
  1405. JustifyContent::FlexStart => write!(f, "flex-start"),
  1406. JustifyContent::Center => write!(f, "center"),
  1407. JustifyContent::FlexEnd => write!(f, "flex-end"),
  1408. JustifyContent::SpaceAround => write!(f, "space-around"),
  1409. JustifyContent::SpaceBetween => write!(f, "space-between"),
  1410. }
  1411. }
  1412. }
  1413. #[derive(Debug, Clone, Copy, PartialEq)]
  1414. pub enum Length {
  1415. Em(f64),
  1416. Ex(f64),
  1417. In(f64),
  1418. Cm(f64),
  1419. Mm(f64),
  1420. Pt(f64),
  1421. Pc(f64),
  1422. Px(f64),
  1423. Zero,
  1424. }
  1425. impl fmt::Display for Length {
  1426. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1427. match self {
  1428. Length::Em(val) => write!(f, "{}em", val),
  1429. Length::Ex(val) => write!(f, "{}ex", val),
  1430. Length::In(val) => write!(f, "{}in", val),
  1431. Length::Cm(val) => write!(f, "{}cm", val),
  1432. Length::Mm(val) => write!(f, "{}mm", val),
  1433. Length::Pt(val) => write!(f, "{}pt", val),
  1434. Length::Pc(val) => write!(f, "{}pc", val),
  1435. Length::Px(val) => write!(f, "{}px", val),
  1436. Length::Zero => write!(f, "0"),
  1437. }
  1438. }
  1439. }
  1440. #[derive(Debug, Clone, Copy, PartialEq)]
  1441. pub enum LengthPercentage {
  1442. Length(Length),
  1443. Percentage(Percentage),
  1444. }
  1445. impl fmt::Display for LengthPercentage {
  1446. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1447. match self {
  1448. LengthPercentage::Length(v) => fmt::Display::fmt(v, f),
  1449. LengthPercentage::Percentage(v) => fmt::Display::fmt(v, f),
  1450. }
  1451. }
  1452. }
  1453. #[derive(Debug, Clone, Copy, PartialEq)]
  1454. pub enum LineStyle {
  1455. None,
  1456. Hidden,
  1457. Dotted,
  1458. Dashed,
  1459. Solid,
  1460. Double,
  1461. Groove,
  1462. Ridge,
  1463. Inset,
  1464. Outset,
  1465. }
  1466. impl fmt::Display for LineStyle {
  1467. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1468. match self {
  1469. LineStyle::None => write!(f, "none"),
  1470. LineStyle::Hidden => write!(f, "hidden"),
  1471. LineStyle::Dotted => write!(f, "dotted"),
  1472. LineStyle::Dashed => write!(f, "dashed"),
  1473. LineStyle::Solid => write!(f, "solid"),
  1474. LineStyle::Double => write!(f, "double"),
  1475. LineStyle::Groove => write!(f, "groove"),
  1476. LineStyle::Ridge => write!(f, "ridge"),
  1477. LineStyle::Inset => write!(f, "inset"),
  1478. LineStyle::Outset => write!(f, "outset"),
  1479. }
  1480. }
  1481. }
  1482. #[derive(Debug, Clone, Copy, PartialEq)]
  1483. pub enum LineWidth {
  1484. Length(Length),
  1485. Thin,
  1486. Medium,
  1487. Thick,
  1488. }
  1489. impl fmt::Display for LineWidth {
  1490. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1491. match self {
  1492. LineWidth::Length(v) => fmt::Display::fmt(v, f),
  1493. LineWidth::Thin => write!(f, "thin"),
  1494. LineWidth::Medium => write!(f, "medium"),
  1495. LineWidth::Thick => write!(f, "thick"),
  1496. }
  1497. }
  1498. }
  1499. // TODO this isn't the full spec for lineheight
  1500. // (https://www.w3.org/TR/CSS2/visudet.html#propdef-line-height)
  1501. #[derive(Debug, Clone, Copy, PartialEq)]
  1502. pub struct LineHeight(f64);
  1503. impl fmt::Display for LineHeight {
  1504. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1505. write!(f, "{}", self.0)
  1506. }
  1507. }
  1508. #[derive(Debug, Clone, Copy, PartialEq)]
  1509. pub enum ListStyleType {
  1510. Disc,
  1511. Circle,
  1512. Square,
  1513. Decimal,
  1514. DecimalLeadingZero,
  1515. LowerRoman,
  1516. UpperRoman,
  1517. LowerGreek,
  1518. UpperGreek,
  1519. LowerLatin,
  1520. UpperLatin,
  1521. Armenian,
  1522. Georgian,
  1523. LowerAlpha,
  1524. UpperAlpha,
  1525. None,
  1526. }
  1527. impl fmt::Display for ListStyleType {
  1528. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1529. match self {
  1530. ListStyleType::Disc => write!(f, "disc"),
  1531. ListStyleType::Circle => write!(f, "circle"),
  1532. ListStyleType::Square => write!(f, "square"),
  1533. ListStyleType::Decimal => write!(f, "decimal"),
  1534. ListStyleType::DecimalLeadingZero => write!(f, "decimal-leading-zero"),
  1535. ListStyleType::LowerRoman => write!(f, "lower-roman"),
  1536. ListStyleType::UpperRoman => write!(f, "upper-roman"),
  1537. ListStyleType::LowerGreek => write!(f, "lower-greek"),
  1538. ListStyleType::UpperGreek => write!(f, "upper-greek"),
  1539. ListStyleType::LowerLatin => write!(f, "lower-latin"),
  1540. ListStyleType::UpperLatin => write!(f, "upper-latin"),
  1541. ListStyleType::Armenian => write!(f, "armenian"),
  1542. ListStyleType::Georgian => write!(f, "georgian"),
  1543. ListStyleType::LowerAlpha => write!(f, "lower-alpha"),
  1544. ListStyleType::UpperAlpha => write!(f, "upper-alpha"),
  1545. ListStyleType::None => write!(f, "none"),
  1546. }
  1547. }
  1548. }
  1549. pub type Margin = Rect<MarginWidth>;
  1550. #[derive(Debug, Clone, PartialEq)]
  1551. pub enum AutoLengthPercentage {
  1552. LengthPercentage(Calc),
  1553. Auto,
  1554. }
  1555. impl fmt::Display for AutoLengthPercentage {
  1556. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1557. match self {
  1558. AutoLengthPercentage::LengthPercentage(v) => fmt::Display::fmt(v, f),
  1559. AutoLengthPercentage::Auto => write!(f, "auto"),
  1560. }
  1561. }
  1562. }
  1563. pub type MarginWidth = AutoLengthPercentage;
  1564. /// for max-width and max-height
  1565. #[derive(Debug, Clone, PartialEq)]
  1566. pub enum MaxWidthHeight {
  1567. None,
  1568. LengthPercentage(Calc),
  1569. MinContent,
  1570. MaxContent,
  1571. FitContent(Calc),
  1572. }
  1573. impl fmt::Display for MaxWidthHeight {
  1574. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1575. match self {
  1576. MaxWidthHeight::None => write!(f, "none"),
  1577. MaxWidthHeight::LengthPercentage(v) => write!(f, "{}", v),
  1578. MaxWidthHeight::MinContent => write!(f, "min-content"),
  1579. MaxWidthHeight::MaxContent => write!(f, "max-content"),
  1580. MaxWidthHeight::FitContent(v) => write!(f, "fit-content({})", v),
  1581. }
  1582. }
  1583. }
  1584. #[derive(Debug, Clone, Copy, PartialEq)]
  1585. pub enum ObjectFit {
  1586. Fill,
  1587. None,
  1588. Contain { scale_down: bool },
  1589. Cover { scale_down: bool },
  1590. }
  1591. impl fmt::Display for ObjectFit {
  1592. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1593. match self {
  1594. ObjectFit::Fill => write!(f, "fill"),
  1595. ObjectFit::None => write!(f, "none"),
  1596. ObjectFit::Contain { scale_down } => {
  1597. if *scale_down {
  1598. write!(f, "contain scale-down")
  1599. } else {
  1600. write!(f, "contain")
  1601. }
  1602. }
  1603. ObjectFit::Cover { scale_down } => {
  1604. if *scale_down {
  1605. write!(f, "cover scale-down")
  1606. } else {
  1607. write!(f, "cover")
  1608. }
  1609. }
  1610. }
  1611. }
  1612. }
  1613. #[derive(Debug, Clone, Copy, PartialEq)]
  1614. pub enum Overflow {
  1615. Both(OverflowXY),
  1616. XY(OverflowXY, OverflowXY),
  1617. }
  1618. impl fmt::Display for Overflow {
  1619. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1620. match self {
  1621. Overflow::Both(v) => write!(f, "{}", v),
  1622. Overflow::XY(x, y) => write!(f, "{} {}", x, y),
  1623. }
  1624. }
  1625. }
  1626. #[derive(Debug, Clone, Copy, PartialEq)]
  1627. pub enum OverflowXY {
  1628. Visible,
  1629. Hidden,
  1630. Clip,
  1631. Scroll,
  1632. Auto,
  1633. }
  1634. impl fmt::Display for OverflowXY {
  1635. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1636. match self {
  1637. OverflowXY::Visible => write!(f, "visible"),
  1638. OverflowXY::Hidden => write!(f, "hidden"),
  1639. OverflowXY::Clip => write!(f, "clip"),
  1640. OverflowXY::Scroll => write!(f, "scroll"),
  1641. OverflowXY::Auto => write!(f, "auto"),
  1642. }
  1643. }
  1644. }
  1645. pub type Padding = Rect<Calc>;
  1646. /// for e.g. `padding-top`
  1647. pub type PaddingWidth = Calc;
  1648. #[derive(Debug, Clone, Copy, PartialEq)]
  1649. pub struct Percentage(pub f64);
  1650. impl fmt::Display for Percentage {
  1651. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1652. write!(f, "{}%", self.0)
  1653. }
  1654. }
  1655. #[derive(Debug, Clone, Copy, PartialEq)]
  1656. pub enum Position {
  1657. Static,
  1658. Relative,
  1659. Absolute,
  1660. Fixed,
  1661. }
  1662. impl fmt::Display for Position {
  1663. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1664. match self {
  1665. Position::Static => write!(f, "static"),
  1666. Position::Relative => write!(f, "relative"),
  1667. Position::Absolute => write!(f, "absolute"),
  1668. Position::Fixed => write!(f, "fixed"),
  1669. }
  1670. }
  1671. }
  1672. /// For parsing things in groups of 1, 2, 3 or 4 for specifying the sides of a rectangle.
  1673. #[derive(Debug, Clone, Copy, PartialEq)]
  1674. pub enum Rect<T> {
  1675. All(T),
  1676. VerticalHorizontal(T, T),
  1677. TopHorizontalBottom(T, T, T),
  1678. TopRightBottomLeft(T, T, T, T),
  1679. }
  1680. impl<T> fmt::Display for Rect<T>
  1681. where
  1682. T: fmt::Display,
  1683. {
  1684. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1685. match self {
  1686. Rect::All(a) => write!(f, "{}", a),
  1687. Rect::VerticalHorizontal(v, h) => write!(f, "{} {}", v, h),
  1688. Rect::TopHorizontalBottom(t, h, b) => write!(f, "{} {} {}", t, h, b),
  1689. Rect::TopRightBottomLeft(t, r, b, l) => write!(f, "{} {} {} {}", t, r, b, l),
  1690. }
  1691. }
  1692. }
  1693. #[derive(Debug, Clone, Copy, PartialEq)]
  1694. pub enum Resize {
  1695. None,
  1696. Both,
  1697. Horizontal,
  1698. Vertical,
  1699. }
  1700. impl fmt::Display for Resize {
  1701. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1702. match self {
  1703. Resize::None => write!(f, "none"),
  1704. Resize::Both => write!(f, "both"),
  1705. Resize::Horizontal => write!(f, "horizontal"),
  1706. Resize::Vertical => write!(f, "vertical"),
  1707. }
  1708. }
  1709. }
  1710. #[derive(Debug, Clone, PartialEq)]
  1711. pub struct Shadow {
  1712. pub color: Option<Color>,
  1713. pub length: ShadowLength,
  1714. pub inset: bool,
  1715. }
  1716. impl fmt::Display for Shadow {
  1717. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1718. // we do it in this order because it makes spacing easier.
  1719. write!(f, "{}", self.length)?;
  1720. if let Some(color) = self.color {
  1721. write!(f, " {}", color)?;
  1722. }
  1723. if self.inset {
  1724. write!(f, " inset")?;
  1725. }
  1726. Ok(())
  1727. }
  1728. }
  1729. #[derive(Debug, Clone, PartialEq)]
  1730. pub enum ShadowLength {
  1731. Offsets {
  1732. horizontal: Length,
  1733. vertical: Length,
  1734. },
  1735. OffsetsBlur {
  1736. horizontal: Length,
  1737. vertical: Length,
  1738. blur: Length,
  1739. },
  1740. OffsetsBlurSpread {
  1741. horizontal: Length,
  1742. vertical: Length,
  1743. blur: Length,
  1744. spread: Length,
  1745. },
  1746. }
  1747. impl fmt::Display for ShadowLength {
  1748. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1749. match self {
  1750. ShadowLength::Offsets {
  1751. horizontal,
  1752. vertical,
  1753. } => write!(f, "{} {}", horizontal, vertical),
  1754. ShadowLength::OffsetsBlur {
  1755. horizontal,
  1756. vertical,
  1757. blur,
  1758. } => write!(f, "{} {} {}", horizontal, vertical, blur),
  1759. ShadowLength::OffsetsBlurSpread {
  1760. horizontal,
  1761. vertical,
  1762. blur,
  1763. spread,
  1764. } => write!(f, "{} {} {} {}", horizontal, vertical, blur, spread),
  1765. }
  1766. }
  1767. }
  1768. #[test]
  1769. fn test_shadow_length() {
  1770. for (input, output) in vec![
  1771. (
  1772. "0 10px",
  1773. ShadowLength::Offsets {
  1774. horizontal: Length::Zero,
  1775. vertical: Length::Px(10.0),
  1776. },
  1777. ),
  1778. (
  1779. "0 10px -10px",
  1780. ShadowLength::OffsetsBlur {
  1781. horizontal: Length::Zero,
  1782. vertical: Length::Px(10.0),
  1783. blur: Length::Px(-10.0),
  1784. },
  1785. ),
  1786. ] {
  1787. assert_eq!(syn::parse_str::<ShadowLength>(input).unwrap(), output)
  1788. }
  1789. }
  1790. #[derive(Debug, Copy, Clone, PartialEq)]
  1791. pub enum TextAlign {
  1792. Left,
  1793. Right,
  1794. Center,
  1795. Justify,
  1796. }
  1797. impl fmt::Display for TextAlign {
  1798. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1799. match self {
  1800. TextAlign::Left => write!(f, "left"),
  1801. TextAlign::Right => write!(f, "right"),
  1802. TextAlign::Center => write!(f, "center"),
  1803. TextAlign::Justify => write!(f, "justify"),
  1804. }
  1805. }
  1806. }
  1807. #[derive(Debug, Clone, PartialEq)]
  1808. pub struct Url {
  1809. // todo modifiers
  1810. url: String,
  1811. }
  1812. impl fmt::Display for Url {
  1813. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1814. write!(f, "url(\"{}\")", self.url)
  1815. }
  1816. }
  1817. #[derive(Debug, Clone, PartialEq)]
  1818. pub enum WhiteSpace {
  1819. Normal,
  1820. Pre,
  1821. Nowrap,
  1822. PreWrap,
  1823. PreLine,
  1824. }
  1825. impl fmt::Display for WhiteSpace {
  1826. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1827. match self {
  1828. WhiteSpace::Normal => write!(f, "normal"),
  1829. WhiteSpace::Pre => write!(f, "pre"),
  1830. WhiteSpace::Nowrap => write!(f, "nowrap"),
  1831. WhiteSpace::PreWrap => write!(f, "pre-wrap"),
  1832. WhiteSpace::PreLine => write!(f, "pre-line"),
  1833. }
  1834. }
  1835. }
  1836. /// values of `width` and `height`, `min-width`, `min-height`.
  1837. #[derive(Debug, Clone, PartialEq)]
  1838. pub enum WidthHeight {
  1839. Auto,
  1840. LengthPercentage(Calc),
  1841. MinContent,
  1842. MaxContent,
  1843. FitContent(Calc),
  1844. }
  1845. impl fmt::Display for WidthHeight {
  1846. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1847. match self {
  1848. WidthHeight::Auto => write!(f, "auto"),
  1849. WidthHeight::LengthPercentage(v) => write!(f, "{}", v),
  1850. WidthHeight::MinContent => write!(f, "min-content"),
  1851. WidthHeight::MaxContent => write!(f, "max-content"),
  1852. WidthHeight::FitContent(v) => write!(f, "fit-content({})", v),
  1853. }
  1854. }
  1855. }
  1856. /// CSS2.1 width, for use with flexbox.
  1857. #[derive(Debug, Clone, PartialEq)]
  1858. pub enum Width21 {
  1859. Auto,
  1860. LengthPercentage(Calc),
  1861. }
  1862. impl fmt::Display for Width21 {
  1863. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1864. match self {
  1865. Width21::Auto => write!(f, "auto"),
  1866. Width21::LengthPercentage(v) => fmt::Display::fmt(v, f),
  1867. }
  1868. }
  1869. }
  1870. /// A generic container for a non-empty comma-separated list of values
  1871. #[derive(Debug, Clone, PartialEq)]
  1872. pub struct NonemptyCommaList<T> {
  1873. first: T,
  1874. rest: Vec<T>,
  1875. }
  1876. impl<T> fmt::Display for NonemptyCommaList<T>
  1877. where
  1878. T: fmt::Display,
  1879. {
  1880. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1881. write!(f, "{}", self.first)?;
  1882. for t in &self.rest {
  1883. write!(f, ",{}", t)?;
  1884. }
  1885. Ok(())
  1886. }
  1887. }
  1888. /// Matches one or two variables.
  1889. #[derive(Debug, Clone, PartialEq)]
  1890. pub enum SingleOrDouble<T> {
  1891. Single(T),
  1892. Double { horiz: T, vert: T },
  1893. }
  1894. impl<T> fmt::Display for SingleOrDouble<T>
  1895. where
  1896. T: fmt::Display,
  1897. {
  1898. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  1899. match self {
  1900. SingleOrDouble::Single(t) => t.fmt(f),
  1901. SingleOrDouble::Double { vert, horiz } => write!(f, "{} {}", vert, horiz),
  1902. }
  1903. }
  1904. }