Skip to content

Commit

Permalink
🧭 Order abbreviations by length (#830)
Browse files Browse the repository at this point in the history
  • Loading branch information
agoose77 authored Jan 10, 2024
1 parent 70ee1ea commit d2e6e78
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/thin-houses-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'myst-transforms': minor
---

Sort (frontmatter) abbreviations definitions by length
2 changes: 1 addition & 1 deletion docs/glossaries-and-terms.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ The abbreviations are case-sensitive and will replace all instances[^1] in your
:::{tip} Order of Abbreviations
:class: dropdown
The order of abbreviations in your frontmatter should specify the longer abbreviations first (e.g. `RHR`) and then the shorter abbreviations (e.g. `HR`). If you do this in the opposite order, you will have an abbreviation for R`HR`.
Abbreviations defined in your frontmatter are applied in longest-sorted order. If you have two abbreviations with the same suffix (e.g. `RHR` and `HR`), the longer abbreviation will always take precedence.
:::
6 changes: 6 additions & 0 deletions packages/myst-transforms/src/abbreviations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function replaceText(mdast: GenericParent, opts: Options) {
const replacements: FindAndReplaceSchema = Object.fromEntries(
Object.entries(opts.abbreviations)
.filter(([abbr]) => abbr.length > 1) // We can't match on single characters!
.sort((a, b) => b[0].length - a[0].length || a[0].localeCompare(b[0])) // Sort by length (longest-first) then locale-ordering
.map(([abbr, title]) => [
abbr,
(value: any, { stack }: RegExpMatchObject) => {
Expand All @@ -41,13 +42,18 @@ function replaceText(mdast: GenericParent, opts: Options) {

export function abbreviationTransform(mdast: GenericParent, opts?: Options) {
if (!opts?.abbreviations || Object.keys(opts.abbreviations).length === 0) return;

// Inline abbreviations have lower priority to passed-in abbreviations
// So, we replace conflicting titles with those that have been passed-in
const abbreviations = selectAll('abbreviation', mdast) as Abbreviation[];
abbreviations.forEach((node) => {
if (node.title) return;
const abbr = toText(node);
const title = opts.abbreviations?.[abbr];
if (title) node.title = title;
});

// Replace instances of abbreviated constructs with their titles
replaceText(mdast, opts);

if (opts.firstTimeLong) {
Expand Down

0 comments on commit d2e6e78

Please sign in to comment.