Skip to content

improved search #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
Binary file modified .DS_Store
Binary file not shown.
16 changes: 16 additions & 0 deletions docs/assets/abbreviations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
*[DCE]: Dynamic Contrast Enhanced
*[MR]: Magnetic Resonance
*[MRI]: Magnetic Resonance Imaging
*[RF]: Radio Frequency
*[SE]: Spin Echo
*[GE]: Gradient Echo
*[AIF]: Arterial Input Function
*[ROI]: Region Of Interest
*[EES]: Extravascular Extracellular Spaces
*[2CXM]: Two Compartment Exchange Model
*[2CU]: Two Compartment Uptake
*[SPGR]: Spoiled Gradient Echo
*[GRE]: Gradient Echo
*[BAT]: Bolus Arrival Time
*[SVD]: Singular Value Decomposition
*[DSC]: Dynamic Susceptibility Contrast
12 changes: 12 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
---
title: The OSIPI Contrast Agent Perfusion MRI Lexicon (CAPLEX)
description: Standardised definitions of quantities, models, and analysis processes for contrast-agent based perfusion MRI.
tags:
- MRI
- perfusion
- lexicon
- DCE
- DSC
---
# The OSIPI Contrast Agent Perfusion MRI Lexicon (CAPLEX)

## What is CAPLEX?
Expand All @@ -17,3 +27,5 @@ There are several ways to join the effort:
1. Become a member of the task force: email **[email protected]**. Anyone with relevant expertise can join - PhDs and postdocs working in DCE/DSC MRI field are particularly encouraged to apply.

2. To suggest edits to the lexicon, go to the CAPLEX Github page: https://github.com/OSIPI/OSIPI_CAPLEX and follow the instructions on how to contribute in the README.md. Additionally, a tutorial on how to contribute can be found [here](contributionTutorial.md).

For tips on using the search bar, see the [Search Help](search-help.md) page.
148 changes: 148 additions & 0 deletions docs/javascripts/extra.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,151 @@ buttons.forEach(button => {
//copyURLToClip(button.id)
})
})

// --- Search Enhancement: Abbreviation/Synonym Expansion & Fuzzy Suggestion ---
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.querySelector('input.md-search__input');
if (!searchInput) return;

// Create suggestion element
let suggestionDiv = document.createElement('div');
suggestionDiv.style.display = 'none';
suggestionDiv.style.position = 'absolute';
suggestionDiv.style.background = '#fffbe6';
suggestionDiv.style.border = '1px solid #ffe066';
suggestionDiv.style.padding = '4px 8px';
suggestionDiv.style.marginTop = '2px';
suggestionDiv.style.fontSize = '0.95em';
suggestionDiv.style.cursor = 'pointer';
suggestionDiv.style.zIndex = 1000;
suggestionDiv.setAttribute('id', 'search-did-you-mean');
searchInput.parentNode.style.position = 'relative';
searchInput.parentNode.appendChild(suggestionDiv);

fetch('assets/abbreviations.md')
.then(response => response.text())
.then(text => {
const abbrMap = {};
text.split('\n').forEach(line => {
const match = line.match(/^\*\[(.+?)\]:\s+(.+)/);
if (match) abbrMap[match[1].toLowerCase()] = match[2].toLowerCase();
});
function levenshtein(a, b) {
const matrix = Array.from({length: a.length+1}, () => Array(b.length+1).fill(0));
for (let i = 0; i <= a.length; i++) matrix[i][0] = i;
for (let j = 0; j <= b.length; j++) matrix[0][j] = j;
for (let i = 1; i <= a.length; i++) {
for (let j = 1; j <= b.length; j++) {
matrix[i][j] = Math.min(
matrix[i-1][j] + 1,
matrix[i][j-1] + 1,
matrix[i-1][j-1] + (a[i-1] === b[j-1] ? 0 : 1)
);
}
}
return matrix[a.length][b.length];
}
searchInput.addEventListener('input', function(e) {
const val = e.target.value.trim().toLowerCase();
suggestionDiv.style.display = 'none';
suggestionDiv.textContent = '';
if (!val) return;
if (abbrMap[val]) {
e.target.value = val + ' ' + abbrMap[val];
}
const abbrs = Object.keys(abbrMap);
let minDist = Infinity, closest = '';
abbrs.forEach(abbr => {
const dist = levenshtein(val, abbr);
if (dist < minDist && dist <= 2) { minDist = dist; closest = abbr; }
});
if (closest && closest !== val) {
suggestionDiv.textContent = `Did you mean: ${closest}?`;
suggestionDiv.style.display = 'block';
suggestionDiv.onclick = function() {
searchInput.value = closest;
suggestionDiv.style.display = 'none';
searchInput.dispatchEvent(new Event('input'));
};
}
});
// Hide suggestion on blur
searchInput.addEventListener('blur', function() {
setTimeout(() => { suggestionDiv.style.display = 'none'; }, 200);
});
});
});
// --- End Search Enhancement ---

