[Feature request] Support <details> tag
See original GitHub issueReddit, GitHub and GitLab all support <details>
tag which looks like spoiler tag:
Click me!
That's how spoiler tag works, but the little surprise is that
It can actually be nested
Would be very helpful if we could implement this as well. I tried doing that using custom HTML plugin as described in the doc, but the problem is it doesn’t support proper nesting, you lose start and end positions of the tag as you go from child details to parent ones as this is actually text-changing span.
Implementing the actual span in TextView is as simple as:
val innerText = spanned.subSequence(innerRange.first, innerRange.first + innerText.length) // contains all spans there
spanned.replace(outerRange.first, outerRange.last + 1, summaryText) // replace it just with spoiler text
// replace inner text with clickable span
val wrapper = object : ClickableSpan() {
override fun onClick(widget: View) {
// replace wrappers with real previous spans
val start = spanned.getSpanStart(this)
val end = spanned.getSpanEnd(this)
spanned.removeSpan(this)
spanned.replace(start, end, innerText)
view.text = spanned
AsyncDrawableScheduler.schedule(view)
}
}
spanned.setSpan(wrapper, outerRange.first, outerRange.first + summaryText.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
support MD equivalent of <details> tag · Issue #445 ... - GitHub
The easiest way to have a lot of those on one page is to use the details tag, which allows for automatic hide/show...
Read more >How To Manage Feature Requests [Template included]
This guide will teach you everything about feature requests – how to process them, manage them, respond to them, prioritize them – so...
Read more >The Details disclosure element - HTML - MDN Web Docs
The HTML element creates a disclosure widget in which information is visible only when the widget is toggled into an "open" state.
Read more >Intercom Tags vs. Savio for Tracking Feature Requests
Can I just track feature requests using Intercom conversation tags?” Yes, but it's not ideal. Here's how to do it, together with a...
Read more >Support for Content Tagging | Feature requests - GatherContent
Currently I create a tab on EVERY content template that has a list of our tags and categories. Keeping this updated is a...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@wax911 @noties
Here it is. It’s heavily modified version of the previous one. It also puts hidden text inside the blockquote to separate it from other content.
Tag parser
Post-processor
Hello @Adonai !
This is an extremely hard feature to add seamlessly on the library level. And the reason is why, is exactly as you said it, during rendering a visitor cannot modify content, otherwise all subsequent spans will lose positions. So, we have 2 options:
there is always another option...
3. some regex solution😄So —
#1
although logically would be the perfect place to implement won’t help us. Because commonmark specification is created with interoperability with HTML in mind, so any valid HTML is also valid commonmark/markdown. This comes with HTML being treated as first-class citizen and placed in parsed markdown according to the commonmark parsing strategy and not actual HTML content (there is no entry<details>
anywhere in parsed markdown document). This complicates things for us as we do not have a browser engine at our disposal. So, we will have to rule out the parsing stage for now and try to do something with rendered result instead.BTW, why would having a
<details>
node in parsed markdown would be a good thing? Because it would allow us seamlessly display that node in a differentTextView
widget (or any other actually). So, we could split parsed markdown and display some nodes in different widgets which could give us flexibility. For example, this approach is used inmarkwon-recycler-table
module to display markdown tables inTableLayout
instead of aTextView
. But in the end we don’t have to useRecyclerView
and can inflate our layout programmatically which can be OK for relatively small content.I’m mentioning different widget because it seems that in order to implement a proper
<details>
tag handler we must use a different from other content widget. As we cannot freely append/remove text without messing with other spans.At first I considered using a
ReplacementSpan
which theoretically could help us out - simply trackexpanded
state and draw a summary or (summary + content) based on it. But it implies that all the text must be drawn directly on a Canvas. Markdown tables, for example, that are displayed in aTextView
are actually doing it this way and have some limitations - they cannot display images and cannot be acted upon. So, in case of an image or a nested<details>
this way we won’t be able to achieve anything.So, what are other options? We could still proceed as usual:
<details>
tag handler which sets someDetailsHtmlSpan
markwon.toMarkdown(String)
DetailsHtmlSpan
There is new sample screen with solution I’ve hacked through. It’s not perfect, but I hope it does show a possible way of action - sample
So, after we have found
DetailsHtmlSpan
we split our rendered markdown by biggestDetailsHtmlSpan
and additionally look for nested<details>
tags. So our rendered markdown in a form similar to:Based on that structure we will create 3 TextViews - 1 for each root element. A
<details>
will have a dedicated TextView for itself and all its children (bothSpanned
and nested<details>
). It will also have additional spans to handle clicks and draw an expand/collapse indicator.Please note that this is just a proof-of-concept and I do not consider it to be production ready. Still it is a valuable point of reference as it will cover if this feature worth the cost of its implementation. From my point of view this feature is an overkill to be added to the project, but if someone want to tinker with it, polish or improve that someone is really welcome 🙌