GONMarkupParser
轻松地从 XML/HTML 字符串构建 NSAttributedString。
示例
TL;DR;
NSString *inputText = @"Simple input text, using a preconfigured parser.\n<color value=\"red\">This text will be displayed in red</>.\n<font size="8">This one will be displayed in small</>.\nNow a list:\n<ul><li>First item</><li>Second item</><li><color value="blue">Third blue item</></><li><b><color value="green">Fourth bold green item<//>";
// No custom configuration, use default tags only
// Affect text to label
label.attributedText = [[GONMarkupParserManager sharedParser] attributedStringFromString:inputText
error:nil];
// You can also use [label setMarkedUpText:inputText];
需要更复杂的示例?
NSString *inputText = @"Simple input text, using a preconfigured parser.\n<red>This text will be displayed in red</>.\n<small>This one will be displayed in small</>.\n<pwet>This one is a custom one, to demonstrate how easy it is to declare a new markup.</>";
// Set your custom configuration here
#ifdef DEBUG
[GONMarkupParserManager sharedParser].logLevel = GONMarkupParserLogLevelAll; // Fuck yeah, error debugging
#endif
// Set default string configuration
[[GONMarkupParserManager sharedParser].defaultConfiguration setObject:[UIFont systemFontOfSize:25.0] forKey:NSFontAttributeName];
// Add a custom markup, that will center text when used, and display it in pink.
NSMutableParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
defaultParagraphStyle.alignment = NSTextAlignmentCenter;
[[GONMarkupParserManager sharedParser] addMarkup:[GONMarkupSimple simpleMarkup:@"pwet"
style:@{
NSParagraphStyleAttributeName : defaultParagraphStyle,
NSForegroundColorAttributeName : [@"pink" representedColor] // NSString+Color
}
mergingStrategy:GONMarkupSimpleMergingStrategyMergeAll]];
// Add add font markup, to display small text when encountered
[[GONMarkupParserManager sharedParser] addMarkup:[GONMarkupNamedFont namedFontMarkup:[UIFont systemFontOfSize:12.0] forTag:@"small"]];
// Add a convenient tag for red color
[[GONMarkupParserManager sharedParser] addMarkup:[GONMarkupNamedColor namedColorMarkup:[UIColor redColor]
forTag:@"red"]];
// Affect text to label
label.attributedText = [[GONMarkupParserManager sharedParser] attributedStringFromString:inputText
error:nil];
描述
在 iOS 中创建富文本可能很繁琐,需要很多代码。
GONMarkupParser 的主要目标是提供一个易于使用的语法,类似于 XML/HTML,但更灵活。
其他一些项目允许您从 HTML 构建 NSAttributedString,但我的主要目标是专注于文本语义。实际上,解析器将检测已注册的标记,并应用到文本上。
这样做的目的是能从相同的输入字符串生成不同的输出,而不修改其内容,而是修改标记样式。
GONMarkupParser 不是 解析 HTML 文件的开箱即用解决方案。
安装
CocoaPods: pod 'GONMarkupParser'
手动: 将项目中的 Classes 目录复制。您还需要 手动 安装 NSString+Color。诚恳地建议使用 cocoapods 吧 ;)
在项目中导入所需头文件。.pch 是一个好地方 ;)
GONMarkupParser_All.h 会引用所有库头文件,而 GONMarkupDefaultMarkups.h 只引用默认标记类。
用法
- 实例化一个新的 GONMarkupParser 或使用 + GONMarkupParserManager sharedParser。
- 设置您的解析器,添加支持的标签,默认标签,自定义标签等...
- 使用 - attributedStringFromString:error: 方法从 GONMarkupParser 解析输入字符串并获取结果 NSMutableAttributedString
- 您还可以使用 setMarkedUpText: 方法设置 UILabel / UITextField / UITextView / UIButton 上的文本
工作原理
要完全理解样式将如何应用于字符串,你必须想象一个由 后进先出 stack 组成的样式描述。
每次发现新的标记,都将在当前样式配置上保存,然后按堆栈堆放。新配置将是上一个配置,由当前标记配置更新。
每次发现闭合标记,当前样式配置将被弹出,并且恢复上一个配置。
语法
语法很简单,就像 XML,但是非标准的一个,易于书写,更快。
- 每个标记应该包含在 < 和 > 字符之间
- <strong>
- 就像 XML 一样,闭合标记应从 / 字符开始。您可以在闭合标签中省略标记名称。如果闭合标签与当前打开的标签不匹配,将会生成错误,不会崩溃,生成的文本可能不符合预期。
- </strong>,</>
- 您还可以使用 <//> 来关闭所有打开的标记。
示例
This is a <strong>valid</strong> string with some <color value="red">red <b>bold text</b></color>.
This is a <strong>valid</>string with some <color value="red">red <b>bold text</></>.
This is a <strong>valid</Hakuna> string with some <color value="red">red <b>bold text</mata></ta>. // Will work but generates an error
This is a <strong>valid</> string with some <color value="red">red <b>bold text<//>.
解析器
构造函数
GONMarkupParser 类提供两个类构造函数。
- + defaultMarkupParser 是一个注册了所有默认标签的解析器(更多信息请见默认标签摘要)
- + emptyMarkgiupParser 是一个没有注册任何标签的解析器
属性
解析器可以有一个预处理和后处理块,将在解析前后被调用。这允许您在解析前执行一些字符串替换操作,例如。
解析器有两个有趣的属性
- replaceNewLineCharactersFromInputString,用于从输入字符串中删除所有换行符字符。使用 br 标记来添加新行。默认为 NO。
- replaceHTMLCharactersFromOutputString,在解析后替换字符串中的所有 HTML 实体。默认为 YES。
defaultConfiguration 将包含生成字符串的默认样式配置。内容应该是有效的属性参数,您可以将其传递给 - addAttributes:range: 的 NSMutableAttributedString 对象。例如,要设置默认文字颜色,可以设置 NSForegroundColorAttributeName。
为了调试目的,您可以配置 debugLevel 属性。
assertOnError 属性也用于在遇到错误时生成断言。
配置
解析器必须注册一些标记才能正确处理字符串。
使用 - addMarkup:、- addMarkups:、- removeMarkups: 和 - removeAllMarkups 方法来实现此目的。
每次只能对一个解析器添加一个标记。
已注册字体
为了简化字体使用,可以使用 - registerFont:forKey: 方法注册字体,然后通过给定的键引用它们。
与 <font> 标记一起非常实用,允许您直接使用代码而不是完整的字体名称。您还可以使用 mainFont、titleFont 等代码来轻松地在所有字符串中更新它们。
GONMarkupParserManager
共享解析器
共享解析器可以供使用,因此您无需创建一个并在整个应用程序中引用它。
共享解析器默认配置了所有标记。
解析器注册
可以将一些解析器注册到此类,这样您就可以在应用程序的各个位置使用它们。
可用的UIKit类别
UILabel/UITextField/UITextView
为 UILabel、UITextField 和 UITextView 添加了 2 个方法,允许您使用标记的字符串轻松更新其属性字符串。
- - setMarkedUpText:(NSString *)text parser:(GONMarkupParser *)parser 将使用给定的解析器来处理字符串并生成属性字符串。
- - setMarkedUpText:(NSString *)text 将使用共享的解析器,即 [GONMarkupParserManager sharedParser]。
如果没有为 NSForegroundColorAttributeName、NSFontAttributeName 和 NSParagraphStyleAttributeName 设置解析器默认配置,则将使用默认的组件属性 textColor、textAlignment 和 font。
如果您想将组件样式用作默认解析器配置,强烈建议您使用这些方法。
锚支持
通过使用 <a href="..."> 标记实现锚支持。
如果 NSAttributedString 在 UITextView 中显示,您可以处理对其的用户的点击。
确保您的 UITextView 是 不可编辑的、可选择的 并设置了其 代理。
然后,在您的代理中实现
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
方法。
链接不会应用颜色样式。您必须使用 UITextView 的 linkTextAttributes 属性来设置它。
默认标签
摘要
标签 | 类 | 参数 | 效果 |
---|---|---|---|
left | GONMarkupAlignment | none | 强制文本左对齐 |
right | GONMarkupAlignment | none | 强制文本右对齐 |
center | GONMarkupAlignment | none | 强制文本居中对齐 |
justified | GONMarkupAlignment | none | 强制文本两端对齐 |
natural | GONMarkupAlignment | none | 强制文本自然对齐 |
color | GONMarkupColor | value | 设置文本颜色。有关支持的 value 语法的详细信息,请查看 NSString+Color 中的 representedColor 方法。 |
N/A | GONMarkupNamedColor | none | 设置文本颜色。如果指定的颜色为nil,则可以将其重置为解析器默认颜色。 |
font | GONMarkupFont | size,name,color | 设置文本字体、文本大小或两者。也可以用来设置文本颜色。 |
N/A | GONMarkupNamedFont | none | 设置文本字体和大小。如果指定的字体为nil,则可以将其重置为解析器默认字体。 |
br | GONMarkupLineBreak | none | 添加新行 |
ul | GONMarkupList | none | 创建无序列表 |
ol | GONMarkupList | none | 创建有序列表 |
li | GONMarkupListItem | none | 将列表项添加到当前列表 |
p | GONMarkupParagraph | none | 指定一个段落。段落将自动在其后插入一个空白行 |
inc | GONMarkupInc | value | 增加文本字体大小。如果值缺失,字体将会增加一个点 |
减 | GONMarkupDec | value | 减少文本字体大小。如果值缺失,字体将会减少一个点 |
重置 | GONMarkupReset | all | 所有括号内的文本将使用默认的解析配置 |
N/A | GONMarkupSimple | none | 应用于括号内文本的配置 |
b | GONMarkupBold | none | 将文本设置为粗体。允许用户通过提供另一个字体来定义替换块overrideBlock。例如,提供一种中等字体而不是粗体字体很有用。 |
strong | GONMarkupStrong | none | 将文本设置为粗体(粗体)。允许用户通过提供另一个字体来定义替换块overrideBlock。例如,提供一种中等字体而不是粗体字体很有用。 |
i | GONMarkupItalic | none | 将文本设置为斜体。允许用户通过提供另一个字体来定义替换块overrideBlock。例如,提供一种中等斜体字体而不是粗体斜体字体很有用。 |
sup | GONMarkupTextStyle | none | 将文本设置为上标 |
sub | GONMarkupTextStyle | none | 将文本设置为下标 |
u | GONMarkupLineStyle | words只对单词应用样式(true, false),pattern(solid,点,破折号,点破折号,点破折号点),style(single,粗体,双线)和color(检查NSString+Color representedColor方法) | 下划线文本 |
strike | GONMarkupLineStyle | words只对单词应用样式(true, false),pattern(solid,点,破折号,点破折号,点破折号点),style(single,粗体,双线)和color(检查NSString+Color representedColor方法) | 删除线文本 |
a | GONMarkupAnchor | href链接值 | 支持锚点链接。有关更多信息,请参阅锚点支持。 |
N/A | GONMarkupBlock | none | 遇到时执行关联的块 |
重置
重置是一个特殊标签,允许您保护字符串的一部分。您还可以通过设置< strong>all strong>属性强制标记忽略默认解析配置。
如何添加新的标记
您可以在应用程序中添加新的标记,以添加新样式,或仅为了给文本添加语义,允许您在不更改输入字符串的情况下更新渲染。
共有3种方法可以实现。
添加新的简单标记
在应用程序中添加新的标记的最简单方法之一是使用以下3个类之一
- GONMarkupNamedColor,允许您添加能够更新文本颜色的标记
- GONMarkupNamedFont,允许您添加能够更新文本字体的标记
- GONMarkupSimple 允许您添加标记,以更新所有文本属性。字典旨在与您可能传给使用 -setAttributes:range: 方法配置 NSMutableAttributedString 的字典相同。
示例
// Retrieve shared parser
GONMarkupParser *parser = [GONMarkupParserManager sharedParser];
// Add a named color markup
[parser addMarkup:[GONMarkupNamedColor namedColorMarkup:[UIColor redColor]
forTag:@"red"]];
// Add a named font markup
[parser addMarkup:[GONMarkupNamedFont namedFontMarkup:[UIFont systemFontOfSize:12.0]
forTag:@"small"]];
// Add a custom markup, that will center text when used, and display it in pink.
NSMutableParagraphStyle *defaultParagraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
defaultParagraphStyle.alignment = NSTextAlignmentCenter;
[parser addMarkup:[GONMarkupSimple simpleMarkup:@"pwet"
style:@{
NSParagraphStyleAttributeName : defaultParagraphStyle,
NSForegroundColorAttributeName : [@"pink" representedColor] // NSString+Color
}
mergingStrategy:GONMarkupSimpleMergingStrategyMergeAll]];
添加基于块的新的标记
对于更复杂的标记,您可以添加 GONMarkupBlock 实例。
它有5个参数
- openingMarkupBlock,在找到标记打开时调用。用于将自定义配置推入堆栈
- closingMarkupBlock,标记关闭后调用一次。
- updatedContentStringBlock,在 closingMarkupBlock 之后立即调用,允许您覆盖返回的字符串
- prefixStringForContextBlock,在 openingMarkupBlock 之后立即调用,允许您返回前缀
- suffixStringForContextBlock,在 openingMarkupBlock 之后立即调用,允许您返回后缀
示例
// Retrieve shared parser
GONMarkupParser *parser = [GONMarkupParserManager sharedParser];
// Custom markup, based on block
GONMarkupBlock *markupBlock = [GONMarkupBlock blockMarkup:@"custom"];
markupBlock.openingMarkupBlock = ^(NSMutableDictionary *configurationDictionary, NSString *tag, NSMutableDictionary *context, NSDictionary *attributes) {
// Update font size
[configurationDictionary setObject:[UIFont boldSystemFontOfSize:69.0]
forKey:NSFontAttributeName];
// Update text color
[configurationDictionary setObject:[@"brown" representedColor]
forKey:NSForegroundColorAttributeName];
};
[parser addMarkup:markupBlock];
创建一个新的 GONMarkup 子类
您可以通过继承 GONMarkup 类添加自定义标记。
通过继承添加新标记对于您想要在多个项目中重用标记或实现更复杂的行为非常有用。在进行继承时,您可以访问共享对象,允许您保留数据并在各个标记处理程序之间共享数据。
例如,查看当前定义的标记。 ;). 请参见 GONMarkupList 和 GONMarkupListItem,它们使用共享上下文进行实现。
故障排除
某些文本丢失
检查您的标记是否正确注册,您的标签是否正确匹配。
在使用 < / > 时,某些文本丢失
在文本中使用 < 和 >。
我的标签关闭后文本颜色仍然生效。
这是由 NSAttributedString 的内部行为引起的。一旦设置了颜色,它就会应用,直到设置新的颜色。
为了避免这个问题,请确保在您的解析器中设置了默认文本颜色(defaultConfiguration / NSForegroundColorAttributeName 键)。您可以在 UILabel / UITextField 上使用 setMarkedUpText: 来使用默认组件配置。
文本样式未应用于我的链接
有关更多信息,请参阅 锚点支持。
当使用自定义字体时,遇到一些崩溃
请确保使用正确的字体名称,或者您正在使用的字体代码已正确注册到您的解析器。
想倾出您的设备上所有可用的字体并检查它们的真实名称吗?
请看这里的 DUMP_FONT_LIST()
使用 <br> 不会插入新行
<br> 单独在 GONMarkupParser 中是无效的。请确保使用 <br/>。
颜色未应用
检查您颜色的语法是否正确。
有关支持的语法,请参阅 NSString+UIColor 的更多信息,这用于从您的字符串值计算颜色。
金·卡戴珊打破互联网了吗?
没有,绝对没有。我昨天还能推送到GitHub。
演变
- 允许自定义列表的缩进前缀。
- 在解析器和标记器中实现 NSCoder。
- 允许在解析器/标记器上使用 copy。
- 改进关闭标签。
贡献者
请参阅 GitHub 上的 贡献者页面。
变更日志
更改日志可以在这里找到