// --- Simple Did You Mean Suggestion Above Search Bar ---
document.addEventListener('DOMContentLoaded', function() {
const searchInput = document.querySelector('input.md-search__input');
if (!searchInput) return;

// Create suggestion element above the search bar
let didYouMeanBox = document.createElement('div');
didYouMeanBox.className = 'did-you-mean-box';
didYouMeanBox.style.display = 'none';
didYouMeanBox.style.background = '#fffbe6';
didYouMeanBox.style.border = '1px solid #ffe066';
didYouMeanBox.style.padding = '6px 12px';
didYouMeanBox.style.marginBottom = '8px';
didYouMeanBox.style.fontSize = '1em';
didYouMeanBox.style.cursor = 'pointer';
didYouMeanBox.style.borderRadius = '4px';
didYouMeanBox.style.maxWidth = '400px';
didYouMeanBox.style.position = 'relative';
// Insert above the search input
searchInput.parentNode.insertBefore(didYouMeanBox, searchInput);

fetch('includes/abbreviations.md')
.then(response => response.text())
.then(text => {
const abbrMap = {};
text.split('\n').forEach(line => {
const match = line.match(/^\*\[(.+?)\]:\s+(.+)/);
if (match) abbrMap[match[1].toLowerCase()] = match[2].toLowerCase();
});
function levenshtein(a, b) {
const matrix = Array.from({length: a.length+1}, () => Array(b.length+1).fill(0));
for (let i = 0; i <= a.length; i++) matrix[i][0] = i;
for (let j = 0; j <= b.length; j++) matrix[0][j] = j;
for (let i = 1; i <= a.length; i++) {
for (let j = 1; j <= b.length; j++) {
matrix[i][j] = Math.min(
matrix[i-1][j] + 1,
matrix[i][j-1] + 1,
matrix[i-1][j-1] + (a[i-1] === b[j-1] ? 0 : 1)
);
}
}
return matrix[a.length][b.length];
}
searchInput.addEventListener('input', function(e) {
const val = e.target.value.trim().toLowerCase();
didYouMeanBox.style.display = 'none';
didYouMeanBox.textContent = '';
if (!val) return;
const abbrs = Object.keys(abbrMap);
let minDist = Infinity, closest = '';
abbrs.forEach(abbr => {
const dist = levenshtein(val, abbr);
if (dist < minDist && dist <= 2) { minDist = dist; closest = abbr; }
});
if (closest && closest !== val) {
didYouMeanBox.textContent = `Did you mean: ${closest}? (Click to search)`;
didYouMeanBox.style.display = 'block';
didYouMeanBox.onclick = function() {
searchInput.value = closest;
searchInput.dispatchEvent(new Event('input'));
didYouMeanBox.style.display = 'none';
};
}
});
// Hide suggestion on blur
searchInput.addEventListener('blur', function() {
setTimeout(() => { didYouMeanBox.style.display = 'none'; }, 200);
});
});
});
// --- End Simple Did You Mean Suggestion ---
12 changes: 12 additions & 0 deletions docs/qualityOfLife.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
---
title: Quality of Life Additions
description: Tools and features to improve user experience on the CAPLEX website.
tags:
- usability
- search
- abbreviations
- help
---

## Quality of life additions

