Est.
Automated Glossary
Most jottings have a high density of abbreviations and technical terms. Some of those are very familiar, others are more exotic. I wanted to typeset them so that they would stand out from the normal words, but I didn't want to have to markdown each occurrence.
Requirement
For abbreviations there are special plugins, notably markdown-it-abbr
, which can mark up all words as <abbr>
if there is a definition of that term. The <abbr>
tag might be styled as needed. When you hover the mouse cursor over the word, a tooltip displays the long version of the abbreviation.
I like the basic idea of automatic styling, but instead of a tooltip I would prefer to have to link to a dedicated glossary page for each term. The glossary page should contain some short definitions and further helpful links to other pages of the website.
Automatic Link Insertion
No sooner said than done: Words with all capital letters and a length of at least 3 characters are recognized as glossary items. A word like HTTPS
is replaced with a (markup) link to a glossary page with the same name, in this case /glossary/HTTPS
. If the corresponding markdown page does not exist yet, it will be created automatically (docs/glossary/HTTPS.md
).
If a markdown file named Xyz.md
exits in the glossary directory, it will also trigger the replacement action: All occurrences of the term Xyz
in one of the markdown pages are automatically linked to the Xyz glossary page. This works even for words where not all letters are capitalized. And it works consistently for all pages.
The Curse of Automatic Link Insertion
Occasionally, words should not be typeset as links to the glossary. A typical example is a sentence with uppercase words that you do not want in the glossary, e.g. 55 USD = 7392.83 JPY
.
Other situations where automatic insertion of links is undesirable are fenced code and links.
clonsle.log("HTTPS")
clonsle.log("HTTPS")
would come out as
clonsle.log("[HTTPS](/glossary/HTTPS)")
clonsle.log("[HTTPS](/glossary/HTTPS)")
Links would be completely broken. The inserted text looks like one would write a link in markdown. But because it is fenced code, it would not be translated into a real link.
Automatic Link Prevention
For this reason, automatic link insertion is disabled for fenced code, code literals (``), and links.
For other occurrences, it is sufficient to disturb the sequence of characters in a way that prevents pattern matching, and that is not visible when the Markdown is rendered as HTML. For example, I could write C­PU
to include the term CPU in a text without automatically generating a glossary entry for it.
As a convenient mechanism, my defLinks
Vite plugin not only inserts links, but also interprets :UC()
as a command to uppercase the words in parenthesis. So I simply write
My box has 2 :UC(cpu)s and 16 GB of :UC(ram).
My box has 2 :UC(cpu)s and 16 GB of :UC(ram).
... and get My box has 2 CPUs and 16 GB of RAM.
The Glossary Page
The simplest form of a glossary page on this site looks like this:
<!--- /glossary/SomeThing.md -->
<GlossaryPage>
# SomeThing
SomeThing is some thing.
</GlossaryPage>
<!--- /glossary/SomeThing.md -->
<GlossaryPage>
# SomeThing
SomeThing is some thing.
</GlossaryPage>
<GlossaryPage>
is a Vue component that is registered globally with the VitePress app.
It does two things:
- It teleports a search result list for the glossary term into the right sidebar. This is covered in more detail on the sidebar jotting.
- It appends links to other glossary pages and to content pages that refer to the glossary term.
The template for these links looks like this:
<template>
<template v-if="glossarySections.length > 0">
<div class="see-also">
See also:
<span v-for="(section, index) in glossarySections" :key="section.url">
<a v-if="index !== 0" :href="section.url" class="font-sans"
>, {{ section.heading }}</a
>
<a v-else :href="section.url" class="font-sans">{{
section.heading
}}</a>
</span>
<hr />
</div>
</template>
<br />
<div class="topic-links">
<template v-if="nonGlossarySections.length > 0">
<h4>You also might want to read about the following topics:</h4>
<ul>
<li v-for="section in nonGlossarySections" :key="section.url">
<a :href="section.url" class="font-sans">{{ section.heading }}</a>
<br />
<div v-html="section.topic"></div>
<hr />
</li>
</ul>
</template>
</div>
</template>
<template>
<template v-if="glossarySections.length > 0">
<div class="see-also">
See also:
<span v-for="(section, index) in glossarySections" :key="section.url">
<a v-if="index !== 0" :href="section.url" class="font-sans"
>, {{ section.heading }}</a
>
<a v-else :href="section.url" class="font-sans">{{
section.heading
}}</a>
</span>
<hr />
</div>
</template>
<br />
<div class="topic-links">
<template v-if="nonGlossarySections.length > 0">
<h4>You also might want to read about the following topics:</h4>
<ul>
<li v-for="section in nonGlossarySections" :key="section.url">
<a :href="section.url" class="font-sans">{{ section.heading }}</a>
<br />
<div v-html="section.topic"></div>
<hr />
</li>
</ul>
</template>
</div>
</template>
The data model for the links is the model of the Topic Map. The links on the glossary pages are simply another view of this graph: The top part consists of See Also
links to sections on other glossary pages. The bottom part shows links to sections of main pages of the jotter. Both of these are backlinks: They point to sections that reference the actual glossary term.
The See also
links are rendered as a comma separated list of section headings. The bottom part with links to the main page section has a more fancy styling and includes not only the section heading but also the topic, just like the nodes of the Topic Map.