Compare commits
6 Commits
6359aefd18
...
reese/add-
| Author | SHA1 | Date | |
|---|---|---|---|
|
4fa64cfc70
|
|||
|
e09ad1edf2
|
|||
|
d0c84aef7f
|
|||
|
61bb818140
|
|||
|
b1b81a04ed
|
|||
|
9042468fe8
|
176
css/style.css
176
css/style.css
@@ -413,7 +413,6 @@ footer {
|
|||||||
padding: 1.8rem;
|
padding: 1.8rem;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
box-shadow: 0 -4px 20px rgba(255,20,147,0.3);
|
box-shadow: 0 -4px 20px rgba(255,20,147,0.3);
|
||||||
margin-left: 240px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
@@ -1615,3 +1614,178 @@ footer {
|
|||||||
background: linear-gradient(135deg, var(--pink-500), #1a1a3e);
|
background: linear-gradient(135deg, var(--pink-500), #1a1a3e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Search */
|
||||||
|
.sidebar-search {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-search-input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 0.55rem 0.8rem;
|
||||||
|
border: 2px solid rgba(255,255,255,0.15);
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 0.85rem;
|
||||||
|
color: var(--white);
|
||||||
|
background: rgba(0,0,0,0.2);
|
||||||
|
font-family: inherit;
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.2s, background 0.2s;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-search-input::placeholder {
|
||||||
|
color: rgba(255,255,255,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-search-input:focus {
|
||||||
|
border-color: var(--pink-400);
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-results-dropdown {
|
||||||
|
position: fixed;
|
||||||
|
background: var(--white);
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 40px rgba(0,0,0,0.2), 0 4px 10px rgba(255,20,147,0.15);
|
||||||
|
border: 2px solid var(--pink-200);
|
||||||
|
z-index: 9999;
|
||||||
|
display: none;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-item {
|
||||||
|
padding: 0.75rem 0.9rem;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 1px solid var(--pink-100);
|
||||||
|
transition: background 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-item:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-item:hover,
|
||||||
|
.search-result-item.active {
|
||||||
|
background: var(--pink-50);
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.4rem;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-page {
|
||||||
|
font-size: 0.72rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--pink-500);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-category {
|
||||||
|
font-size: 0.68rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--pink-400);
|
||||||
|
background: var(--pink-100);
|
||||||
|
padding: 0.1rem 0.45rem;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-heading {
|
||||||
|
font-size: 0.92rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--pink-700);
|
||||||
|
margin-bottom: 0.15rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-snippet {
|
||||||
|
font-size: 0.82rem;
|
||||||
|
color: var(--pink-800);
|
||||||
|
line-height: 1.4;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-no-results {
|
||||||
|
padding: 1rem 0.9rem;
|
||||||
|
font-size: 0.88rem;
|
||||||
|
color: var(--pink-400);
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-highlight {
|
||||||
|
background: var(--pink-200);
|
||||||
|
color: var(--pink-900);
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0 0.1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dark mode search styles */
|
||||||
|
[data-theme="dark"] .sidebar-search-input {
|
||||||
|
border-color: rgba(255,255,255,0.1);
|
||||||
|
color: var(--text-primary);
|
||||||
|
background: rgba(255,255,255,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .sidebar-search-input::placeholder {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .sidebar-search-input:focus {
|
||||||
|
border-color: var(--border-accent);
|
||||||
|
background: rgba(255,255,255,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-results-dropdown {
|
||||||
|
background: var(--bg-card);
|
||||||
|
border-color: var(--border-primary);
|
||||||
|
box-shadow: 0 10px 40px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-result-item {
|
||||||
|
border-bottom-color: var(--border-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-result-item:hover,
|
||||||
|
[data-theme="dark"] .search-result-item.active {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-result-page {
|
||||||
|
color: var(--text-heading-strong);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-result-category {
|
||||||
|
color: var(--text-heading);
|
||||||
|
background: rgba(255,20,147,0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-result-heading {
|
||||||
|
color: var(--text-heading);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-result-snippet {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-no-results {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .search-highlight {
|
||||||
|
background: rgba(255,20,147,0.2);
|
||||||
|
color: var(--text-heading);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,9 +157,13 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
<script src="lib/llm.js"></script>
|
<script src="lib/llm.js"></script>
|
||||||
|
<script src="lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
function askQuestion() {
|
function askQuestion() {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// Shared LLM module - provides streaming chat to any page
|
|
||||||
var LLM = (function() {
|
var LLM = (function() {
|
||||||
var defaultApiUrl = 'https://llama-instruct.reeselink.com/v1';
|
var defaultApiUrl = 'https://llama-instruct.reeselink.com/v1';
|
||||||
var defaultModel = 'instruct';
|
var defaultModel = 'instruct';
|
||||||
|
|||||||
69
lib/marked.min.js
vendored
Normal file
69
lib/marked.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
566
lib/search.js
Normal file
566
lib/search.js
Normal file
@@ -0,0 +1,566 @@
|
|||||||
|
var Search = (function() {
|
||||||
|
var dropdownVisible = false;
|
||||||
|
var selectedIndex = -1;
|
||||||
|
var results = [];
|
||||||
|
var debounceTimer = null;
|
||||||
|
var currentInput = null;
|
||||||
|
|
||||||
|
// Page title mapping
|
||||||
|
var PAGE_TITLES = {
|
||||||
|
'index.html': 'Home',
|
||||||
|
'terminology.html': 'Terminology',
|
||||||
|
'techniques.html': 'Techniques',
|
||||||
|
'use-cases.html': 'Use Cases',
|
||||||
|
'model-types.html': 'Model Types',
|
||||||
|
'prompts.html': 'Prompt Guide',
|
||||||
|
'math.html': 'Math & Concepts',
|
||||||
|
'chat.html': 'Chat',
|
||||||
|
'image-gen.html': 'Image Gen'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Content to skip during crawling
|
||||||
|
var SKIP_CONTENT = [
|
||||||
|
'AI Cheat Sheet',
|
||||||
|
'Toggle dark mode',
|
||||||
|
'Toggle menu',
|
||||||
|
'Send',
|
||||||
|
'Ask me anything about AI',
|
||||||
|
'Ask a Question',
|
||||||
|
'Ask anything about AI',
|
||||||
|
'Powered by your configured LLM',
|
||||||
|
'Try AI right now',
|
||||||
|
'Full Chat',
|
||||||
|
'Generate',
|
||||||
|
'Clear',
|
||||||
|
'Image Generation',
|
||||||
|
'Enter image prompt'
|
||||||
|
];
|
||||||
|
|
||||||
|
function assignAnchors() {
|
||||||
|
var defCards = document.querySelectorAll('.def-card');
|
||||||
|
defCards.forEach(function(card) {
|
||||||
|
var h3 = card.querySelector('h3');
|
||||||
|
if (h3) {
|
||||||
|
var id = slugify(h3.textContent.trim());
|
||||||
|
if (id) card.setAttribute('id', id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var tables = document.querySelectorAll('.glossary-table tbody tr');
|
||||||
|
tables.forEach(function(row) {
|
||||||
|
var firstTd = row.querySelector('td');
|
||||||
|
if (firstTd) {
|
||||||
|
var id = slugify(firstTd.textContent.trim());
|
||||||
|
if (id) row.setAttribute('id', id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var useGrid = document.querySelector('.use-grid');
|
||||||
|
if (useGrid) {
|
||||||
|
var useCards = useGrid.querySelectorAll('.use-card');
|
||||||
|
useCards.forEach(function(card) {
|
||||||
|
var h3 = card.querySelector('h3');
|
||||||
|
if (h3) {
|
||||||
|
var id = slugify(h3.textContent.trim());
|
||||||
|
if (id) card.setAttribute('id', id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var promptBlocks = document.querySelectorAll('.prompt-block');
|
||||||
|
promptBlocks.forEach(function(block) {
|
||||||
|
var h3 = block.querySelector('h3');
|
||||||
|
if (h3) {
|
||||||
|
var id = slugify(h3.textContent.trim());
|
||||||
|
if (id) block.setAttribute('id', id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
var navInner = document.querySelector('.nav-inner');
|
||||||
|
if (!navInner) return;
|
||||||
|
|
||||||
|
var brand = navInner.querySelector('.nav-brand');
|
||||||
|
if (!brand) return;
|
||||||
|
|
||||||
|
assignAnchors();
|
||||||
|
|
||||||
|
// Create search wrapper
|
||||||
|
var searchWrapper = document.createElement('div');
|
||||||
|
searchWrapper.className = 'sidebar-search';
|
||||||
|
searchWrapper.style.cssText = 'position:relative; margin-top:0.5rem; margin-bottom:0.25rem;';
|
||||||
|
|
||||||
|
var searchInput = document.createElement('input');
|
||||||
|
searchInput.type = 'text';
|
||||||
|
searchInput.className = 'sidebar-search-input';
|
||||||
|
searchInput.placeholder = 'Search...';
|
||||||
|
searchInput.setAttribute('aria-label', 'Search all pages');
|
||||||
|
searchInput.autocomplete = 'off';
|
||||||
|
|
||||||
|
searchWrapper.appendChild(searchInput);
|
||||||
|
|
||||||
|
// Insert after brand
|
||||||
|
brand.parentNode.insertBefore(searchWrapper, brand.nextSibling);
|
||||||
|
|
||||||
|
currentInput = searchInput;
|
||||||
|
|
||||||
|
// Event listeners
|
||||||
|
searchInput.addEventListener('input', function(e) {
|
||||||
|
clearTimeout(debounceTimer);
|
||||||
|
var query = e.target.value.trim();
|
||||||
|
if (query.length === 0) {
|
||||||
|
hideDropdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debounceTimer = setTimeout(function() {
|
||||||
|
performSearch(query);
|
||||||
|
}, 150);
|
||||||
|
});
|
||||||
|
|
||||||
|
searchInput.addEventListener('keydown', function(e) {
|
||||||
|
if (!dropdownVisible || results.length === 0) return;
|
||||||
|
|
||||||
|
if (e.key === 'ArrowDown') {
|
||||||
|
e.preventDefault();
|
||||||
|
selectedIndex = Math.min(selectedIndex + 1, results.length - 1);
|
||||||
|
updateSelection();
|
||||||
|
} else if (e.key === 'ArrowUp') {
|
||||||
|
e.preventDefault();
|
||||||
|
selectedIndex = Math.max(selectedIndex - 1, 0);
|
||||||
|
updateSelection();
|
||||||
|
} else if (e.key === 'Enter') {
|
||||||
|
e.preventDefault();
|
||||||
|
if (selectedIndex >= 0 && selectedIndex < results.length) {
|
||||||
|
navigateToResult(results[selectedIndex]);
|
||||||
|
} else if (results.length > 0) {
|
||||||
|
navigateToResult(results[0]);
|
||||||
|
}
|
||||||
|
} else if (e.key === 'Escape') {
|
||||||
|
e.preventDefault();
|
||||||
|
hideDropdown();
|
||||||
|
searchInput.blur();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
searchInput.addEventListener('focus', function() {
|
||||||
|
if (results.length > 0 && currentInput.value.trim().length > 0) {
|
||||||
|
showDropdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close dropdown when clicking outside
|
||||||
|
document.addEventListener('click', function(e) {
|
||||||
|
if (!searchWrapper.contains(e.target)) {
|
||||||
|
hideDropdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reposition on scroll and resize
|
||||||
|
function positionDropdown() {
|
||||||
|
var container = document.getElementById('searchResultsContainer');
|
||||||
|
if (!container || !dropdownVisible) return;
|
||||||
|
var rect = currentInput.getBoundingClientRect();
|
||||||
|
var vw = window.innerWidth;
|
||||||
|
container.style.top = (rect.bottom + 5) + 'px';
|
||||||
|
if (vw <= 900) {
|
||||||
|
container.style.left = '0';
|
||||||
|
container.style.width = '100vw';
|
||||||
|
} else {
|
||||||
|
container.style.left = rect.left + 'px';
|
||||||
|
container.style.width = '520px';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('scroll', positionDropdown);
|
||||||
|
window.addEventListener('resize', positionDropdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
function crawlPage(url, callback) {
|
||||||
|
fetch(url)
|
||||||
|
.then(function(response) { return response.text(); })
|
||||||
|
.then(function(html) {
|
||||||
|
var parser = new DOMParser();
|
||||||
|
var doc = parser.parseFromString(html, 'text/html');
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
// Get page title
|
||||||
|
var pageTitle = PAGE_TITLES[doc.title.replace(' - Cheat Sheet', '').replace('AI Cheat Sheet', '').trim()] || doc.title;
|
||||||
|
|
||||||
|
// Extract def-cards
|
||||||
|
var defCards = doc.querySelectorAll('.def-card');
|
||||||
|
defCards.forEach(function(card) {
|
||||||
|
var heading = card.querySelector('h3');
|
||||||
|
var p = card.querySelector('p');
|
||||||
|
var example = card.querySelector('.example');
|
||||||
|
var category = card.querySelector('.category');
|
||||||
|
|
||||||
|
if (!heading || !p) return;
|
||||||
|
|
||||||
|
var headingText = heading.textContent.trim();
|
||||||
|
var defText = p.textContent.trim();
|
||||||
|
var catText = category ? category.textContent.trim() : '';
|
||||||
|
var exText = example ? example.textContent.trim() : '';
|
||||||
|
|
||||||
|
var fullText = (catText + ' ' + headingText + ' ' + defText + ' ' + exText).trim();
|
||||||
|
if (fullText.length < 10) return;
|
||||||
|
|
||||||
|
// Skip boilerplate content
|
||||||
|
var skip = false;
|
||||||
|
for (var i = 0; i < SKIP_CONTENT.length; i++) {
|
||||||
|
if (fullText.indexOf(SKIP_CONTENT[i]) === 0) { skip = true; break; }
|
||||||
|
}
|
||||||
|
if (skip) return;
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
page: pageTitle,
|
||||||
|
url: url,
|
||||||
|
heading: headingText,
|
||||||
|
category: catText,
|
||||||
|
snippet: defText,
|
||||||
|
fullText: fullText.toLowerCase(),
|
||||||
|
anchor: slugify(headingText)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract table rows
|
||||||
|
var tables = doc.querySelectorAll('.glossary-table tbody tr');
|
||||||
|
tables.forEach(function(row) {
|
||||||
|
var tds = row.querySelectorAll('td');
|
||||||
|
if (tds.length < 2) return;
|
||||||
|
|
||||||
|
var acronym = tds[0].textContent.trim();
|
||||||
|
var meaning = tds[1].textContent.trim();
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
page: pageTitle,
|
||||||
|
url: url,
|
||||||
|
heading: acronym,
|
||||||
|
category: 'Acronym',
|
||||||
|
snippet: meaning,
|
||||||
|
fullText: (acronym + ' ' + meaning).toLowerCase(),
|
||||||
|
anchor: slugify(acronym)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extract section headings for pages without def-cards (like use-cases, model-types)
|
||||||
|
var sections = doc.querySelectorAll('h2.section-title');
|
||||||
|
sections.forEach(function(h2) {
|
||||||
|
var sectionName = h2.textContent.trim();
|
||||||
|
// Check if there are cards under this section
|
||||||
|
var next = h2.nextElementSibling;
|
||||||
|
var cards = [];
|
||||||
|
while (next && !next.classList.contains('section-title')) {
|
||||||
|
if (next.classList && (next.classList.contains('card') || next.classList.contains('use-card') || next.classList.contains('prompt-block') || next.classList.contains('def-card'))) {
|
||||||
|
cards.push(next);
|
||||||
|
}
|
||||||
|
next = next.nextElementSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
cards.forEach(function(card) {
|
||||||
|
var h3 = card.querySelector('h3');
|
||||||
|
var p = card.querySelector('p');
|
||||||
|
if (!h3 || !p) return;
|
||||||
|
|
||||||
|
var headingText = h3.textContent.trim();
|
||||||
|
var cardText = p.textContent.trim();
|
||||||
|
|
||||||
|
// Skip if already captured as def-card
|
||||||
|
if (card.classList.contains('def-card')) return;
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
page: pageTitle,
|
||||||
|
url: url,
|
||||||
|
heading: headingText,
|
||||||
|
category: sectionName,
|
||||||
|
snippet: cardText,
|
||||||
|
fullText: (sectionName + ' ' + headingText + ' ' + cardText).toLowerCase(),
|
||||||
|
anchor: slugify(headingText)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// For pages with .use-grid, extract use-cards
|
||||||
|
var useGrid = doc.querySelector('.use-grid');
|
||||||
|
if (useGrid) {
|
||||||
|
var useCards = useGrid.querySelectorAll('.use-card');
|
||||||
|
useCards.forEach(function(card) {
|
||||||
|
var h3 = card.querySelector('h3');
|
||||||
|
var p = card.querySelector('p');
|
||||||
|
if (!h3 || !p) return;
|
||||||
|
var headingText = h3.textContent.trim();
|
||||||
|
var cardText = p.textContent.trim();
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
page: pageTitle,
|
||||||
|
url: url,
|
||||||
|
heading: headingText,
|
||||||
|
category: 'Use Case',
|
||||||
|
snippet: cardText,
|
||||||
|
fullText: (headingText + ' ' + cardText).toLowerCase(),
|
||||||
|
anchor: slugify(headingText)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For prompt guide, extract prompt-blocks
|
||||||
|
var promptBlocks = doc.querySelectorAll('.prompt-block');
|
||||||
|
if (promptBlocks.length > 0) {
|
||||||
|
promptBlocks.forEach(function(block) {
|
||||||
|
var h3 = block.querySelector('h3');
|
||||||
|
var label = block.querySelector('.label');
|
||||||
|
var p = block.querySelector('p');
|
||||||
|
|
||||||
|
if (!h3) return;
|
||||||
|
var headingText = h3.textContent.trim();
|
||||||
|
var labelText = label ? label.textContent.trim() : '';
|
||||||
|
var cardText = p ? p.textContent.trim() : '';
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
page: pageTitle,
|
||||||
|
url: url,
|
||||||
|
heading: headingText,
|
||||||
|
category: labelText || 'Prompt',
|
||||||
|
snippet: cardText,
|
||||||
|
fullText: (headingText + ' ' + labelText + ' ' + cardText).toLowerCase(),
|
||||||
|
anchor: slugify(headingText)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// For math page, extract def-cards (already handled above)
|
||||||
|
// For model-types, also grab comparison table
|
||||||
|
var modelTables = doc.querySelectorAll('.glossary-table');
|
||||||
|
if (modelTables.length > 0) {
|
||||||
|
modelTables.forEach(function(table) {
|
||||||
|
var rows = table.querySelectorAll('tbody tr');
|
||||||
|
rows.forEach(function(row) {
|
||||||
|
var tds = row.querySelectorAll('td');
|
||||||
|
if (tds.length === 0) return;
|
||||||
|
var rowText = '';
|
||||||
|
for (var i = 0; i < tds.length; i++) {
|
||||||
|
rowText += ' ' + tds[i].textContent.trim();
|
||||||
|
}
|
||||||
|
if (rowText.length < 5) return;
|
||||||
|
|
||||||
|
results.push({
|
||||||
|
page: pageTitle,
|
||||||
|
url: url,
|
||||||
|
heading: tds[0] ? tds[0].textContent.trim() : 'Table Entry',
|
||||||
|
category: 'Comparison',
|
||||||
|
snippet: rowText.trim(),
|
||||||
|
fullText: rowText.toLowerCase(),
|
||||||
|
anchor: slugify(tds[0] ? tds[0].textContent.trim() : 'Table Entry')
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(results);
|
||||||
|
})
|
||||||
|
.catch(function() {
|
||||||
|
callback([]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function crawlAllPages(callback) {
|
||||||
|
var pages = [
|
||||||
|
{ url: '/index.html', title: 'Home' },
|
||||||
|
{ url: '/pages/terminology.html', title: 'Terminology' },
|
||||||
|
{ url: '/pages/techniques.html', title: 'Techniques' },
|
||||||
|
{ url: '/pages/use-cases.html', title: 'Use Cases' },
|
||||||
|
{ url: '/pages/model-types.html', title: 'Model Types' },
|
||||||
|
{ url: '/pages/prompts.html', title: 'Prompt Guide' },
|
||||||
|
{ url: '/pages/math.html', title: 'Math & Concepts' }
|
||||||
|
];
|
||||||
|
|
||||||
|
var allResults = [];
|
||||||
|
var completed = 0;
|
||||||
|
|
||||||
|
if (pages.length === 0) {
|
||||||
|
callback(allResults);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pages.forEach(function(page) {
|
||||||
|
crawlPage(page.url, function(results) {
|
||||||
|
allResults = allResults.concat(results);
|
||||||
|
completed++;
|
||||||
|
if (completed === pages.length) {
|
||||||
|
callback(allResults);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function performSearch(query) {
|
||||||
|
var q = query.toLowerCase().trim();
|
||||||
|
if (q.length === 0) { hideDropdown(); return; }
|
||||||
|
|
||||||
|
crawlAllPages(function(allResults) {
|
||||||
|
searchResults(allResults, q);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchResults(allResults, q) {
|
||||||
|
var qWords = q.split(/\s+/).filter(function(w) { return w.length > 0; });
|
||||||
|
var scored = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < allResults.length; i++) {
|
||||||
|
var item = allResults[i];
|
||||||
|
var text = item.fullText || '';
|
||||||
|
var score = 0;
|
||||||
|
|
||||||
|
if (text.indexOf(q) !== -1) score += 100;
|
||||||
|
|
||||||
|
for (var j = 0; j < qWords.length; j++) {
|
||||||
|
if (text.indexOf(qWords[j]) !== -1) score += 10;
|
||||||
|
if (item.heading && item.heading.toLowerCase().indexOf(qWords[j]) === 0) score += 20;
|
||||||
|
if (item.category && item.category.toLowerCase().indexOf(qWords[j]) !== -1) score += 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (score > 0) {
|
||||||
|
scored.push({ item: item, score: score });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scored.sort(function(a, b) { return b.score - a.score; });
|
||||||
|
var topResults = scored.slice(0, 10).map(function(s) { return s.item; });
|
||||||
|
displayResults(topResults, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlightText(text, query) {
|
||||||
|
if (!text || !query) return escapeHTML(text);
|
||||||
|
var escaped = escapeHTML(text);
|
||||||
|
var qWords = query.toLowerCase().split(/\s+/).filter(function(w) { return w.length > 0; });
|
||||||
|
|
||||||
|
for (var i = 0; i < qWords.length; i++) {
|
||||||
|
var word = qWords[i];
|
||||||
|
var regex = new RegExp('(' + escapeRegex(word) + ')', 'gi');
|
||||||
|
escaped = escaped.replace(regex, '<mark class="search-highlight">$1</mark>');
|
||||||
|
}
|
||||||
|
|
||||||
|
return escaped;
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeRegex(str) {
|
||||||
|
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
}
|
||||||
|
|
||||||
|
function escapeHTML(str) {
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.textContent = str;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
function slugify(text) {
|
||||||
|
return text
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\(.*?\)/g, function(match) { return match.replace(/[()]/g, ''); })
|
||||||
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
|
.replace(/^-+|-+$/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
function displayResults(foundResults, query) {
|
||||||
|
results = foundResults;
|
||||||
|
selectedIndex = -1;
|
||||||
|
|
||||||
|
if (results.length === 0) {
|
||||||
|
showDropdown();
|
||||||
|
var container = document.getElementById('searchResultsContainer');
|
||||||
|
if (container) {
|
||||||
|
container.innerHTML = '<div class="search-no-results">No results found for "' + escapeHTML(query) + '"</div>';
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var container = document.getElementById('searchResultsContainer');
|
||||||
|
var html = '';
|
||||||
|
for (var i = 0; i < results.length; i++) {
|
||||||
|
var r = results[i];
|
||||||
|
var categoryLabel = r.category ? '<span class="search-result-category">' + escapeHTML(r.category) + '</span>' : '';
|
||||||
|
var highlightedSnippet = highlightText(r.snippet, query);
|
||||||
|
|
||||||
|
html += '<div class="search-result-item" data-index="' + i + '" data-url="' + escapeHTML(r.url) + '" data-anchor="' + escapeHTML(r.anchor || '') + '">';
|
||||||
|
html += '<div class="search-result-title">';
|
||||||
|
html += '<span class="search-result-page">' + escapeHTML(r.page) + '</span>';
|
||||||
|
html += categoryLabel;
|
||||||
|
html += '</div>';
|
||||||
|
html += '<div class="search-result-heading">' + highlightText(r.heading, query) + '</div>';
|
||||||
|
html += '<div class="search-result-snippet">' + highlightedSnippet + '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
container.innerHTML = html;
|
||||||
|
showDropdown();
|
||||||
|
|
||||||
|
// Attach click handlers
|
||||||
|
var items = container.querySelectorAll('.search-result-item');
|
||||||
|
for (var j = 0; j < items.length; j++) {
|
||||||
|
items[j].addEventListener('click', function() {
|
||||||
|
var url = this.getAttribute('data-url');
|
||||||
|
var anchor = this.getAttribute('data-anchor');
|
||||||
|
navigateToResult({ url: url, anchor: anchor });
|
||||||
|
});
|
||||||
|
items[j].addEventListener('mouseenter', function() {
|
||||||
|
var idx = parseInt(this.getAttribute('data-index'), 10);
|
||||||
|
selectedIndex = idx;
|
||||||
|
updateSelection();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelection() {
|
||||||
|
var items = document.querySelectorAll('.search-result-item');
|
||||||
|
for (var i = 0; i < items.length; i++) {
|
||||||
|
if (i === selectedIndex) {
|
||||||
|
items[i].classList.add('active');
|
||||||
|
items[i].scrollIntoView({ block: 'nearest' });
|
||||||
|
} else {
|
||||||
|
items[i].classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showDropdown() {
|
||||||
|
var container = document.getElementById('searchResultsContainer');
|
||||||
|
if (container) {
|
||||||
|
var rect = currentInput.getBoundingClientRect();
|
||||||
|
var vw = window.innerWidth;
|
||||||
|
var sidebarWidth = 240;
|
||||||
|
|
||||||
|
if (vw <= 900) {
|
||||||
|
container.style.left = '0';
|
||||||
|
container.style.width = '100vw';
|
||||||
|
} else {
|
||||||
|
container.style.left = rect.left + 'px';
|
||||||
|
container.style.width = '520px';
|
||||||
|
}
|
||||||
|
container.style.top = (rect.bottom + 5) + 'px';
|
||||||
|
container.style.display = 'block';
|
||||||
|
dropdownVisible = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideDropdown() {
|
||||||
|
var container = document.getElementById('searchResultsContainer');
|
||||||
|
if (container) {
|
||||||
|
container.style.display = 'none';
|
||||||
|
}
|
||||||
|
dropdownVisible = false;
|
||||||
|
selectedIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function navigateToResult(result) {
|
||||||
|
hideDropdown();
|
||||||
|
if (currentInput) currentInput.blur();
|
||||||
|
var target = result.url;
|
||||||
|
if (result.anchor) {
|
||||||
|
target = result.url + '#' + result.anchor;
|
||||||
|
}
|
||||||
|
window.location.href = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
init: init
|
||||||
|
};
|
||||||
|
})();
|
||||||
@@ -119,6 +119,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
|
<script src="../lib/marked.min.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
var chatMessages = document.getElementById('chatMessages');
|
var chatMessages = document.getElementById('chatMessages');
|
||||||
@@ -129,6 +135,12 @@
|
|||||||
var apiTokenInput = document.getElementById('apiToken');
|
var apiTokenInput = document.getElementById('apiToken');
|
||||||
var modelNameInput = document.getElementById('modelName');
|
var modelNameInput = document.getElementById('modelName');
|
||||||
|
|
||||||
|
// Parse markdown in initial welcome message
|
||||||
|
var initialBubble = chatMessages.querySelector('.message-bubble p');
|
||||||
|
if(initialBubble) {
|
||||||
|
initialBubble.innerHTML = marked.parseInline(initialBubble.textContent);
|
||||||
|
}
|
||||||
|
|
||||||
// Restore saved settings
|
// Restore saved settings
|
||||||
var savedToken = localStorage.getItem('apiToken');
|
var savedToken = localStorage.getItem('apiToken');
|
||||||
if(savedToken) apiTokenInput.value = savedToken;
|
if(savedToken) apiTokenInput.value = savedToken;
|
||||||
@@ -153,7 +165,11 @@
|
|||||||
|
|
||||||
var p = document.createElement('p');
|
var p = document.createElement('p');
|
||||||
p.className = 'message-content';
|
p.className = 'message-content';
|
||||||
p.textContent = content;
|
if(role === 'assistant') {
|
||||||
|
p.innerHTML = marked.parse(content);
|
||||||
|
} else {
|
||||||
|
p.textContent = content;
|
||||||
|
}
|
||||||
bubble.appendChild(p);
|
bubble.appendChild(p);
|
||||||
|
|
||||||
msgDiv.appendChild(avatar);
|
msgDiv.appendChild(avatar);
|
||||||
@@ -271,7 +287,7 @@
|
|||||||
var delta = json.choices && json.choices[0] && json.choices[0].delta;
|
var delta = json.choices && json.choices[0] && json.choices[0].delta;
|
||||||
if(delta && delta.content) {
|
if(delta && delta.content) {
|
||||||
streamContent += delta.content;
|
streamContent += delta.content;
|
||||||
contentEl.textContent = streamContent;
|
contentEl.innerHTML = marked.parse(streamContent);
|
||||||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||||||
}
|
}
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
@@ -313,7 +329,7 @@
|
|||||||
chatMessages.innerHTML = '';
|
chatMessages.innerHTML = '';
|
||||||
var welcomeMsg = document.createElement('div');
|
var welcomeMsg = document.createElement('div');
|
||||||
welcomeMsg.className = 'message assistant-message';
|
welcomeMsg.className = 'message assistant-message';
|
||||||
welcomeMsg.innerHTML = '<div class="message-avatar">AI</div><div class="message-bubble"><p>Hello! Chat cleared. How can I help you?</p></div>';
|
welcomeMsg.innerHTML = '<div class="message-avatar">AI</div><div class="message-bubble"><p>' + marked.parse('Hello! Chat cleared. How can I help you?') + '</p></div>';
|
||||||
chatMessages.appendChild(welcomeMsg);
|
chatMessages.appendChild(welcomeMsg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -115,6 +115,11 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
var apiUrlInput = document.getElementById('apiUrl');
|
var apiUrlInput = document.getElementById('apiUrl');
|
||||||
@@ -282,7 +287,7 @@
|
|||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
model: model,
|
model: model,
|
||||||
n: 1,
|
n: 1,
|
||||||
size: '1024x1024'
|
size: '512x512'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.then(function(response) {
|
.then(function(response) {
|
||||||
|
|||||||
@@ -260,8 +260,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<script src="../lib/modal.js"></script>
|
<script src="../lib/modal.js"></script>
|
||||||
<script src="../lib/llm.js"></script>
|
<script src="../lib/llm.js"></script>
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
function walkThrough(title, prompt) {
|
function walkThrough(title, prompt) {
|
||||||
|
|||||||
@@ -237,8 +237,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<script src="../lib/modal.js"></script>
|
<script src="../lib/modal.js"></script>
|
||||||
<script src="../lib/llm.js"></script>
|
<script src="../lib/llm.js"></script>
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
function explainModel(title, definition) {
|
function explainModel(title, definition) {
|
||||||
|
|||||||
@@ -236,8 +236,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<script src="../lib/modal.js"></script>
|
<script src="../lib/modal.js"></script>
|
||||||
<script src="../lib/llm.js"></script>
|
<script src="../lib/llm.js"></script>
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
var techniquePrompts = {
|
var techniquePrompts = {
|
||||||
|
|||||||
@@ -200,8 +200,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<script src="../lib/modal.js"></script>
|
<script src="../lib/modal.js"></script>
|
||||||
<script src="../lib/llm.js"></script>
|
<script src="../lib/llm.js"></script>
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
function demoTechnique(title, prompt) {
|
function demoTechnique(title, prompt) {
|
||||||
|
|||||||
@@ -237,8 +237,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<script src="../lib/modal.js"></script>
|
<script src="../lib/modal.js"></script>
|
||||||
<script src="../lib/llm.js"></script>
|
<script src="../lib/llm.js"></script>
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
function explainTerm(title, definition) {
|
function explainTerm(title, definition) {
|
||||||
|
|||||||
@@ -232,8 +232,12 @@
|
|||||||
|
|
||||||
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
<footer>AI Cheat Sheet — A learning reference for artificial intelligence</footer>
|
||||||
|
|
||||||
|
<div class="search-results-dropdown" id="searchResultsContainer"></div>
|
||||||
|
|
||||||
<script src="../lib/modal.js"></script>
|
<script src="../lib/modal.js"></script>
|
||||||
<script src="../lib/llm.js"></script>
|
<script src="../lib/llm.js"></script>
|
||||||
|
<script src="../lib/search.js"></script>
|
||||||
|
<script>Search.init();</script>
|
||||||
<script>
|
<script>
|
||||||
(function(){
|
(function(){
|
||||||
function brainstormUseCase(title, prompt) {
|
function brainstormUseCase(title, prompt) {
|
||||||
|
|||||||
Reference in New Issue
Block a user