This section will introduce you to some tools available on this website to make your experience better.
Expand All @@ -20,6 +30,8 @@ You can right-click on any [link](#copying-reference-doi), such as a reference t

At the top of the webpage, you may find the `Search` bar allowing you to find resources within the website quickly. If you wish to find a table row by code, enclose the code using `""`, for example to find Gradient echo model you could search for `"M.SM1.001"`.

**See the [Search Help](search-help.md) page for tips on getting the best results.**

!!! warning

The greek letters rendered using MathJax cannot be searched for at the moment.
Expand Down
47 changes: 47 additions & 0 deletions docs/search-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Search Help

Welcome to the CAPLEX Search Help page! Here you'll find tips and features to help you get the most out of the search functionality.

## Summary Table: What Each Change Does

| Feature | User Benefit |
|------------------------|----------------------------------------------|
| Page metadata | More relevant, ranked search results |
| Abbreviations/synonyms | Find results for all common terms |
| Search result previews | See context for each result |
| Highlighting | Instantly spot search terms in results |
| Did you mean/fuzzy | Find results even with typos or misspellings |
| Search help page | Users know how to get the best results |

## How to Use Search

- Use the search bar at the top of any page to quickly find terms, models, or processes.
- Enclose codes in quotes (e.g., `"M.SM1.001"`) to find specific table rows.
- Search is typo-tolerant and will suggest corrections for common misspellings.
- Results show a preview/snippet for context.
- Search terms are highlighted in the results.

## Abbreviations and Synonyms

- Common abbreviations (e.g., DCE, MRI, ROI) are recognized. Hover over underlined abbreviations for definitions.
- Synonyms and alternative names are indexed—try searching for any common term.

## Fuzzy Search and "Did You Mean"

- If you make a typo, the search will suggest the closest matching term.
- Try partial words or common misspellings—relevant results will still appear.

## Search Result Previews

- Each result includes a snippet of the surrounding text for context.
- Click a result to jump directly to the relevant section.

## Highlighting

- Your search terms are highlighted in the results for easy scanning.

## More Tips

- For best results, use specific terms or codes.
- If you can't find what you're looking for, try a synonym or abbreviation.
- For more help, see the [Quality of Life](qualityOfLife.md) page or [Style Guide](style-guide.md).
51 changes: 29 additions & 22 deletions docs/stylesheets/extra.css
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
/* Force the table to use the full page width, may cause issues on mobile */
.md-typeset__table {
width: 100%;
}

.md-typeset__table table:not([class]) {
display: table
}
/* This automatically stretches the site contents to monitor width*/
.md-grid {
max-width: initial;
}
/* Preserve words so they are not broken in the middle on newlines */
.md-typeset td {
overflow-wrap: break-word;
}
/* Control hyperlink button properties */
.md-button.md-button--hyperlink {
/* top | right | bottom | left */
padding: 3px 2px;
font-size: 12px;
}
/* Force the table to use the full page width, may cause issues on mobile */
.md-typeset__table {
width: 100%;
}

.md-typeset__table table:not([class]) {
display: table;
}
/* This automatically stretches the site contents to monitor width*/
.md-grid {
max-width: initial;
}
/* Preserve words so they are not broken in the middle on newlines */
.md-typeset td {
overflow-wrap: break-word;
}
/* Control hyperlink button properties */
.md-button.md-button--hyperlink {
/* top | right | bottom | left */
padding: 3px 2px;
font-size: 12px;
}
/* docs/stylesheets/extra.css */
.md-search-result__highlight {
background-color: #ffe066;
color: #222;
padding: 0 2px;
border-radius: 2px;
}
15 changes: 14 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ copyright: >

theme:
name: material
features:
- search.suggest
- search.highlight
- search.share
logo: osipiImgs/OSIPI_logo.png
favicon: osipiImgs/OSIPI_logo_only_square.png
palette:
Expand All @@ -28,6 +32,8 @@ theme:
name: Switch to light mode
features:
- search.suggest
- search.highlight
- search.share
icon:
admonition:
note: fontawesome/solid/note-sticky
Expand Down Expand Up @@ -62,7 +68,14 @@ nav:
plugins:
- search:
lang: en
separator: '[\s\-,:!=\[\]()"/]+|(?!\b)(?=[A-Z][a-z])|\.(?!\d)|&[lg]t;'
separator: '[\s\-\.,:;!?\[\]\(\)"/\*\^_~\+]+|(?<=[a-z])(?=[A-Z])'
prebuild_index: true
min_search_length: 2
indexing: full
boost: 7
pipeline:
- stopWordFilter


markdown_extensions:
- toc:
Expand Down
Loading