react-native-enriched-markdown 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +80 -8
  2. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerDelegate.java +17 -2
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedMarkdownTextManagerInterface.java +6 -1
  4. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.cpp +9 -0
  5. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/EventEmitters.h +6 -0
  6. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.cpp +28 -3
  7. package/android/generated/jni/react/renderer/components/EnrichedMarkdownTextSpec/Props.h +225 -1
  8. package/android/src/main/cpp/jni-adapter.cpp +28 -11
  9. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownText.kt +132 -15
  10. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextLayoutManager.kt +1 -16
  11. package/android/src/main/java/com/swmansion/enriched/markdown/EnrichedMarkdownTextManager.kt +67 -13
  12. package/android/src/main/java/com/swmansion/enriched/markdown/MeasurementStore.kt +241 -21
  13. package/android/src/main/java/com/swmansion/enriched/markdown/accessibility/MarkdownAccessibilityHelper.kt +279 -0
  14. package/android/src/main/java/com/swmansion/enriched/markdown/events/LinkLongPressEvent.kt +23 -0
  15. package/android/src/main/java/com/swmansion/enriched/markdown/parser/MarkdownASTNode.kt +2 -0
  16. package/android/src/main/java/com/swmansion/enriched/markdown/parser/Parser.kt +17 -3
  17. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/BlockquoteRenderer.kt +13 -18
  18. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeBlockRenderer.kt +23 -24
  19. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/CodeRenderer.kt +1 -0
  20. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/DocumentRenderer.kt +2 -1
  21. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/EmphasisRenderer.kt +2 -1
  22. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/HeadingRenderer.kt +18 -2
  23. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ImageRenderer.kt +22 -6
  24. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LineBreakRenderer.kt +1 -0
  25. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/LinkRenderer.kt +3 -2
  26. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListItemRenderer.kt +2 -1
  27. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ListRenderer.kt +16 -9
  28. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/NodeRenderer.kt +5 -1
  29. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ParagraphRenderer.kt +23 -9
  30. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/Renderer.kt +24 -10
  31. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/SpanStyleCache.kt +1 -0
  32. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrikethroughRenderer.kt +27 -0
  33. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/StrongRenderer.kt +2 -1
  34. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/TextRenderer.kt +1 -0
  35. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/ThematicBreakRenderer.kt +1 -0
  36. package/android/src/main/java/com/swmansion/enriched/markdown/renderer/UnderlineRenderer.kt +27 -0
  37. package/android/src/main/java/com/swmansion/enriched/markdown/spans/ImageSpan.kt +1 -0
  38. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LineHeightSpan.kt +8 -17
  39. package/android/src/main/java/com/swmansion/enriched/markdown/spans/LinkSpan.kt +19 -5
  40. package/android/src/main/java/com/swmansion/enriched/markdown/spans/MarginBottomSpan.kt +1 -1
  41. package/android/src/main/java/com/swmansion/enriched/markdown/spans/StrikethroughSpan.kt +12 -0
  42. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BaseBlockStyle.kt +1 -0
  43. package/android/src/main/java/com/swmansion/enriched/markdown/styles/BlockquoteStyle.kt +3 -0
  44. package/android/src/main/java/com/swmansion/enriched/markdown/styles/CodeBlockStyle.kt +3 -0
  45. package/android/src/main/java/com/swmansion/enriched/markdown/styles/HeadingStyle.kt +5 -1
  46. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ImageStyle.kt +3 -1
  47. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ListStyle.kt +3 -0
  48. package/android/src/main/java/com/swmansion/enriched/markdown/styles/ParagraphStyle.kt +5 -1
  49. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StrikethroughStyle.kt +17 -0
  50. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleConfig.kt +32 -1
  51. package/android/src/main/java/com/swmansion/enriched/markdown/styles/StyleParser.kt +22 -5
  52. package/android/src/main/java/com/swmansion/enriched/markdown/styles/TextAlignment.kt +32 -0
  53. package/android/src/main/java/com/swmansion/enriched/markdown/styles/UnderlineStyle.kt +17 -0
  54. package/android/src/main/java/com/swmansion/enriched/markdown/utils/HTMLGenerator.kt +23 -5
  55. package/android/src/main/java/com/swmansion/enriched/markdown/utils/LinkLongPressMovementMethod.kt +121 -0
  56. package/android/src/main/java/com/swmansion/enriched/markdown/utils/MarkdownExtractor.kt +10 -0
  57. package/android/src/main/java/com/swmansion/enriched/markdown/utils/Utils.kt +58 -56
  58. package/android/src/main/jni/CMakeLists.txt +1 -13
  59. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.cpp +0 -13
  60. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextShadowNode.h +2 -14
  61. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/conversions.h +3 -0
  62. package/cpp/parser/MD4CParser.cpp +21 -8
  63. package/cpp/parser/MD4CParser.hpp +5 -1
  64. package/cpp/parser/MarkdownASTNode.hpp +2 -0
  65. package/ios/EnrichedMarkdownText.mm +356 -29
  66. package/ios/attachments/{ImageAttachment.h → EnrichedMarkdownImageAttachment.h} +1 -1
  67. package/ios/attachments/{ImageAttachment.m → EnrichedMarkdownImageAttachment.m} +4 -4
  68. package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.cpp +9 -0
  69. package/ios/generated/EnrichedMarkdownTextSpec/EventEmitters.h +6 -0
  70. package/ios/generated/EnrichedMarkdownTextSpec/Props.cpp +28 -3
  71. package/ios/generated/EnrichedMarkdownTextSpec/Props.h +225 -1
  72. package/ios/parser/MarkdownASTNode.h +2 -0
  73. package/ios/parser/MarkdownParser.h +9 -0
  74. package/ios/parser/MarkdownParser.mm +31 -2
  75. package/ios/parser/MarkdownParserBridge.mm +13 -3
  76. package/ios/renderer/AttributedRenderer.h +2 -0
  77. package/ios/renderer/AttributedRenderer.m +52 -19
  78. package/ios/renderer/BlockquoteRenderer.m +7 -6
  79. package/ios/renderer/CodeBlockRenderer.m +9 -8
  80. package/ios/renderer/HeadingRenderer.m +31 -24
  81. package/ios/renderer/ImageRenderer.m +31 -10
  82. package/ios/renderer/ListItemRenderer.m +51 -39
  83. package/ios/renderer/ListRenderer.m +21 -18
  84. package/ios/renderer/ParagraphRenderer.m +27 -16
  85. package/ios/renderer/RenderContext.h +17 -0
  86. package/ios/renderer/RenderContext.m +66 -2
  87. package/ios/renderer/RendererFactory.m +6 -0
  88. package/ios/renderer/StrikethroughRenderer.h +6 -0
  89. package/ios/renderer/StrikethroughRenderer.m +40 -0
  90. package/ios/renderer/UnderlineRenderer.h +6 -0
  91. package/ios/renderer/UnderlineRenderer.m +39 -0
  92. package/ios/styles/StyleConfig.h +46 -0
  93. package/ios/styles/StyleConfig.mm +351 -12
  94. package/ios/utils/AccessibilityInfo.h +35 -0
  95. package/ios/utils/AccessibilityInfo.m +24 -0
  96. package/ios/utils/CodeBlockBackground.m +4 -9
  97. package/ios/utils/FontUtils.h +5 -0
  98. package/ios/utils/FontUtils.m +14 -0
  99. package/ios/utils/HTMLGenerator.m +21 -7
  100. package/ios/utils/MarkdownAccessibilityElementBuilder.h +45 -0
  101. package/ios/utils/MarkdownAccessibilityElementBuilder.m +323 -0
  102. package/ios/utils/MarkdownExtractor.m +18 -5
  103. package/ios/utils/ParagraphStyleUtils.h +10 -2
  104. package/ios/utils/ParagraphStyleUtils.m +57 -2
  105. package/ios/utils/PasteboardUtils.h +1 -1
  106. package/ios/utils/PasteboardUtils.m +3 -3
  107. package/lib/module/EnrichedMarkdownText.js +33 -2
  108. package/lib/module/EnrichedMarkdownText.js.map +1 -1
  109. package/lib/module/EnrichedMarkdownTextNativeComponent.ts +83 -3
  110. package/lib/module/index.js +0 -1
  111. package/lib/module/index.js.map +1 -1
  112. package/lib/module/normalizeMarkdownStyle.js +58 -14
  113. package/lib/module/normalizeMarkdownStyle.js.map +1 -1
  114. package/lib/typescript/src/EnrichedMarkdownText.d.ts +85 -3
  115. package/lib/typescript/src/EnrichedMarkdownText.d.ts.map +1 -1
  116. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts +75 -1
  117. package/lib/typescript/src/EnrichedMarkdownTextNativeComponent.d.ts.map +1 -1
  118. package/lib/typescript/src/index.d.ts +2 -3
  119. package/lib/typescript/src/index.d.ts.map +1 -1
  120. package/lib/typescript/src/normalizeMarkdownStyle.d.ts.map +1 -1
  121. package/package.json +1 -1
  122. package/src/EnrichedMarkdownText.tsx +133 -5
  123. package/src/EnrichedMarkdownTextNativeComponent.ts +83 -3
  124. package/src/index.tsx +5 -2
  125. package/src/normalizeMarkdownStyle.ts +46 -0
  126. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.cpp +0 -9
  127. package/android/src/main/jni/react/renderer/components/EnrichedMarkdownTextSpec/MarkdownTextState.h +0 -25
