@@ -86,7 +86,10 @@ - (void)setDefaults {
8686 @([StrikethroughStyle getStyleType ]): [[StrikethroughStyle alloc ] initWithEditor: self ],
8787 @([InlineCodeStyle getStyleType ]): [[InlineCodeStyle alloc ] initWithEditor: self ],
8888 @([LinkStyle getStyleType ]): [[LinkStyle alloc ] initWithEditor: self ],
89- @([MentionStyle getStyleType ]): [[MentionStyle alloc ] initWithEditor: self ]
89+ @([MentionStyle getStyleType ]): [[MentionStyle alloc ] initWithEditor: self ],
90+ @([H1Style getStyleType ]): [[H1Style alloc ] initWithEditor: self ],
91+ @([H2Style getStyleType ]): [[H2Style alloc ] initWithEditor: self ],
92+ @([H3Style getStyleType ]): [[H3Style alloc ] initWithEditor: self ]
9093 };
9194
9295 _conflictingStyles = @{
@@ -96,7 +99,10 @@ - (void)setDefaults {
9699 @([StrikethroughStyle getStyleType ]) : @[],
97100 @([InlineCodeStyle getStyleType ]) : @[@([LinkStyle getStyleType ]), @([MentionStyle getStyleType ])],
98101 @([LinkStyle getStyleType ]): @[@([InlineCodeStyle getStyleType ]), @([LinkStyle getStyleType ]), @([MentionStyle getStyleType ])],
99- @([MentionStyle getStyleType ]): @[@([InlineCodeStyle getStyleType ]), @([LinkStyle getStyleType ])]
102+ @([MentionStyle getStyleType ]): @[@([InlineCodeStyle getStyleType ]), @([LinkStyle getStyleType ])],
103+ @([H1Style getStyleType ]): @[@([H2Style getStyleType ]), @([H3Style getStyleType ])],
104+ @([H2Style getStyleType ]): @[@([H1Style getStyleType ]), @([H3Style getStyleType ])],
105+ @([H3Style getStyleType ]): @[@([H1Style getStyleType ]), @([H2Style getStyleType ])]
100106 };
101107
102108 _blockingStyles = @{
@@ -107,6 +113,9 @@ - (void)setDefaults {
107113 @([InlineCodeStyle getStyleType ]) : @[],
108114 @([LinkStyle getStyleType ]): @[],
109115 @([MentionStyle getStyleType ]): @[],
116+ @([H1Style getStyleType ]): @[],
117+ @([H2Style getStyleType ]): @[],
118+ @([H3Style getStyleType ]): @[]
110119 };
111120
112121 _editorParser = [[EditorParser alloc ] initWithEditor: self ];
@@ -320,15 +329,18 @@ - (CGSize)measureSize:(CGFloat)maxWidth {
320329 // edge case: empty input should still be of a height of a single line, so we add a mock "I" character
321330 if ([currentStr length ] == 0 ) {
322331 [currentStr appendAttributedString:
323- [[NSAttributedString alloc ] initWithString: @" I" attributes: defaultTypingAttributes ]
332+ [[NSAttributedString alloc ] initWithString: @" I" attributes: textView.typingAttributes ]
324333 ];
325334 }
326335
327336 // edge case: trailing newlines aren't counted towards height calculations, so we add a mock "I" character
328- if ([currentStr length ] > 0 && [[currentStr.string substringFromIndex: [currentStr length ] - 1 ] isEqualToString: @" \n " ]) {
329- [currentStr appendAttributedString:
330- [[NSAttributedString alloc ] initWithString: @" I" attributes: defaultTypingAttributes]
331- ];
337+ if (currentStr.length > 0 ) {
338+ unichar lastChar = [currentStr.string characterAtIndex: currentStr.length-1 ];
339+ if ([[NSCharacterSet newlineCharacterSet ] characterIsMember: lastChar]) {
340+ [currentStr appendAttributedString:
341+ [[NSAttributedString alloc ] initWithString: @" I" attributes: textView.typingAttributes]
342+ ];
343+ }
332344 }
333345
334346 CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString ((CFAttributedStringRef)currentStr);
@@ -455,9 +467,9 @@ - (void)tryUpdatingActiveStyles {
455467 .isInlineCode = [_activeStyles containsObject: @([InlineCodeStyle getStyleType ])],
456468 .isLink = [_activeStyles containsObject: @([LinkStyle getStyleType ])],
457469 .isMention = [_activeStyles containsObject: @([MentionStyle getStyleType ])],
458- .isH1 = NO , // [_activeStyles containsObject: @([H1Style getStyleType])],
459- .isH2 = NO , // [_activeStyles containsObject: @([H2Style getStyleType])],
460- .isH3 = NO , // [_activeStyles containsObject: @([H3Style getStyleType])],
470+ .isH1 = [_activeStyles containsObject: @([H1Style getStyleType ])],
471+ .isH2 = [_activeStyles containsObject: @([H2Style getStyleType ])],
472+ .isH3 = [_activeStyles containsObject: @([H3Style getStyleType ])],
461473 .isCodeBlock = NO , // [_activeStyles containsObject: @([CodeBlockStyle getStyleType])],
462474 .isBlockQuote = NO , // [_activeStyles containsObject: @([BlockQuoteStyle getStyleType])],
463475 .isUnorderedList = NO , // [_activeStyles containsObject: @([UnorderedListStyle getStyleType])],
@@ -518,6 +530,12 @@ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args {
518530 } else if ([commandName isEqualToString: @" startMention" ]) {
519531 NSString *indicator = (NSString *)args[0 ];
520532 [self startMentionWithIndicator: indicator];
533+ } else if ([commandName isEqualToString: @" toggleH1" ]) {
534+ [self toggleParagraphStyle: [H1Style getStyleType ]];
535+ } else if ([commandName isEqualToString: @" toggleH2" ]) {
536+ [self toggleParagraphStyle: [H2Style getStyleType ]];
537+ } else if ([commandName isEqualToString: @" toggleH3" ]) {
538+ [self toggleParagraphStyle: [H3Style getStyleType ]];
521539 }
522540}
523541
@@ -606,6 +624,19 @@ - (void)toggleRegularStyle:(StyleType)type {
606624 }
607625}
608626
627+ - (void )toggleParagraphStyle : (StyleType)type {
628+ id <BaseStyleProtocol> styleClass = stylesDict[@(type)];
629+ // we always pass whole paragraph/s range to these styles
630+ NSRange paragraphRange = [textView.textStorage.string paragraphRangeForRange: textView.selectedRange];
631+
632+ if ([self handleStyleBlocksAndConflicts: type range: paragraphRange]) {
633+ [styleClass applyStyle: paragraphRange];
634+ // height needs to be checked as well with paragraph styles
635+ [self tryUpdatingHeight ];
636+ [self tryUpdatingActiveStyles ];
637+ }
638+ }
639+
609640- (void )addLinkAt : (NSInteger )start end : (NSInteger )end text : (NSString *)text url : (NSString *)url {
610641 LinkStyle *linkStyleClass = (LinkStyle *)stylesDict[@([LinkStyle getStyleType ])];
611642 if (linkStyleClass == nullptr ) { return ; }
0 commit comments