@@ -18,6 +18,13 @@ internal sealed class PropertyFactory
1818
1919 private readonly Dictionary < string , ShorthandCreator > _shorthandsBuilder = new Dictionary < string , ShorthandCreator > ( StringComparer . OrdinalIgnoreCase ) ;
2020
21+ // Shorthands that parse and expand normally but are excluded from serialization reconstruction:
22+ // the logical shorthands, whose longhands are the physical ones (margin-top/-bottom/…), so letting
23+ // the serializer collapse e.g. margin-top+margin-bottom into `margin-block` would change existing
24+ // output. Excluded from GetShorthands (the serialization query) only; CreateShorthand,
25+ // GetLonghands and IsShorthand still work.
26+ private readonly HashSet < string > _logicalShorthands = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
27+
2128 private readonly Dictionary < string , LonghandCreator > _fonts ;
2229
2330 // @property descriptors (syntax / initial-value / inherits). Their values have no fixed CSS grammar
@@ -357,6 +364,124 @@ private PropertyFactory()
357364 _fontsBuilder . Add ( PropertyNames . Src , ( ) => new SrcProperty ( ) ) ;
358365 _fontsBuilder . Add ( PropertyNames . UnicodeRange , ( ) => new UnicodeRangeProperty ( ) ) ;
359366
367+ // CSS Logical Properties and Values Level 1. Layout here is always LTR / horizontal-tb,
368+ // so each logical property is registered to produce/export the existing physical
369+ // longhands (block-start = top, block-end = bottom, inline-start = left,
370+ // inline-end = right). Nothing downstream needs to change, since it already handles
371+ // every physical longhand.
372+
373+ // Logical margin longhands (aliases to the physical longhand classes).
374+ AddLonghand ( PropertyNames . MarginBlockStart , ( ) => new MarginTopProperty ( ) , true ) ;
375+ AddLonghand ( PropertyNames . MarginBlockEnd , ( ) => new MarginBottomProperty ( ) , true ) ;
376+ AddLonghand ( PropertyNames . MarginInlineStart , ( ) => new MarginLeftProperty ( ) , true ) ;
377+ AddLonghand ( PropertyNames . MarginInlineEnd , ( ) => new MarginRightProperty ( ) , true ) ;
378+ // Logical margin shorthands.
379+ AddLogicalShorthand ( PropertyNames . MarginBlock , ( ) => new MarginBlockProperty ( ) ,
380+ PropertyNames . MarginTop ,
381+ PropertyNames . MarginBottom ) ;
382+ AddLogicalShorthand ( PropertyNames . MarginInline , ( ) => new MarginInlineProperty ( ) ,
383+ PropertyNames . MarginLeft ,
384+ PropertyNames . MarginRight ) ;
385+
386+ // Logical padding longhands (aliases to the physical longhand classes).
387+ AddLonghand ( PropertyNames . PaddingBlockStart , ( ) => new PaddingTopProperty ( ) , true ) ;
388+ AddLonghand ( PropertyNames . PaddingBlockEnd , ( ) => new PaddingBottomProperty ( ) , true ) ;
389+ AddLonghand ( PropertyNames . PaddingInlineStart , ( ) => new PaddingLeftProperty ( ) , true ) ;
390+ AddLonghand ( PropertyNames . PaddingInlineEnd , ( ) => new PaddingRightProperty ( ) , true ) ;
391+ // Logical padding shorthands.
392+ AddLogicalShorthand ( PropertyNames . PaddingBlock , ( ) => new PaddingBlockProperty ( ) ,
393+ PropertyNames . PaddingTop ,
394+ PropertyNames . PaddingBottom ) ;
395+ AddLogicalShorthand ( PropertyNames . PaddingInline , ( ) => new PaddingInlineProperty ( ) ,
396+ PropertyNames . PaddingLeft ,
397+ PropertyNames . PaddingRight ) ;
398+
399+ // Logical inset longhands (aliases to the physical coordinate longhand classes).
400+ AddLonghand ( PropertyNames . InsetBlockStart , ( ) => new TopProperty ( ) , true ) ;
401+ AddLonghand ( PropertyNames . InsetBlockEnd , ( ) => new BottomProperty ( ) , true ) ;
402+ AddLonghand ( PropertyNames . InsetInlineStart , ( ) => new LeftProperty ( ) , true ) ;
403+ AddLonghand ( PropertyNames . InsetInlineEnd , ( ) => new RightProperty ( ) , true ) ;
404+ // Inset shorthands.
405+ AddLogicalShorthand ( PropertyNames . Inset , ( ) => new InsetProperty ( ) ,
406+ PropertyNames . Top ,
407+ PropertyNames . Right ,
408+ PropertyNames . Bottom ,
409+ PropertyNames . Left ) ;
410+ AddLogicalShorthand ( PropertyNames . InsetBlock , ( ) => new InsetBlockProperty ( ) ,
411+ PropertyNames . Top ,
412+ PropertyNames . Bottom ) ;
413+ AddLogicalShorthand ( PropertyNames . InsetInline , ( ) => new InsetInlineProperty ( ) ,
414+ PropertyNames . Left ,
415+ PropertyNames . Right ) ;
416+
417+ // Logical per-edge border longhands (aliases to the physical longhand classes).
418+ AddLonghand ( PropertyNames . BorderBlockStartWidth , ( ) => new BorderTopWidthProperty ( ) , true ) ;
419+ AddLonghand ( PropertyNames . BorderBlockStartStyle , ( ) => new BorderTopStyleProperty ( ) ) ;
420+ AddLonghand ( PropertyNames . BorderBlockStartColor , ( ) => new BorderTopColorProperty ( ) , true ) ;
421+ AddLonghand ( PropertyNames . BorderBlockEndWidth , ( ) => new BorderBottomWidthProperty ( ) , true ) ;
422+ AddLonghand ( PropertyNames . BorderBlockEndStyle , ( ) => new BorderBottomStyleProperty ( ) ) ;
423+ AddLonghand ( PropertyNames . BorderBlockEndColor , ( ) => new BorderBottomColorProperty ( ) , true ) ;
424+ AddLonghand ( PropertyNames . BorderInlineStartWidth , ( ) => new BorderLeftWidthProperty ( ) , true ) ;
425+ AddLonghand ( PropertyNames . BorderInlineStartStyle , ( ) => new BorderLeftStyleProperty ( ) ) ;
426+ AddLonghand ( PropertyNames . BorderInlineStartColor , ( ) => new BorderLeftColorProperty ( ) , true ) ;
427+ AddLonghand ( PropertyNames . BorderInlineEndWidth , ( ) => new BorderRightWidthProperty ( ) , true ) ;
428+ AddLonghand ( PropertyNames . BorderInlineEndStyle , ( ) => new BorderRightStyleProperty ( ) ) ;
429+ AddLonghand ( PropertyNames . BorderInlineEndColor , ( ) => new BorderRightColorProperty ( ) , true ) ;
430+
431+ // Logical per-edge border shorthands (aliases to the physical edge shorthand classes).
432+ AddLogicalShorthand ( PropertyNames . BorderBlockStart , ( ) => new BorderTopProperty ( ) ,
433+ PropertyNames . BorderTopWidth ,
434+ PropertyNames . BorderTopStyle ,
435+ PropertyNames . BorderTopColor ) ;
436+ AddLogicalShorthand ( PropertyNames . BorderBlockEnd , ( ) => new BorderBottomProperty ( ) ,
437+ PropertyNames . BorderBottomWidth ,
438+ PropertyNames . BorderBottomStyle ,
439+ PropertyNames . BorderBottomColor ) ;
440+ AddLogicalShorthand ( PropertyNames . BorderInlineStart , ( ) => new BorderLeftProperty ( ) ,
441+ PropertyNames . BorderLeftWidth ,
442+ PropertyNames . BorderLeftStyle ,
443+ PropertyNames . BorderLeftColor ) ;
444+ AddLogicalShorthand ( PropertyNames . BorderInlineEnd , ( ) => new BorderRightProperty ( ) ,
445+ PropertyNames . BorderRightWidth ,
446+ PropertyNames . BorderRightStyle ,
447+ PropertyNames . BorderRightColor ) ;
448+
449+ // Logical two-edge border shorthands (both block/inline edges the same value).
450+ AddLogicalShorthand ( PropertyNames . BorderBlock , ( ) => new BorderBlockProperty ( ) ,
451+ PropertyNames . BorderTopWidth ,
452+ PropertyNames . BorderTopStyle ,
453+ PropertyNames . BorderTopColor ,
454+ PropertyNames . BorderBottomWidth ,
455+ PropertyNames . BorderBottomStyle ,
456+ PropertyNames . BorderBottomColor ) ;
457+ AddLogicalShorthand ( PropertyNames . BorderInline , ( ) => new BorderInlineProperty ( ) ,
458+ PropertyNames . BorderLeftWidth ,
459+ PropertyNames . BorderLeftStyle ,
460+ PropertyNames . BorderLeftColor ,
461+ PropertyNames . BorderRightWidth ,
462+ PropertyNames . BorderRightStyle ,
463+ PropertyNames . BorderRightColor ) ;
464+
465+ // Logical two-edge border width/style/color shorthands.
466+ AddLogicalShorthand ( PropertyNames . BorderBlockWidth , ( ) => new BorderBlockWidthProperty ( ) ,
467+ PropertyNames . BorderTopWidth ,
468+ PropertyNames . BorderBottomWidth ) ;
469+ AddLogicalShorthand ( PropertyNames . BorderBlockStyle , ( ) => new BorderBlockStyleProperty ( ) ,
470+ PropertyNames . BorderTopStyle ,
471+ PropertyNames . BorderBottomStyle ) ;
472+ AddLogicalShorthand ( PropertyNames . BorderBlockColor , ( ) => new BorderBlockColorProperty ( ) ,
473+ PropertyNames . BorderTopColor ,
474+ PropertyNames . BorderBottomColor ) ;
475+ AddLogicalShorthand ( PropertyNames . BorderInlineWidth , ( ) => new BorderInlineWidthProperty ( ) ,
476+ PropertyNames . BorderLeftWidth ,
477+ PropertyNames . BorderRightWidth ) ;
478+ AddLogicalShorthand ( PropertyNames . BorderInlineStyle , ( ) => new BorderInlineStyleProperty ( ) ,
479+ PropertyNames . BorderLeftStyle ,
480+ PropertyNames . BorderRightStyle ) ;
481+ AddLogicalShorthand ( PropertyNames . BorderInlineColor , ( ) => new BorderInlineColorProperty ( ) ,
482+ PropertyNames . BorderLeftColor ,
483+ PropertyNames . BorderRightColor ) ;
484+
360485 _fonts = _fontsBuilder ;
361486
362487 _propertyDescriptors = new Dictionary < string , LonghandCreator > ( StringComparer . OrdinalIgnoreCase )
@@ -379,6 +504,14 @@ private void AddShorthand(string name, ShorthandCreator creator, params string[]
379504 _mappingsBuilder . Add ( name , longhands ) ;
380505 }
381506
507+ // A logical shorthand: registered for parsing/expansion, but excluded from serialization
508+ // reconstruction (see the _logicalShorthands field comment).
509+ private void AddLogicalShorthand ( string name , ShorthandCreator creator , params string [ ] longhands )
510+ {
511+ AddShorthand ( name , creator , longhands ) ;
512+ _logicalShorthands . Add ( name ) ;
513+ }
514+
382515 private void AddLonghand ( string name , LonghandCreator creator , bool animatable = false , bool font = false )
383516 {
384517 _longhandsBuilder . Add ( name , creator ) ;
@@ -458,7 +591,10 @@ public string[] GetLonghands(string name)
458591
459592 public IEnumerable < string > GetShorthands ( string name )
460593 {
461- return from mapping in _mappings where mapping . Value . Contains ( name , StringComparison . OrdinalIgnoreCase ) select mapping . Key ;
594+ return from mapping in _mappings
595+ where ! _logicalShorthands . Contains ( mapping . Key )
596+ && mapping . Value . Contains ( name , StringComparison . OrdinalIgnoreCase )
597+ select mapping . Key ;
462598 }
463599
464600 private delegate Property LonghandCreator ( ) ;
0 commit comments