@@ -20,12 +20,9 @@
20
20
  return self;
21
21
  }
22
22
 
23
- #pragma mark - Rendering
24
-
25
23
  - (void)renderNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output context:(RenderContext *)context
26
24
  {
27
- // 1. Context-Aware Styling
28
- // We only set the block style if no parent element (like a list or blockquote) has already established one.
25
+ // Only set block style if a parent element (e.g. List, Blockquote) hasn't already established one
29
26
  BOOL isTopLevel = (context.currentBlockType == BlockTypeNone);
30
27
 
31
28
  if (isTopLevel) {
@@ -33,37 +30,51 @@
33
30
  }
34
31
 
35
32
  NSUInteger start = output.length;
33
+ BOOL shouldApplyMargin =
34
+ (context.currentBlockType == BlockTypeNone || context.currentBlockType == BlockTypeParagraph);
35
+
36
+ // Detect if the paragraph is a wrapper for a standalone image to use image-specific spacing
37
+ BOOL isBlockImage = (node.children.count == 1 && ((MarkdownASTNode *)node.children[0]).type == MarkdownNodeTypeImage);
38
+ CGFloat marginTop = isBlockImage ? _config.imageMarginTop : _config.paragraphMarginTop;
39
+
40
+ NSUInteger contentStart = start;
41
+
42
+ // Handle leading margin for the first element in the document (Index 0 check)
43
+ if (shouldApplyMargin && start == 0) {
44
+ NSUInteger offset = applyBlockSpacingBefore(output, 0, marginTop);
45
+ contentStart += offset;
46
+ start += offset;
47
+ }
48
+
36
49
  @try {
37
50
  [_rendererFactory renderChildrenOfNode:node into:output context:context];
38
51
  } @finally {
39
- // Only clear the style if this paragraph was the one that set it.
40
52
  if (isTopLevel) {
41
53
  [context clearBlockStyle];
42
54
  }
43
55
  }
44
56
 
45
- // 2. Geometry and Spacing Logic
46
57
  if (output.length <= start)
47
58
  return;
48
59
  NSRange range = NSMakeRange(start, output.length - start);
49
60
 
50
- // Check if this paragraph is purely a wrapper for a block image.
51
- // Images often require different spacing and should not have standard line height applied.
52
- BOOL isBlockImage = (node.children.count == 1 && ((MarkdownASTNode *)node.children[0]).type == MarkdownNodeTypeImage);
53
-
54
- // Apply line height only for text paragraphs to avoid unwanted gaps above/below images.
61
+ // Avoid standard line height on block images to prevent vertical alignment issues
55
62
  if (!isBlockImage) {
56
63
  applyLineHeight(output, range, _config.paragraphLineHeight);
57
64
  }
58
65
 
59
- // 3. Margin Application
60
- // Only top-level paragraphs apply bottom margins; nested paragraphs defer to their parents.
66
+ applyTextAlignment(output, range, _config.paragraphTextAlign);
67
+
68
+ // Apply marginTop for non-index-0 elements using paragraphSpacingBefore
69
+ if (shouldApplyMargin && contentStart != 1) {
70
+ applyParagraphSpacingBefore(output, range, marginTop);
71
+ }
72
+
61
73
  CGFloat marginBottom = 0;
62
- if (isTopLevel) {
74
+ if (shouldApplyMargin) {
63
75
  marginBottom = isBlockImage ? _config.imageMarginBottom : _config.paragraphMarginBottom;
64
76
  }
65
-
66
- applyParagraphSpacing(output, start, marginBottom);
77
+ applyParagraphSpacingAfter(output, start, marginBottom);
67
78
  }
68
79
 
69
80
  @end
@@ -25,6 +25,15 @@ typedef NS_ENUM(NSInteger, ListType) { ListTypeUnordered, ListTypeOrdered };
25
25
  @interface RenderContext : NSObject
26
26
  @property (nonatomic, strong) NSMutableArray<NSValue *> *linkRanges;
27
27
  @property (nonatomic, strong) NSMutableArray<NSString *> *linkURLs;
28
+ @property (nonatomic, strong) NSMutableArray<NSValue *> *headingRanges;
29
+ @property (nonatomic, strong) NSMutableArray<NSNumber *> *headingLevels;
30
+ @property (nonatomic, strong) NSMutableArray<NSValue *> *imageRanges;
31
+ @property (nonatomic, strong) NSMutableArray<NSString *> *imageAltTexts;
32
+ @property (nonatomic, strong) NSMutableArray<NSString *> *imageURLs;
33
+ @property (nonatomic, strong) NSMutableArray<NSValue *> *listItemRanges;
34
+ @property (nonatomic, strong) NSMutableArray<NSNumber *> *listItemPositions; // Position in parent list (1, 2, 3...)
35
+ @property (nonatomic, strong) NSMutableArray<NSNumber *> *listItemDepths; // Nesting depth (1 = top level, 2+ = nested)
36
+ @property (nonatomic, strong) NSMutableArray<NSNumber *> *listItemOrdered; // YES = ordered, NO = unordered (bullet)
28
37
  @property (nonatomic, assign) BlockType currentBlockType;
29
38
  @property (nonatomic, strong) BlockStyle *currentBlockStyle;
30
39
  @property (nonatomic, assign) NSInteger currentHeadingLevel;
@@ -32,6 +41,8 @@ typedef NS_ENUM(NSInteger, ListType) { ListTypeUnordered, ListTypeOrdered };
32
41
  @property (nonatomic, assign) NSInteger listDepth;
33
42
  @property (nonatomic, assign) ListType listType;
34
43
  @property (nonatomic, assign) NSInteger listItemNumber;
44
+ @property (nonatomic, assign) BOOL allowFontScaling;
45
+ @property (nonatomic, assign) CGFloat maxFontSizeMultiplier;
35
46
 
36
47
  - (instancetype)init;
37
48
  - (void)reset;
@@ -40,6 +51,12 @@ typedef NS_ENUM(NSInteger, ListType) { ListTypeUnordered, ListTypeOrdered };
40
51
  - (NSMutableParagraphStyle *)spacerStyleWithHeight:(CGFloat)height spacing:(CGFloat)spacing;
41
52
  - (NSMutableParagraphStyle *)blockSpacerStyleWithMargin:(CGFloat)margin;
42
53
  - (void)registerLinkRange:(NSRange)range url:(NSString *)url;
54
+ - (void)registerHeadingRange:(NSRange)range level:(NSInteger)level text:(NSString *)text;
55
+ - (void)registerImageRange:(NSRange)range altText:(NSString *)altText url:(NSString *)url;
56
+ - (void)registerListItemRange:(NSRange)range
57
+ position:(NSInteger)position
58
+ depth:(NSInteger)depth
59
+ isOrdered:(BOOL)isOrdered;
43
60
  - (void)setBlockStyle:(BlockType)type
44
61
  fontSize:(CGFloat)fontSize
45
62
  fontFamily:(NSString *)fontFamily
@@ -1,5 +1,6 @@
1
1
  #import "RenderContext.h"
2
2
  #import "CodeBackground.h"
3
+ #import "FontUtils.h"
3
4
  #import <React/RCTFont.h>
4
5
 
5
6
  @implementation BlockStyle
@@ -16,8 +17,19 @@
16
17
  if (self = [super init]) {
17
18
  _linkRanges = [NSMutableArray array];
18
19
  _linkURLs = [NSMutableArray array];
20
+ _headingRanges = [NSMutableArray array];
21
+ _headingLevels = [NSMutableArray array];
22
+ _imageRanges = [NSMutableArray array];
23
+ _imageAltTexts = [NSMutableArray array];
24
+ _imageURLs = [NSMutableArray array];
25
+ _listItemRanges = [NSMutableArray array];
26
+ _listItemPositions = [NSMutableArray array];
27
+ _listItemDepths = [NSMutableArray array];
28
+ _listItemOrdered = [NSMutableArray array];
19
29
  _fontCache = [NSMutableDictionary dictionary];
20
30
  _currentBlockStyle = [[BlockStyle alloc] init];
31
+ _allowFontScaling = YES;
32
+ _maxFontSizeMultiplier = 0;
21
33
 
22
34
  NSMutableParagraphStyle *spacerTemplate = [[NSMutableParagraphStyle alloc] init];
23
35
  _baseSpacerTemplate = [spacerTemplate copy];
@@ -36,8 +48,11 @@
36
48
 
37
49
  - (UIFont *)cachedFontForSize:(CGFloat)fontSize family:(NSString *)fontFamily weight:(NSString *)fontWeight
38
50
  {
51
+ CGFloat effectiveMultiplier = _allowFontScaling ? RCTFontSizeMultiplierWithMax(_maxFontSizeMultiplier) : 1.0;
52
+
39
53
  NSString *weightKey = (fontWeight.length > 0) ? fontWeight : @"";
40
- NSString *key = [NSString stringWithFormat:@"%.1f|%@|%@", fontSize, fontFamily ?: @"", weightKey];
54
+ NSString *key =
55
+ [NSString stringWithFormat:@"%.1f|%@|%@|%.2f", fontSize, fontFamily ?: @"", weightKey, effectiveMultiplier];
41
56
 
42
57
  UIFont *cached = _fontCache[key];
43
58
  if (cached) {
@@ -52,7 +67,7 @@
52
67
  weight:effectiveWeight
53
68
  style:nil
54
69
  variant:nil
55
- scaleMultiplier:1];
70
+ scaleMultiplier:effectiveMultiplier];
56
71
 
57
72
  if (font) {
58
73
  _fontCache[key] = font;
@@ -88,6 +103,46 @@
88
103
  [self.linkURLs addObject:url ?: @""];
89
104
  }
90
105
 
106
+ - (void)registerHeadingRange:(NSRange)range level:(NSInteger)level text:(NSString *)text
107
+ {
108
+ if (range.length == 0)
109
+ return;
110
+ [self.headingRanges addObject:[NSValue valueWithRange:range]];
111
+ [self.headingLevels addObject:@(level)];
112
+ }
113
+
114
+ - (void)registerImageRange:(NSRange)range altText:(NSString *)altText url:(NSString *)url
115
+ {
116
+ if (range.length == 0)
117
+ return;
118
+ [self.imageRanges addObject:[NSValue valueWithRange:range]];
119
+ [self.imageAltTexts addObject:altText ?: @""];
120
+ [self.imageURLs addObject:url ?: @""];
121
+ }
122
+
123
+ #pragma mark - Registration Helpers
124
+
125
+ - (void)registerListItemRange:(NSRange)range
126
+ position:(NSInteger)position
127
+ depth:(NSInteger)depth
128
+ isOrdered:(BOOL)isOrdered
129
+ {
130
+ if (![self isValidRange:range])
131
+ return;
132
+
133
+ [self.listItemRanges addObject:[NSValue valueWithRange:range]];
134
+ [self.listItemPositions addObject:@(position)];
135
+ [self.listItemDepths addObject:@(depth)];
136
+ [self.listItemOrdered addObject:@(isOrdered)];
137
+ }
138
+
139
+ #pragma mark - Private
140
+
141
+ - (BOOL)isValidRange:(NSRange)range
142
+ {
143
+ return range.length > 0 && range.location != NSNotFound;
144
+ }
145
+
91
146
  #pragma mark - Block Style Management
92
147
 
93
148
  /**
@@ -175,6 +230,15 @@
175
230
  {
176
231
  [_linkRanges removeAllObjects];
177
232
  [_linkURLs removeAllObjects];
233
+ [_headingRanges removeAllObjects];
234
+ [_headingLevels removeAllObjects];
235
+ [_imageRanges removeAllObjects];
236
+ [_imageAltTexts removeAllObjects];
237
+ [_imageURLs removeAllObjects];
238
+ [_listItemRanges removeAllObjects];
239
+ [_listItemPositions removeAllObjects];
240
+ [_listItemDepths removeAllObjects];
241
+ [_listItemOrdered removeAllObjects];
178
242
  [self clearBlockStyle];
179
243
 
180
244
  _blockquoteDepth = 0;
@@ -10,10 +10,12 @@
10
10
  #import "ListRenderer.h"
11
11
  #import "ParagraphRenderer.h"
12
12
  #import "RenderContext.h"
13
+ #import "StrikethroughRenderer.h"
13
14
  #import "StrongRenderer.h"
14
15
  #import "StyleConfig.h"
15
16
  #import "TextRenderer.h"
16
17
  #import "ThematicBreakRenderer.h"
18
+ #import "UnderlineRenderer.h"
17
19
 
18
20
  @implementation RendererFactory {
19
21
  StyleConfig *_config;
@@ -64,6 +66,10 @@
64
66
  return [[StrongRenderer alloc] initWithRendererFactory:self config:_config];
65
67
  case MarkdownNodeTypeEmphasis:
66
68
  return [[EmphasisRenderer alloc] initWithRendererFactory:self config:_config];
69
+ case MarkdownNodeTypeStrikethrough:
70
+ return [[StrikethroughRenderer alloc] initWithRendererFactory:self config:_config];
71
+ case MarkdownNodeTypeUnderline:
72
+ return [[UnderlineRenderer alloc] initWithRendererFactory:self config:_config];
67
73
  case MarkdownNodeTypeParagraph:
68
74
  return [[ParagraphRenderer alloc] initWithRendererFactory:self config:_config];
69
75
  case MarkdownNodeTypeLink:
@@ -0,0 +1,6 @@
1
+ #pragma once
2
+ #import "NodeRenderer.h"
3
+
4
+ @interface StrikethroughRenderer : NSObject <NodeRenderer>
5
+ - (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config;
6
+ @end
@@ -0,0 +1,40 @@
1
+ #import "StrikethroughRenderer.h"
2
+ #import "MarkdownASTNode.h"
3
+ #import "RenderContext.h"
4
+ #import "RendererFactory.h"
5
+ #import "StyleConfig.h"
6
+
7
+ @implementation StrikethroughRenderer {
8
+ RendererFactory *_rendererFactory;
9
+ StyleConfig *_config;
10
+ }
11
+
12
+ - (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config
13
+ {
14
+ if (self = [super init]) {
15
+ _rendererFactory = rendererFactory;
16
+ _config = (StyleConfig *)config;
17
+ }
18
+ return self;
19
+ }
20
+
21
+ #pragma mark - Rendering
22
+
23
+ - (void)renderNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output context:(RenderContext *)context
24
+ {
25
+ NSUInteger start = output.length;
26
+ [_rendererFactory renderChildrenOfNode:node into:output context:context];
27
+
28
+ NSRange range = NSMakeRange(start, output.length - start);
29
+ if (range.length == 0)
30
+ return;
31
+
32
+ // Apply strikethrough style
33
+ [output addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
34
+
35
+ // Apply strikethrough line color (not text color)
36
+ UIColor *strikethroughColor = [_config strikethroughColor];
37
+ [output addAttribute:NSStrikethroughColorAttributeName value:strikethroughColor range:range];
38
+ }
39
+
40
+ @end
@@ -0,0 +1,6 @@
1
+ #import "NodeRenderer.h"
2
+ #import <Foundation/Foundation.h>
3
+
4
+ @interface UnderlineRenderer : NSObject <NodeRenderer>
5
+ - (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config;
6
+ @end
@@ -0,0 +1,39 @@
1
+ #import "UnderlineRenderer.h"
2
+ #import "MarkdownASTNode.h"
3
+ #import "RenderContext.h"
4
+ #import "RendererFactory.h"
5
+ #import "StyleConfig.h"
6
+
7
+ @implementation UnderlineRenderer {
8
+ RendererFactory *_rendererFactory;
9
+ StyleConfig *_config;
10
+ }
11
+
12
+ - (instancetype)initWithRendererFactory:(id)rendererFactory config:(id)config
13
+ {
14
+ if (self = [super init]) {
15
+ _rendererFactory = rendererFactory;
16
+ _config = (StyleConfig *)config;
17
+ }
18
+ return self;
19
+ }
20
+
21
+ #pragma mark - Rendering
22
+
23
+ - (void)renderNode:(MarkdownASTNode *)node into:(NSMutableAttributedString *)output context:(RenderContext *)context
24
+ {
25
+ NSUInteger start = output.length;
26
+ [_rendererFactory renderChildrenOfNode:node into:output context:context];
27
+
28
+ NSRange range = NSMakeRange(start, output.length - start);
29
+ if (range.length == 0)
30
+ return;
31
+
32
+ [output addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
33
+
34
+ UIColor *underlineColor = [_config underlineColor];
35
+
36
+ [output addAttribute:NSUnderlineColorAttributeName value:underlineColor range:range];
37
+ }
38
+
39
+ @end
@@ -3,6 +3,10 @@
3
3
 
4
4
  @interface StyleConfig : NSObject <NSCopying>
5
5
  - (instancetype)init;
6
+ - (CGFloat)fontScaleMultiplier;
7
+ - (void)setFontScaleMultiplier:(CGFloat)newValue;
8
+ - (CGFloat)maxFontSizeMultiplier;
9
+ - (void)setMaxFontSizeMultiplier:(CGFloat)newValue;
6
10
  // Primary font properties
7
11
  - (UIColor *)primaryColor;
8
12
  - (void)setPrimaryColor:(UIColor *)newValue;
@@ -22,10 +26,14 @@
22
26
  - (void)setParagraphFontWeight:(NSString *)newValue;
23
27
  - (UIColor *)paragraphColor;
24
28
  - (void)setParagraphColor:(UIColor *)newValue;
29
+ - (CGFloat)paragraphMarginTop;
30
+ - (void)setParagraphMarginTop:(CGFloat)newValue;
25
31
  - (CGFloat)paragraphMarginBottom;
26
32
  - (void)setParagraphMarginBottom:(CGFloat)newValue;
27
33
  - (CGFloat)paragraphLineHeight;
28
34
  - (void)setParagraphLineHeight:(CGFloat)newValue;
35
+ - (NSTextAlignment)paragraphTextAlign;
36
+ - (void)setParagraphTextAlign:(NSTextAlignment)newValue;
29
37
  - (UIFont *)paragraphFont;
30
38
  // H1 properties
31
39
  - (CGFloat)h1FontSize;
@@ -36,10 +44,14 @@
36
44
  - (void)setH1FontWeight:(NSString *)newValue;
37
45
  - (UIColor *)h1Color;
38
46
  - (void)setH1Color:(UIColor *)newValue;
47
+ - (CGFloat)h1MarginTop;
48
+ - (void)setH1MarginTop:(CGFloat)newValue;
39
49
  - (CGFloat)h1MarginBottom;
40
50
  - (void)setH1MarginBottom:(CGFloat)newValue;
41
51
  - (CGFloat)h1LineHeight;
42
52
  - (void)setH1LineHeight:(CGFloat)newValue;
53
+ - (NSTextAlignment)h1TextAlign;
54
+ - (void)setH1TextAlign:(NSTextAlignment)newValue;
43
55
  - (UIFont *)h1Font;
44
56
  // H2 properties
45
57
  - (CGFloat)h2FontSize;
@@ -50,10 +62,14 @@
50
62
  - (void)setH2FontWeight:(NSString *)newValue;
51
63
  - (UIColor *)h2Color;
52
64
  - (void)setH2Color:(UIColor *)newValue;
65
+ - (CGFloat)h2MarginTop;
66
+ - (void)setH2MarginTop:(CGFloat)newValue;
53
67
  - (CGFloat)h2MarginBottom;
54
68
  - (void)setH2MarginBottom:(CGFloat)newValue;
55
69
  - (CGFloat)h2LineHeight;
56
70
  - (void)setH2LineHeight:(CGFloat)newValue;
71
+ - (NSTextAlignment)h2TextAlign;
72
+ - (void)setH2TextAlign:(NSTextAlignment)newValue;
57
73
  - (UIFont *)h2Font;
58
74
  // H3 properties
59
75
  - (CGFloat)h3FontSize;
@@ -64,10 +80,14 @@
64
80
  - (void)setH3FontWeight:(NSString *)newValue;
65
81
  - (UIColor *)h3Color;
66
82
  - (void)setH3Color:(UIColor *)newValue;
83
+ - (CGFloat)h3MarginTop;
84
+ - (void)setH3MarginTop:(CGFloat)newValue;
67
85
  - (CGFloat)h3MarginBottom;
68
86
  - (void)setH3MarginBottom:(CGFloat)newValue;
69
87
  - (CGFloat)h3LineHeight;
70
88
  - (void)setH3LineHeight:(CGFloat)newValue;
89
+ - (NSTextAlignment)h3TextAlign;
90
+ - (void)setH3TextAlign:(NSTextAlignment)newValue;
71
91
  - (UIFont *)h3Font;
72
92
  // H4 properties
73
93
  - (CGFloat)h4FontSize;
@@ -78,10 +98,14 @@
78
98
  - (void)setH4FontWeight:(NSString *)newValue;
79
99
  - (UIColor *)h4Color;
80
100
  - (void)setH4Color:(UIColor *)newValue;
101
+ - (CGFloat)h4MarginTop;
102
+ - (void)setH4MarginTop:(CGFloat)newValue;
81
103
  - (CGFloat)h4MarginBottom;
82
104
  - (void)setH4MarginBottom:(CGFloat)newValue;
83
105
  - (CGFloat)h4LineHeight;
84
106
  - (void)setH4LineHeight:(CGFloat)newValue;
107
+ - (NSTextAlignment)h4TextAlign;
108
+ - (void)setH4TextAlign:(NSTextAlignment)newValue;
85
109
  - (UIFont *)h4Font;
86
110
  // H5 properties
87
111
  - (CGFloat)h5FontSize;
@@ -92,10 +116,14 @@
92
116
  - (void)setH5FontWeight:(NSString *)newValue;
93
117
  - (UIColor *)h5Color;
94
118
  - (void)setH5Color:(UIColor *)newValue;
119
+ - (CGFloat)h5MarginTop;
120
+ - (void)setH5MarginTop:(CGFloat)newValue;
95
121
  - (CGFloat)h5MarginBottom;
96
122
  - (void)setH5MarginBottom:(CGFloat)newValue;
97
123
  - (CGFloat)h5LineHeight;
98
124
  - (void)setH5LineHeight:(CGFloat)newValue;
125
+ - (NSTextAlignment)h5TextAlign;
126
+ - (void)setH5TextAlign:(NSTextAlignment)newValue;
99
127
  - (UIFont *)h5Font;
100
128
  // H6 properties
101
129
  - (CGFloat)h6FontSize;
@@ -106,10 +134,14 @@
106
134
  - (void)setH6FontWeight:(NSString *)newValue;
107
135
  - (UIColor *)h6Color;
108
136
  - (void)setH6Color:(UIColor *)newValue;
137
+ - (CGFloat)h6MarginTop;
138
+ - (void)setH6MarginTop:(CGFloat)newValue;
109
139
  - (CGFloat)h6MarginBottom;
110
140
  - (void)setH6MarginBottom:(CGFloat)newValue;
111
141
  - (CGFloat)h6LineHeight;
112
142
  - (void)setH6LineHeight:(CGFloat)newValue;
143
+ - (NSTextAlignment)h6TextAlign;
144
+ - (void)setH6TextAlign:(NSTextAlignment)newValue;
113
145
  - (UIFont *)h6Font;
114
146
  // Link properties
115
147
  - (UIColor *)linkColor;
@@ -122,6 +154,12 @@
122
154
  // Emphasis properties
123
155
  - (UIColor *)emphasisColor;
124
156
  - (void)setEmphasisColor:(UIColor *)newValue;
157
+ // Strikethrough properties
158
+ - (UIColor *)strikethroughColor;
159
+ - (void)setStrikethroughColor:(UIColor *)newValue;
160
+ // Underline properties
161
+ - (UIColor *)underlineColor;
162
+ - (void)setUnderlineColor:(UIColor *)newValue;
125
163
  // Code properties
126
164
  - (UIColor *)codeColor;
127
165
  - (void)setCodeColor:(UIColor *)newValue;
@@ -134,6 +172,8 @@
134
172
  - (void)setImageHeight:(CGFloat)newValue;
135
173
  - (CGFloat)imageBorderRadius;
136
174
  - (void)setImageBorderRadius:(CGFloat)newValue;
175
+ - (CGFloat)imageMarginTop;
176
+ - (void)setImageMarginTop:(CGFloat)newValue;
137
177
  - (CGFloat)imageMarginBottom;
138
178
  - (void)setImageMarginBottom:(CGFloat)newValue;
139
179
  // Inline image properties
@@ -148,6 +188,8 @@
148
188
  - (void)setBlockquoteFontWeight:(NSString *)newValue;
149
189
  - (UIColor *)blockquoteColor;
150
190
  - (void)setBlockquoteColor:(UIColor *)newValue;
191
+ - (CGFloat)blockquoteMarginTop;
192
+ - (void)setBlockquoteMarginTop:(CGFloat)newValue;
151
193
  - (CGFloat)blockquoteMarginBottom;
152
194
  - (void)setBlockquoteMarginBottom:(CGFloat)newValue;
153
195
  - (CGFloat)blockquoteLineHeight;
@@ -170,6 +212,8 @@
170
212
  - (void)setListStyleFontWeight:(NSString *)newValue;
171
213
  - (UIColor *)listStyleColor;
172
214
  - (void)setListStyleColor:(UIColor *)newValue;
215
+ - (CGFloat)listStyleMarginTop;
216
+ - (void)setListStyleMarginTop:(CGFloat)newValue;
173
217
  - (CGFloat)listStyleMarginBottom;
174
218
  - (void)setListStyleMarginBottom:(CGFloat)newValue;
175
219
  - (CGFloat)listStyleLineHeight;
@@ -200,6 +244,8 @@
200
244
  - (void)setCodeBlockFontWeight:(NSString *)newValue;
201
245
  - (UIColor *)codeBlockColor;
202
246
  - (void)setCodeBlockColor:(UIColor *)newValue;
247
+ - (CGFloat)codeBlockMarginTop;
248
+ - (void)setCodeBlockMarginTop:(CGFloat)newValue;
203
249
  - (CGFloat)codeBlockMarginBottom;
204
250
  - (void)setCodeBlockMarginBottom:(CGFloat)newValue;
205
251
  - (CGFloat)codeBlockLineHeight;