Uncodin / bypass

Skip the HTML, Bypass takes markdown and renders it directly on Android and iOS.
http://uncodin.github.com/bypass/
Apache License 2.0
1.51k stars 193 forks source link

Impossible to Find Accurate Range of Link in BPElement #193

Open insanj opened 9 years ago

insanj commented 9 years ago

Currently there is no way to get the range of a link (in the parsed string) from a BPElement.

Using a non-BPMarkdownView view to present Bypass-parsed stuff (such as a UILabel) prevents links from being interactable. So, I traverse the BPDocument's elements and childElements to find all the links (elements.elementType == BPLink && element.attributes[@"link"]) and then addAttributes with NSLinkAttributeName to the parsed attributed string. (Note: I'm not using a BPMarkdownView because it doesn't automatically detect links like a UILabel, but perhaps using a regex to match links and adding them manually to the BPMarkdownView would be more sane than what follows...)

Unfortunately, if there is more than one string match for the link element text (such as the text "link" appearing more than once, each a separate hyperlink), then there is no way to discern which should be matched with which address.

Because there is no way to find the exact range of the link within the parsed string, if the hyperlinked text is found more than once, there is no way to accurately link the correct text. To make sure at least the links are duplicated, rather than making all matches overwrite each other (i.e. the first match for the string "link" gets hyperlinked over and over with every link address attribute because there is no way to find the specific range of the hyperlink, so rangeOfString just throws out the first find), I have kept all matches in a dictionary, mapped to the range of where it was found. Then the next time the same string has a hyperlink, I start the rangeOfString with the location in the dictionary. But, if there are matches in the original string before or between the matches, then they will be incorrectly hyperlinked. I've considered analyzing the individual childElements and substituting the dictionary for the index of the current element step in the parsed string, but that seems like overkill -- in a way just writing a stepping algorithm for the stepping algorithm.

Is there any better way to achieve what I'm looking for? I'm just trying to add tappable links to a UILabel using Bypass, and it's turning into a nightmare! If I could add rules to the Bypass infrastructure, like adding attributes to certain kinds of matches or symbols (which could also allow me to add support for other markdown matches like ^[]), or if there was a simple workaround / modification for this, that would be a welcome improvement.

myell0w commented 9 years ago

hi insanj,

I'm not fully sure but if I remember correctly from twitter you're working on a reddit client. in this case (or if not and you're just interested in fast markdown parsing including links) you might wanna take a look at my branch:

https://github.com/myell0w/bypass-core/tree/reddit-extensions?files=1

insanj commented 9 years ago

@myell0w Thanks for the suggestion! Is there any documentation available for this branch? Should I just substitute the files from the existing bypass-core src with yours? What do you mean by "fast markdown parsing including links" -- is this built-in?

myell0w commented 9 years ago

there's sadly no documentation as I just built this for my own use, I think the best would be if you check out the commits that I made. you can hit me up on Twitter and I'll try to help you, if you have any specific questions.

as for the integration, bypass was splitted up into bypass-core and bypass-iOS at the time I used it, not sure how it progressed afterwards. so I also have a fork of bypass-iOS that integrates with my fork of bypass-core.

and last but not least, yes - link parsing (of non-markdown-annotated links) is built in, so there's no need for another pass to parse them, they get parsed with the markdown (as I modified the C parser to trigger on 'h')