{"id":17043431,"url":"https://github.com/leavez/neat","last_synced_at":"2025-06-27T15:07:47.156Z","repository":{"id":62448947,"uuid":"86771042","full_name":"leavez/Neat","owner":"leavez","description":"Fix the line height problems of TextKit","archived":false,"fork":false,"pushed_at":"2019-11-06T09:22:09.000Z","size":682,"stargazers_count":106,"open_issues_count":4,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-21T04:21:47.425Z","etag":null,"topics":["ios","lineheight","textkit"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leavez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-31T02:49:03.000Z","updated_at":"2025-04-30T02:57:23.000Z","dependencies_parsed_at":"2022-11-02T01:01:24.590Z","dependency_job_id":null,"html_url":"https://github.com/leavez/Neat","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/leavez/Neat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leavez%2FNeat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leavez%2FNeat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leavez%2FNeat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leavez%2FNeat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leavez","download_url":"https://codeload.github.com/leavez/Neat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leavez%2FNeat/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260545846,"owners_count":23025815,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","lineheight","textkit"],"created_at":"2024-10-14T09:29:31.764Z","updated_at":"2025-06-18T11:36:56.513Z","avatar_url":"https://github.com/leavez.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Neat\n\n[![Version](https://img.shields.io/cocoapods/v/Neat.svg?style=flat)](http://cocoapods.org/pods/Neat)\n[![License](https://img.shields.io/cocoapods/l/Neat.svg?style=flat)](http://cocoapods.org/pods/Neat)\n[![Platform](https://img.shields.io/cocoapods/p/Neat.svg?style=flat)](http://cocoapods.org/pods/Neat)\n\nNeat is a tool solve the line height problems when using TextKit on iOS. \n\nLine heights (or the visual line sapcings) displayed by TextKit vary on different lines when mixing different languages in one text. It looks very ungraceful and breaks the beauty of text layout. A common example is Chinese-English mixed layout, and even English-emoji mix cannot escape!! `UILabel` and `UITextView` handle this very well. Neat make TextKit views look exactly the same to `UILabel`.\n\n![](./Example/problems.png)\n\nNeat also remove the extra line spacing of last line when text is truncated to the maxNumberOfLines. It may, but not always, happen when `lineSpacing` is greater than zero. This function makes it very convenient to constrain the spaces between textView and other views.\n\n[ComponentKit](https://github.com/facebook/componentkit) could be fixed with Neat.\n\n## Install\n\nInstall via CocoaPods:\n\n```ruby\npod \"Neat\"\n```\n\n## Usage\n\n### Basic Usages:\n\n1. Import Neat and call `[UIFont patchMetrics];` once before textView layout. Recommend in `didFinishLaunchingWithOption:` or class load method.\n2. set the delegate of textView's layouManager to `[NELineHeightFixer sharedInstance]`. If the delegate is occupied, wraps it with `NSLayoutManagerDelegateFixerWrapper`.\n\n### Advanced:\n\nPlease read \"How it works\" first.\n\nNeat contains 2 parts:\n\n- a patch for UIFont.  `UIFont+Patch`\n  - It alone solve the line spacing problems.\n- a implementation of NSLayoutManagerDelegate.  `NELineHeightFixer` and `NSLayoutManagerDelegateFixerWrapper`\n  - It alone solve the problem extra line spacing below last line.\n  - it alone solve the line spacing problems with an small exception.\n\nThese 2 parts work together solve the problems above perfectly.\n\n**NOTE**: The patch for UIFont effects globally since it swizzles the methods of UIFont. This may have potential conflict on other parts. Walk around: use second part alone. To solve the small expection, you could set the maximumLineHeight of attribtuedString to `fixedLineHeightForFontSize:paragraphStyle:` of NELineHeightFixer.\n\n## How it works\n\nThe nature of diffent line heights when mixing different languages is the different metrics of different fonts. When you use system default font, you get `SFUIText`. SF only have glyphs for English text. When encountered emoji, it fall down to `AppleColorEmojiUI`. SF and AppleColorEmojiUI have different metrics, i.e. `lineHeight`, `descender` and etc. The later have larger lineHeight. When a line contain an emoji character, layoutManger gives a larger rect to display this line, which led to a larger visual line spacing.\n\n( This is same to English-Chinese mix. `PingFang`  have small lineHeight, so pure Chinese lines have small line spacings. PingFang also have different descender, which effects baseLineOffset, making it more wired in a English-Chinese mixed line. )\n\nTwo ways to solve the problem:\n\n- make all fonts' metrics the same\n  -  by swizzling the method of UIFont and return `SFUIText`'s value\n- manully set the line rects \n  - by implementing method of NSLayoutManagerDelegate:  `layoutManager:shouldSetLineFragmentRect:lineFragmentUsedRect:baselineOffset:inTextContainer:forGlyphRange:` and modify the rects and baseLineOffset.\n\nNeat implements both ways, beacuse neither of these methods alone can solve it well. The first can't handle the extra line spacing below last line. The second alone could solve all two problems, with a exception that having a small additional space below last line when last line or the truncated part contains emoji.\n\n## License\n\nNeat is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleavez%2Fneat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleavez%2Fneat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleavez%2Fneat/lists"}