retypeapp / retype

Retype is an ✨ ultra-high-performance✨ static site generator that builds a website based on simple text files.
https://retype.com
Other
1.01k stars 201 forks source link

feature: Build a Glossary feature from within Retype #645

Open gdcrocx opened 8 months ago

gdcrocx commented 8 months ago

Hello @geoffreymcgill,

Love Retype! Love how fun and simple it is to build documentation sites with Retype.

I am in need of a feature to build a Glossary for a documentation site and would love to see if this is a feature that the community would be interested in as well (vote with a ❤️ on this issue).

I was thinking of the following as it's syntax. This could be within a file called glossary.md.

 [!term AWS abbrev=Amazon Web Services desc=A popular Cloud service provider]

Then, wherever we refer the term within the documentation site, we use the syntax, something like {{ !term AWS.abbrev }} instead of plain-text and the UI renders a neat tooltip with the value/meaning/description , in this case, the abbreviation of the word from the Glossary.

As a side feature, we could auto-generate a Glossary page with the available term definitions.

gdcrocx commented 8 months ago

Thank you for your time over chat to discuss some possible solutions, like the glossary-like feature available on Markdown.

To make use of this Markdown feature, one has to create a folder named _includes at the root of the site input directory and then a file called bottom.md within the _includes folder.

The file bottom.md would then contain

*[AWS]: Amazon Web Services
*[HTML]: Hyper Text Markup Language
*[CSS]: Cascading Style Sheet

Now everytime, the term AWS, HTML, CSS appears on the site, Markdown renders a rudimentary tooltip with the value.

fredahrens commented 8 months ago

Hi @gdcrocx, this is a very nice solution and works almost quite well.

There still is one problem: If the term is enclosed in brackets or prefixed by bracket due to having the term in a list of other terms, the term isn't detected and the tooltip isn't shown.

Example:

having the following included in _bottom.md:

*[PO]: Purchase Order

this functions very well with normal markdown like

Use `Approve` for approving the PO.

It doesn't work with markdown like

This works with any document (PO, RfQ, RQ).

If a definition exists, all other items in the list are properly detected. Putting ´PO´ at the end of the list, before the closing bracket, still detects the term.

