PageSourceSearch

https://yaml.org/js/mathjax.js

js yaml.org collected 2026-10-01 06:53:11 UTC 8,007 bytes, 284 lines download raw bytes

1// yaml.org Custom JavaScript
2
3// MathJax configuration
4window.MathJax = {
5  tex: {
6    inlineMath: [['$', '$'], ['\\(', '\\)']],
7    displayMath: [['$$', '$$'], ['\\[', '\\]']],
8    processEscapes: true,
9    processEnvironments: true
10  },
11  options: {
12    ignoreHtmlClass: 'tex2jax_ignore',
13    processHtmlClass: 'tex2jax_process'
14  }
15};
16
17// Custom functionality for yaml.org
18document.addEventListener('DOMContentLoaded', function() {
19  
20  // Add smooth scrolling to anchor links
21  document.querySelectorAll('a[href^="#"]').forEach(anchor => {
22    anchor.addEventListener('click', function (e) {
23      e.preventDefault();
24      const target = document.querySelector(this.getAttribute('href'));
25      if (target) {
26        target.scrollIntoView({
27          behavior: 'smooth',
28          block: 'start'
29        });
30      }
31    });
32  });
33
34  // Add sponsor card hover effects
35  document.querySelectorAll('.sponsor-card').forEach(card => {
36    card.addEventListener('mouseenter', function() {
37      this.style.transform = 'translateY(-4px)';
38    });
39    
40    card.addEventListener('mouseleave', function() {
41      this.style.transform = 'translateY(0)';
42    });
43  });
44
45  // Add stats counter animation
46  function animateCounters() {
47    document.querySelectorAll('.stat-number').forEach(counter => {
48      const target = parseInt(counter.textContent);
49      const duration = 2000;
50      const step = target / (duration / 16);
51      let current = 0;
52      
53      const timer = setInterval(() => {
54        current += step;
55        if (current >= target) {
56          current = target;
57          clearInterval(timer);
58        }
59        counter.textContent = Math.floor(current).toLocaleString();
60      }, 16);
61    });
62  }
63
64  // Trigger counter animation when stats come into view
65  const observer = new IntersectionObserver((entries) => {
66    entries.forEach(entry => {
67      if (entry.isIntersecting) {
68        animateCounters();
69        observer.unobserve(entry.target);
70      }
71    });
72  });
73
74  const statsSection = document.querySelector('.stats-grid');
75  if (statsSection) {
76    observer.observe(statsSection);
77  }
78
79  // Add mobile menu improvements
80  const mobileMenuToggle = document.querySelector('.md-header__button');
81  if (mobileMenuToggle) {
82    mobileMenuToggle.addEventListener('click', function() {
83      document.body.classList.toggle('mobile-menu-open');
84    });
85  }
86
87  // Add search highlighting
88  const searchInput = document.querySelector('.md-search__input');
89  if (searchInput) {
90    searchInput.addEventListener('input', function() {
91      const query = this.value.toLowerCase();
92      if (query.length > 2) {
93        highlightSearchResults(query);
94      } else {
95        clearSearchHighlights();
96      }
97    });
98  }
99
100  // Search result highlighting function
101  function highlightSearchResults(query) {
102    clearSearchHighlights();
103    
104    document.querySelectorAll('main').forEach(main => {
105      const walker = document.createTreeWalker(
106        main,
107        NodeFilter.SHOW_TEXT,
108        null,
109        false
110      );
111
112      let node;
113      while (node = walker.nextNode()) {
114        const text = node.textContent;
115        if (text.toLowerCase().includes(query)) {
116          const span = document.createElement('span');
117          span.className = 'search-highlight';
118          span.style.backgroundColor = 'rgba(255, 193, 7, 0.3)';
119          span.style.padding = '2px 4px';
120          span.style.borderRadius = '2px';
121          
122          const regex = new RegExp(`(${query})`, 'gi');
123          const highlightedText = text.replace(regex, '<span class="search-highlight">$1</span>');
124          
125          const wrapper = document.createElement('span');
126          wrapper.innerHTML = highlightedText;
127          node.parentNode.replaceChild(wrapper, node);
128        }
129      }
130    });
131  }
132
133  // Clear search highlights
134  function clearSearchHighlights() {
135    document.querySelectorAll('.search-highlight').forEach(highlight => {
136      const parent = highlight.parentNode;
137      parent.replaceChild(document.createTextNode(highlight.textContent), highlight);
138      parent.normalize();
139    });
140  }
141
142  // Add sponsor tier selection
143  document.querySelectorAll('.sponsor-tier-selector').forEach(selector => {
144    selector.addEventListener('change', function() {
145      const selectedTier = this.value;
146      updateSponsorDisplay(selectedTier);
147    });
148  });
149
150  // Update sponsor display based on selection
151  function updateSponsorDisplay(tier) {
152    document.querySelectorAll('.sponsor-card').forEach(card => {
153      if (tier === 'all' || card.classList.contains(tier)) {
154        card.style.display = 'block';
155      } else {
156        card.style.display = 'none';
157      }
158    });
159  }
160
161  // Add smooth page transitions
162  document.querySelectorAll('a[href^="/"]').forEach(link => {
163    link.addEventListener('click', function(e) {
164      if (this.hostname === window.location.hostname) {
165        e.preventDefault();
166        const targetUrl = this.href;
167        
168        // Add loading state
169        document.body.classList.add('page-loading');
170        
171        // Simulate page transition
172        setTimeout(() => {
173          window.location.href = targetUrl;
174        }, 300);
175      }
176    });
177  });
178
179  // Add back to top button
180  const backToTopButton = document.createElement('button');
181  backToTopButton.innerHTML = '↑';
182  backToTopButton.className = 'back-to-top';
183  backToTopButton.style.cssText = `
184    position: fixed;
185    bottom: 20px;
186    right: 20px;
187    width: 50px;
188    height: 50px;
189    border-radius: 50%;
190    background: var(--yaml-primary);
191    color: white;
192    border: none;
193    cursor: pointer;
194    font-size: 20px;
195    opacity: 0;
196    transition: opacity 0.3s ease;
197    z-index: 1000;
198  `;
199
200  document.body.appendChild(backToTopButton);
201
202  // Show/hide back to top button
203  window.addEventListener('scroll', function() {
204    if (window.pageYOffset > 300) {
205      backToTopButton.style.opacity = '1';
206    } else {
207      backToTopButton.style.opacity = '0';
208    }
209  });
210
211  // Back to top functionality
212  backToTopButton.addEventListener('click', function() {
213    window.scrollTo({
214      top: 0,
215      behavior: 'smooth'
216    });
217  });
218
219  // Add sponsor contact form handling
220  const sponsorForms = document.querySelectorAll('.sponsor-contact-form');
221  sponsorForms.forEach(form => {
222    form.addEventListener('submit', function(e) {
223      e.preventDefault();
224      
225      // Get form data
226      const formData = new FormData(this);
227      const data = Object.fromEntries(formData);
228      
229      // Show success message
230      showNotification('Thank you for your interest! We\'ll be in touch soon.', 'success');
231      
232      // Reset form
233      this.reset();
234    });
235  });
236
237  // Notification system
238  function showNotification(message, type = 'info') {
239    const notification = document.createElement('div');
240    notification.className = `notification notification-${type}`;
241    notification.textContent = message;
242    notification.style.cssText = `
243      position: fixed;
244      top: 20px;
245      right: 20px;
246      padding: 1rem 1.5rem;
247      border-radius: 4px;
248      color: white;
249      font-weight: 500;
250      z-index: 1001;
251      transform: translateX(100%);
252      transition: transform 0.3s ease;
253    `;
254
255    // Set background color based on type
256    switch (type) {
257      case 'success':
258        notification.style.background = 'var(--yaml-secondary)';
259        break;
260      case 'error':
261        notification.style.background = '#f44336';
262        break;
263      default:
264        notification.style.background = 'var(--yaml-primary)';
265    }
266
267    document.body.appendChild(notification);
268
269    // Animate in
270    setTimeout(() => {
271      notification.style.transform = 'translateX(0)';
272    }, 100);
273
274    // Auto-remove after 5 seconds
275    setTimeout(() => {
276      notification.style.transform = 'translateX(100%)';
277      setTimeout(() => {
278        document.body.removeChild(notification);
279      }, 300);
280    }, 5000);
281  }
282
283  console.log('yaml.org JavaScript loaded successfully!');
284}); 

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.