@@ -34,7 +34,14 @@ extension AttributeScopes {
3434
3535 @available ( macOS 13 , iOS 16 , tvOS 16 , watchOS 9 , * )
3636 public let durationField : DurationFieldAttribute
37-
37+
38+ /// The base writing direction of a paragraph.
39+ #if FOUNDATION_FRAMEWORK
40+ @_spi ( AttributedStringWritingDirection)
41+ #endif
42+ @available ( FoundationPreview 6 . 2 , * )
43+ public let writingDirection : WritingDirectionAttribute
44+
3845#if FOUNDATION_FRAMEWORK
3946 @available ( FoundationPreview 0 . 1 , * )
4047 public let agreementConcept : AgreementConceptAttribute
@@ -507,7 +514,21 @@ extension AttributeScopes.FoundationAttributes {
507514 case nanoseconds
508515 }
509516 }
510-
517+
518+ /// The attribute key for the base writing direction of a paragraph.
519+ #if FOUNDATION_FRAMEWORK
520+ @_spi ( AttributedStringWritingDirection)
521+ #endif
522+ @available ( FoundationPreview 6 . 2 , * )
523+ @frozen
524+ public enum WritingDirectionAttribute : CodableAttributedStringKey {
525+ public typealias Value = AttributedString . WritingDirection
526+ public static let name : String = " Foundation.WritingDirectionAttribute "
527+
528+ public static let runBoundaries : AttributedString . AttributeRunBoundaries ? = . paragraph
529+ public static let inheritedByAddedText = false
530+ }
531+
511532#if FOUNDATION_FRAMEWORK
512533 @available ( macOS 13 , iOS 16 , tvOS 16 , watchOS 9 , * )
513534 public struct LocalizedStringArgumentAttributes {
@@ -647,6 +668,9 @@ extension AttributeScopes.FoundationAttributes.ByteCountAttribute : Sendable {}
647668@available ( * , unavailable)
648669extension AttributeScopes . FoundationAttributes . DurationFieldAttribute : Sendable { }
649670
671+ @available ( * , unavailable)
672+ extension AttributeScopes . FoundationAttributes . WritingDirectionAttribute : Sendable { }
673+
650674#if FOUNDATION_FRAMEWORK
651675
652676@available ( macOS, unavailable, introduced: 14.0 )
@@ -819,3 +843,72 @@ extension AttributeScopes.FoundationAttributes.LocalizedNumberFormatAttribute.Va
819843}
820844
821845#endif // FOUNDATION_FRAMEWORK
846+
847+ extension AttributedString {
848+ /// The writing direction of a piece of text.
849+ ///
850+ /// Writing direction defines the base direction in which bidirectional text
851+ /// lays out its directional runs. A directional run is a contigous sequence
852+ /// of characters that all have the same effective directionality, which can
853+ /// be determined using the Unicode BiDi algorithm. The ``leftToRight``
854+ /// writing direction puts the directional run that is placed first in the
855+ /// storage leftmost, and places subsequent directional runs towards the
856+ /// right. The ``rightToLeft`` writing direction puts the directional run
857+ /// that is placed first in the storage rightmost, and places subsequent
858+ /// directional runs towards the left.
859+ ///
860+ /// Note that writing direction is a property separate from a text's
861+ /// alignment, its line layout direction, or its character direction.
862+ /// However, it is often used to determine the default alignment of a
863+ /// paragraph. E.g. English (a language with
864+ /// ``Locale/LanguageDirection-swift.enum/leftToRight``
865+ /// ``Locale/Language-swift.struct/characterDirection``) is usually aligned
866+ /// to the left, but may be centered or aligned to the right for special
867+ /// effect, or to be visually more appealing in a user interface.
868+ ///
869+ /// For bidirectional text to be perceived as laid out correctly, make sure
870+ /// that the writing direction is set to the value equivalent to the
871+ /// ``Locale/Language-swift.struct/characterDirection`` of the primary
872+ /// language in the text. E.g. an English sentence that contains some
873+ /// Arabic (a language with
874+ /// ``Locale/LanguageDirection-swift.enum/rightToLeft``
875+ /// ``Locale/Language-swift.struct/characterDirection``) words, should use
876+ /// a ``leftToRight`` writing direction. An Arabic sentence that contains
877+ /// some English words, should use a ``rightToLeft`` writing direction.
878+ ///
879+ /// Writing direction is always orthogonoal to the line layout direction
880+ /// chosen to display a certain text. The line layout direction is the
881+ /// direction in which a sequence of lines is placed in. E.g. English text
882+ /// is usually displayed with a line layout direction of
883+ /// ``Locale/LanguageDirection-swift.enum/topToBottom``. While languages do
884+ /// have an associated line language direction (see
885+ /// ``Locale/Language-swift.struct/lineLayoutDirection``), not all displays
886+ /// of text follow the line layout direction of the text's primary language.
887+ ///
888+ /// Horizontal script is script with a line layout direction of either
889+ /// ``Locale/LanguageDirection-swift.enum/topToBottom`` or
890+ /// ``Locale/LanguageDirection-swift.enum/bottomToTop``. Vertical script
891+ /// has a ``Locale/LanguageDirection-swift.enum/leftToRight`` or
892+ /// ``Locale/LanguageDirection-swift.enum/rightToLeft`` line layout
893+ /// direction. In vertical scripts, a writing direction of ``leftToRight``
894+ /// is interpreted as top-to-bottom and a writing direction of
895+ /// ``rightToLeft`` is interpreted as bottom-to-top.
896+ #if FOUNDATION_FRAMEWORK
897+ @_spi ( AttributedStringWritingDirection)
898+ #endif
899+ @available ( FoundationPreview 6 . 2 , * )
900+ @frozen
901+ public enum WritingDirection : Codable , Hashable , CaseIterable , Sendable {
902+ /// A left-to-right writing direction in horizontal script.
903+ ///
904+ /// - Note: In vertical scripts, this equivalent to a top-to-bottom
905+ /// writing direction.
906+ case leftToRight
907+
908+ /// A right-to-left writing direction in horizontal script.
909+ ///
910+ /// - Note: In vertical scripts, this equivalent to a bottom-to-top
911+ /// writing direction.
912+ case rightToLeft
913+ }
914+ }
0 commit comments