My temporary workaround is to add the term in `_bottom.md' with the starting bracket, like

*[PO]: Purchase Order  
*[(PO]: Purchase Order 

(tested with Retype 3.5.0)

gdcrocx commented 8 months ago

@fredahrens All credit goes to @geoffreymcgill who suggested the rudimentary markdown feature to me.

I am trying to build a workaround using Scriban or Liquid templating to build the values inside bottom.md from the data section of the retype.yml and a glossary.html page but have no luck.

I would love to see if someone can help me with running this templating script successfully while Retype can work on Glossary being a feature.

Sample retype.yml

...
data:
  term:
    AWS: Amazon Web Services
    HTML: Hyper Text Markup Language
    CSS: Cascading Style Sheet

or

...
data:
  termAWS: Amazon Web Services
  termHTML: Hyper Text Markup Language
  termCSS: Cascading Style Sheet

bottom.md

...
{% for key, value in data %}
    {# Check if the data key starts with the word "term" as a workaround for being unable to store an object under data #}
    {% if key contains "term" and key[0..3] == "term" %}
        *[{{- key -}}]: {{- value -}}
    {% endif %}
{% endfor %}

Also, generate a glossary.md file for a Glossary section in the documentation site.

glossary.md

---
label: Glossary
order: 200
expanded: false
visibility: public
---

Term   | Abbreviation 
---    | --- 
{% for key, value in data %}
   {# Create the term with the key as `a href` anchor so the term can be referred to across the documentation site for later. #}
   [ {{- key -}} ](){ # {{- key -}} | {{- value -}} 
{% endfor %}

The above templating script would generate a HTML page with a table of terms and their abbreviations.

glossary.html

Glossary

Term Abbreviation
[CSP]() Cloud Service Provider
geoffreymcgill commented 8 months ago

but have no luck

I seem to have this working decently well using the following settings and files:

Table layout

retype.yml

data:
  term:
    AWS: Amazon Web Services
    CSS: Cascading Style Sheet
    HTML: Hyper Text Markup Language

In my retype.yml, I am using the default templating language, Scriban (not Liquid). There is project level setting to enable Liquid style syntax for the templating language, but I do not have that enabled.

_includes/bottom.md

{{~ for item in term ~}}
*[{{ item.key }}]: {{ item.value }}
{{~ end ~}}

glossary.md

# Glossary

Term   | Abbreviation
---    | ---
{{~ for item in term ~}}
    {{- item.key }} | {{ item.value }}
{{~ end ~}}

The above creates the following Glossary page in HTML:

Screen Shot 2023-10-20 at 11 18 23 AM

Table with Anchors

Adding an anchor to the table in glossary.md using the following syntax:

Term   | Abbreviation
---    | ---
{{~ for item in term ~}}
[](#{{ item.key }}){ #{{ item.key }} } {{ item.key }} | {{ item.value }}
{{~ end ~}}

Heading layout

The following is a variation on glossary.md where the terms are rendered as Headings, then Retype will automatically add the Heading anchors and build the Table of Contents in the right side-bar.

# Glossary

## Terms

{{ for item in term }}
### {{ item.key }}

{{ item.value }}
{{ end }}

The above renders as:

Screen Shot 2023-10-20 at 11 25 11 AM

Hope this helps.

geoffreymcgill commented 8 months ago

I updated the retype.com website to use the techniques above to dynamically build the list of project-wide abbreviations.

Check out the commit with the changes.

Here is the new data section added to the project retype.yml file:

data:
  abbreviations:
    HTML: Hyper Text Markup Language
    CSS: Cascading Style Sheet

New _includes/bottom.md file:

<!-- Add content to _includes/bottom.md to include here -->

<!-- Project wide abbreviations, _includes/bottom.md -->
{{~ for item in abbreviations ~}}
*[{{ item.key }}]: {{ item.value }}
{{~ end ~}}

Hope this helps.

fredahrens commented 8 months ago

This seems to be a better approach for managing the list of abbreviations. And I really like the idea of rendering a glossary page from the data in the project file.

I have the following list in retype.yml:

data:
  abbreviations:
    PO: Purchase Order  
    RQ: Requisition  
    RfQ: Request for Quotation  

The definition for PO is available only in normal text. Having it in a list enclosed in brackets as the first item, it's not detected.

image

The 2. problem: Currently it works only for abbreviations with all uppercase characters. Abbreviations containing lowercase characters are not processed.

geoffreymcgill commented 8 months ago

The 2. problem: Currently it works only for abbreviations with all uppercase characters. Abbreviations containing lowercase characters are not processed.

For me, the RfQ abbreviation appears to work correctly when used in plain paragraph text.

Screenshot 2023-10-20 at 9 39 50 PM

All caps is not required either. For example, using the following abbreviations sample converts all instances of the string Retype:

<!-- Project wide abbreviations, _includes/bottom.md -->
*[HTML]: Hyper Text Markup Language
*[CSS]: Cascading Style Sheet
*[Retype]: Retype is sooo cool!
Screenshot 2023-10-20 at 9 44 14 PM

The parsing problem with the (PO, RQ, RfQ) sample is strange one and there must be an issue with our underlying Markdown parser library. I'm going to poke around and see if I can figure out what is going wrong.

gdcrocx commented 8 months ago

This is so cool! Thanks @fredahrens @geoffreymcgill

I am working on expanding the glossary.md file to generate HTML in a way where when abbreviations are used in other places within the page, they link with the in-page anchor links we just generated.

This is where I am stuck (I am new to Scriban and would love some help here).

Here I am working with abbreviations as though it can be mutated but I realized much later that anything within data is loaded as constants. I tried using with <variable> ... end to store mutated values of abbreviations into a new variable. Then later, iterate through the new variable so I can generate some cool HTML but no luck.

<!-- Sample code. abbreviations as-is is immutable. -->
{{ for item in abbreviations }} 
    {{ itemValue = item.value }}
    {{~ for key in ( object.keys abbreviations ) ~}}
        {{~ if string.contains itemValue key ~}}
            {{ itemValue = ( itemValue | string.replace key ("<a href='#" ~ key ~ "'>" ~ key ~ "</a>") ) }}
            {{ abbreviations[key] = itemValue }}
        {{ else }}
            {{ abbreviations[key] = item.value }}
        {{ end }}
    {{ end }}
{{ end }}

<!-- Iterate through the new mutated abbreviations variable, now with the glossary terms in the abbreviation replaced with anchor links to its terms and abbreviations within the same glossary page -->
{{~ for item in abbreviations ~}}
    [{{ item.key }}](){ #{{ item.key }} } | {{ item.value }}
{{~ end ~}}

Imagine you had a data like this, where the abbreviation of CSS contains the term HTML which is an anchor link to the term HTML and its abbreviation.

data:
  abbreviations:
    HTML: Hyper Text Markup Language.
    CSS: Cascading Style Sheet. Works with HTML.

As for what I have in my vanilla glossary.md before building the above snippet in Scriban -

Term   | Abbreviation
---    | ---
{{~ for item in abbreviations ~}}
[{{ item.key }}](){ #{{ item.key }} } | {{ item.value }}
{{~ end ~}}

which renders a page like this one below, with in-page anchor links for each term so it can be referred elsewhere within the page.

Screenshot 2023-10-20 at 11 56 42 PM

geoffreymcgill commented 8 months ago

You kinda lost me. Should the sample with the <!-- Sample code. abbreviations as-is is immutable. --> be added to the gloassary.md page? Can you provide some more explanation or a before-and-after sample of the data that mocks up your requirement.