homebrewery icon indicating copy to clipboard operation
homebrewery copied to clipboard

Rich Indexing

Open dbolack-ab opened this issue 1 year ago • 13 comments

Semi-Dynamic Index building for Markdown+

Build simple, rich, or hybrid indexes with internal links.

Usage

Both usage cases center around the use of the index marked extension.

#IndexName:Topic/Subtopic

Multiple Indices

This system is capable of tracking multiple indices. Entries without a declared index in their formatting will be placed in the default index Index. An index marker is a block-level marker.

Simple Index

Anywhere in the document add an index marker with no label and a list of terms to be indexed. Terms will be searched for in a case and whitespace insensitive manner.

#Topic

Complex Index Entry

There are a number of variations that can be employed here. The only requirement is the line starts with a #, has no space, and contains a Topic - and Index and a Subtopic are optional.

This generates an entry for Fireball under the topic of Elemental Spells in the Appendix: Magic index.

#Appendix\: Magic:Elemental Spells|Fireball

This generates the topic of Elemental Spells in the Appendix: Magic index.

#Appendix\: Magic:Elemental Spells

This generates the topic of Elemental Spells in the default index.

#Elemental Spells

This generates an entry for Fireball under the topic of Elemental Spells in the default index.

#Elemental Spells|Fireball

This generates an entry for Fireball under the topic of Elemental Spells in the default index.

#Elemental Spells|Fireball

Crossreferences

This system supports crossreferencing index entries. Crossreference hyperlinks link to the crossreference target rather than a page number. Crossreference targets do not need to exist in the brew prior to being referenced; missing targets will result in the references being silently dropped on index generation.

Crossreferences are implemented by appending | followed by an optional key and then the index entry to reference.

Examples:

#Cross Index Name:CrossReference Topic/CrossReference Subtopic 1|Index Name:Topic 

#Cross Index Name:CrossReference Topic/CrossReference Subtopic 2|+Index Name:Topic 1/SubTopic 1

#Cross Index Name:CrossReference Topic 2|Index Name:Topic 2

#Cross Index Name:CrossReference Topic 2/CrossReference SubTopic 3||Index Name:Topic 2

#Cross Index Name:CrossReference Topic 2/CrossReference SubTopic 4||+Index Name:Topic 2/SubTopic 2

The optional keys are:

Key Reference Type
None See
+ See Under
| See Also
|+ See Also Under

The reference type is prepended to the target. The code does not enforce any particular style guide.

The above example would generate:

{{index,wide
##### Cross Index Name

- CrossReference Topic
  - CrossReference Subtopic 2
    see under [Topic 1: SubTopic 1](#idx_indexname_topic1_subtopic1)
- CrossReference Topic 2
    see [Topic 2](#idx_indexname_topic2)
  - CrossReference SubTopic 3
    see also [Topic 2](#idx_indexname_topic2)
  - CrossReference SubTopic 4
    see also under [Topic 2: SubTopic 2](#idx_indexname_topic2_subtopic2)

}}

Generating the Index

The rich index snippet, when executed, combines the simple and rich index entries into a single, alphabetized index.

If you have simple and rich entries, rich entries will be folded under the simple entries as follows:

  1. Simple entries are created as top-level, un-indented entries.
  2. Child entries are indented under their top-level parent.
  3. If a Rich entry has no parent, it will be inserted as a top-level entry.
  4. If a Rich entry has a parent and that parent does not exist in the top-level entries, the parent will be added as a new top-level entry and the Rich entry will be added as a child of that top-level entry.
  5. If a Rich entry has a parent and the parent exists in the top-level entries, and the Rich entry is not listed as a child of the parent, it will be added as a new child.
  6. If a Rich entry has a parent and the parent exists in the top-level entries, and the Rich entry exists, the child will be updated with an additional page reference to the new Rich entry.
  7. Results are poured into the brew inside a {{index,wide }} container. If muliple indices exist, they will appear in alphabetical order separated by a \page.

Known issues.

  • The snippet is not smart enough to know that it is scanning markup when looking for terms. This could create bad entries.
  • The Styling is meh. I mostly emulated the existing Index snippet. We could do some dot padding, etc.

Other notes

I'm not the most efficient JS coder. I'd be very unsurprised if some of this could be condensed.

Test Brew ShareID: https://homebrewery-pr-3113.herokuapp.com/share/vtI5G0Zl_fan

dbolack-ab avatar Oct 27 '23 04:10 dbolack-ab

The simple index lookup assumes page-level anchor links in the format #page## ( e.g. #page1 ) that do not currently exist

Homebrewery does have page-level anchor's on the <div class="page"> elements, in the form of id="p1". These get used by the TOC snippet.

image

ericscheid avatar Oct 27 '23 05:10 ericscheid

The simple index lookup assumes page-level anchor links in the format #page## ( e.g. #page1 ) that do not currently exist

Homebrewery does have page-level anchor's on the <div class="page"> elements, in the form of id="p1". These get used by the TOC snippet.

Oh. Wow. I just learned a new thing. I had no idea that the anchor behavior also applied to any ID'd tag. That's got to have been there for years?!

:exploding_head:

dbolack-ab avatar Oct 27 '23 13:10 dbolack-ab

Yes, but due to how rendering works this is funky, Id for headers are not unique between pages, and Partial Page Rendering(PPR, which applies to 50+ pages brews) blocks them altogether. We are working on some fixes for that.

5e-Cleric avatar Oct 27 '23 17:10 5e-Cleric

Yes, but due to how rendering works this is funky, Id for headers are not unique between pages, and Partial Page Rendering(PPR, which applies to 50+ pages brews) blocks them altogether. We are working on some fixes for that.

Fair, but as long as the ones for the pages are, it works for this purpose so long as someone doesn't manage to construct a collision between tags.

I considered concatenating the page number with the munged label ( i.e. p1-thisismylabel ) but I didn't see an elegant way to grab that...

dbolack-ab avatar Oct 28 '23 01:10 dbolack-ab

If/when #3089 goes live, each Markdown token will be contained inside pageBlock tokens, which will have a pageNumber property, so it will all be accessible from the Markdown Lexer output.

G-Ambatte avatar Oct 28 '23 02:10 G-Ambatte

I am unsure what is going wrong with this conflict

dbolack-ab avatar Dec 14 '23 20:12 dbolack-ab

As pageblock tokens do not seem to be a thing any longer, I have added the Brew document variables object to be passed for Render. Ideally, all Brew meta data that is MAYBE vaguely usable for the document as a "Constant" should be added to this object. I limited it to the pageNumber for now.

dbolack-ab avatar Jan 16 '24 08:01 dbolack-ab

There is currently an active conflict between the Variable code and this PR. The variables code is processing the parentheticals if the parenthetical has spaces. I have not been able to determine why - my regex is too weak to understand the version of variables that was implemented.

dbolack-ab avatar Mar 11 '24 01:03 dbolack-ab

Test document:

https://homebrewery-pr-3113.herokuapp.com/share/T9i5qU8UxHcK

dbolack-ab avatar Apr 21 '24 01:04 dbolack-ab