@@ -197,6 +197,7 @@ public final class StyledTextLibrary: NativeLibrary {
197
197
self . define ( Procedure ( " load-styled-text " , loadStyledText) )
198
198
self . define ( Procedure ( " copy-styled-text " , copyStyledText) )
199
199
self . define ( Procedure ( " save-styled-text " , saveStyledText) )
200
+ self . define ( Procedure ( " html->styled-text " , htmlToStyledText) )
200
201
self . define ( Procedure ( " bytevector->styled-text " , bytevectorToStyledText) )
201
202
self . define ( Procedure ( " styled-text=? " , styledTextEquals) )
202
203
self . define ( Procedure ( " styled-text-string " , styledTextString) )
@@ -208,6 +209,9 @@ public final class StyledTextLibrary: NativeLibrary {
208
209
self . define ( Procedure ( " styled-text-remove! " , styledTextRemove) )
209
210
self . define ( Procedure ( " styled-text-attribute " , styledTextAttribute) )
210
211
self . define ( Procedure ( " styled-text-attributes " , styledTextAttributes) )
212
+ self . define ( Procedure ( " styled-text-first-attribute " , styledTextFirstAttribute) )
213
+ self . define ( Procedure ( " styled-text-first-attributes " , styledTextFirstAttributes) )
214
+ self . define ( Procedure ( " styled-text->html " , styledTextToHtml) )
211
215
self . define ( Procedure ( " styled-text->bytevector " , styledTextToBytevector) )
212
216
213
217
// Text styles
@@ -584,6 +588,16 @@ public final class StyledTextLibrary: NativeLibrary {
584
588
return . void
585
589
}
586
590
591
+ private func htmlToStyledText( html: Expr ) throws -> Expr {
592
+ let data = Data ( try html. asString ( ) . utf8)
593
+ let str = try NSMutableAttributedString (
594
+ data: data,
595
+ options: [ . documentType: NSAttributedString . DocumentType. html,
596
+ . characterEncoding: String . Encoding. utf8. rawValue] ,
597
+ documentAttributes: nil )
598
+ return . object( StyledText ( str) )
599
+ }
600
+
587
601
private func bytevectorToStyledText( expr: Expr , format: Expr , args: Arguments ) throws -> Expr {
588
602
let subvec = try BytevectorLibrary . subVector ( " bytevector->styled-text " , expr, args)
589
603
if let docType = self . documentType ( from: try format. asSymbol ( ) ) {
@@ -731,40 +745,67 @@ public final class StyledTextLibrary: NativeLibrary {
731
745
return . void
732
746
}
733
747
734
- private func styledTextAttribute( text: Expr , index : Expr , sym : Expr , args : Arguments ) throws -> Expr {
735
- guard let ( start , end ) = args . optional ( . false , . false ) else {
736
- throw RuntimeError . argumentCount ( of : " styled-text-attribute " , min : 3 , max : 5 ,
737
- args : . pair ( text , . pair ( index , . pair ( sym , . makeList ( args ) ) ) ) )
738
- }
748
+ private func styledTextAttribute( text: Expr ,
749
+ sym : Expr ,
750
+ index : Expr ,
751
+ start : Expr ? ,
752
+ end : Expr ? ) throws -> Expr {
739
753
let str = try self . styledText ( from: text) . value
740
- let idx = try index. asInt ( below: str. length + 1 )
741
754
guard let key = self . attributeKey ( from: try sym. asSymbol ( ) ) else {
742
755
throw RuntimeError . eval ( . unknownTextStyleAttribute, sym)
743
756
}
744
- let s = start. isTrue ? try start. asInt ( below: idx + 1 ) : 0
745
- let e = end. isTrue ? try end. asInt ( above: s, below: str. length + 1 ) : str. length
757
+ let idx = try index. asInt ( below: str. length + 1 )
758
+ let s = start != nil && start!. isTrue ? try start!. asInt ( below: idx + 1 ) : 0
759
+ let e = end != nil && end!. isTrue ? try end!. asInt ( above: s, below: str. length + 1 ) : str. length
746
760
var range = NSRange ( location: 0 , length: 0 )
747
761
if let value = str. attribute ( key,
748
762
at: idx,
749
763
longestEffectiveRange: & range,
750
764
in: NSRange ( location: s, length: e - s) ) ,
751
765
let res = try self . textStyleValue ( key: key, value: value) {
752
766
return . values( . pair( res, . pair( . pair( . fixnum( Int64 ( range. location) ) ,
753
- . fixnum( Int64 ( range. location + range. length) ) ) , . null) ) )
754
- } else {
755
- return . false
767
+ . fixnum( Int64 ( range. location + range. length) ) ) ,
768
+ . null) ) )
756
769
}
770
+ return . values( . pair( . false , . pair( . false , . null) ) )
757
771
}
758
772
759
- private func styledTextAttributes( text: Expr , index: Expr , args: Arguments ) throws -> Expr {
760
- guard let ( start, end) = args. optional ( . false , . false ) else {
761
- throw RuntimeError . argumentCount ( of: " styled-text-attributes " , min: 2 , max: 4 ,
762
- args: . pair( text, . pair( index, . makeList( args) ) ) )
773
+ private func styledTextFirstAttribute( text: Expr ,
774
+ sym: Expr ,
775
+ start: Expr ? ,
776
+ end: Expr ? ) throws -> Expr {
777
+ let str = try self . styledText ( from: text) . value
778
+ guard let key = self . attributeKey ( from: try sym. asSymbol ( ) ) else {
779
+ throw RuntimeError . eval ( . unknownTextStyleAttribute, sym)
763
780
}
781
+ let s = start != nil && start!. isTrue ? try start!. asInt ( below: str. length + 1 ) : 0
782
+ let e = end != nil && end!. isTrue ? try end!. asInt ( above: s, below: str. length + 1 ) : str. length
783
+ var res = Expr . undef
784
+ str. enumerateAttribute ( key,
785
+ in: NSRange ( location: s, length: e - s) ,
786
+ options: [ ] ,
787
+ using: { value, range, stop in
788
+ do {
789
+ if let value = value,
790
+ let val = try self . textStyleValue ( key: key, value: value) {
791
+ res = . values( . pair( val, . pair( . pair( . fixnum( Int64 ( range. location) ) ,
792
+ . fixnum( Int64 ( range. location + range. length) ) ) ,
793
+ . null) ) )
794
+ stop. pointee = false
795
+ }
796
+ } catch { }
797
+ } )
798
+ return res. isUndef ? . values( . pair( . false , . pair( . false , . null) ) ) : res
799
+ }
800
+
801
+ private func styledTextAttributes( text: Expr ,
802
+ index: Expr ,
803
+ start: Expr ? ,
804
+ end: Expr ? ) throws -> Expr {
764
805
let str = try self . styledText ( from: text) . value
765
806
let idx = try index. asInt ( below: str. length + 1 )
766
- let s = start. isTrue ? try start. asInt ( below: idx + 1 ) : 0
767
- let e = end. isTrue ? try end. asInt ( above: s, below: str. length + 1 ) : str. length
807
+ let s = start != nil && start! . isTrue ? try start! . asInt ( below: idx + 1 ) : 0
808
+ let e = end != nil && end! . isTrue ? try end! . asInt ( above: s, below: str. length + 1 ) : str. length
768
809
var range = NSRange ( location: 0 , length: 0 )
769
810
let res = TextStyle ( )
770
811
res. attributes = str. attributes ( at: idx,
@@ -776,6 +817,47 @@ public final class StyledTextLibrary: NativeLibrary {
776
817
. null) ) )
777
818
}
778
819
820
+ private func styledTextFirstAttributes( text: Expr , start: Expr ? , end: Expr ? ) throws -> Expr {
821
+ let str = try self . styledText ( from: text) . value
822
+ let s = start != nil && start!. isTrue ? try start!. asInt ( below: str. length + 1 ) : 0
823
+ let e = end != nil && end!. isTrue ? try end!. asInt ( above: s, below: str. length + 1 ) : str. length
824
+ var res = Expr . undef
825
+ str. enumerateAttributes ( in: NSRange ( location: s, length: e - s) ,
826
+ options: [ ] ,
827
+ using: { attribs, range, stop in
828
+ if !attribs. isEmpty {
829
+ let tstyle = TextStyle ( )
830
+ tstyle. attributes = attribs
831
+ res = . values( . pair( . object( tstyle) ,
832
+ . pair( . pair( . fixnum( Int64 ( range. location) ) ,
833
+ . fixnum( Int64 ( range. location + range. length) ) ) ,
834
+ . null) ) )
835
+ stop. pointee = true
836
+ }
837
+ } )
838
+ guard res. isUndef else {
839
+ return res
840
+ }
841
+ return . values( . pair( . false , . pair( . false , . null) ) )
842
+ }
843
+
844
+ private func styledTextToHtml( text: Expr ,
845
+ start: Expr ? ,
846
+ end: Expr ? ) throws -> Expr {
847
+ let str = try self . styledText ( from: text) . value
848
+ let e = ( end? . isTrue ?? false ) ? try end!. asInt ( below: str. length + 1 ) : str. length
849
+ let s = ( start? . isTrue ?? false ) ? try start!. asInt ( below: e + 1 ) : 0
850
+ let data = try str. data (
851
+ from: NSRange ( location: s, length: e - s) ,
852
+ documentAttributes: [ . documentType: NSAttributedString . DocumentType. html,
853
+ . characterEncoding: String . Encoding. utf8. rawValue] )
854
+ if let res = String ( data: data, encoding: String . Encoding. utf8) {
855
+ return . makeString( res)
856
+ } else {
857
+ return . false
858
+ }
859
+ }
860
+
779
861
private func styledTextToBytevector( text: Expr ,
780
862
format: Expr ,
781
863
start: Expr ? ,
0 commit comments