diff --git a/_docs/js/components.js b/_docs/js/components.js new file mode 100644 index 0000000..d0fa8d2 --- /dev/null +++ b/_docs/js/components.js @@ -0,0 +1,2 @@ +import * as header from "./components/header.js"; +import * as sidebar from "./components/sidebar.js"; diff --git a/_docs/js/components/header.js b/_docs/js/components/header.js new file mode 100644 index 0000000..9487930 --- /dev/null +++ b/_docs/js/components/header.js @@ -0,0 +1,49 @@ + +class Header extends HTMLElement { + + constructor(){ + super(); + } + + connectedCallback() { + this.innerHTML = ` +
+ +
+ + +
+
+ `; + } + + +} + +customElements.define('app-header', Header); \ No newline at end of file diff --git a/_docs/js/components/sidebar.js b/_docs/js/components/sidebar.js new file mode 100644 index 0000000..e0625cc --- /dev/null +++ b/_docs/js/components/sidebar.js @@ -0,0 +1,178 @@ +class Sidebar extends HTMLElement { + constructor() { + super(); + this.navItems = []; + } + + connectedCallback() { + this.render(); + this.scanHeaders(); + this.setupScrollListener(); + this.highlightActiveSection(); + } + + scanHeaders() { + // Clear existing nav items + this.navItems = []; + + // Find all h2 and h3 elements with IDs in the content area + const contentWrapper = document.querySelector('.content-wrapper'); + if (!contentWrapper) return; + + const headers = contentWrapper.querySelectorAll('h2[id], h3[id]'); + + headers.forEach(header => { + const id = header.getAttribute('id'); + const text = header.textContent.trim(); + const level = header.tagName.toLowerCase(); + + this.navItems.push({ + id, + text, + level, + element: header + }); + }); + + this.renderNavigation(); + } + + renderNavigation() { + const ul = this.querySelector('ul'); + if (!ul) return; + + // Clear existing content + ul.innerHTML = ''; + + let currentH2Li = null; + + this.navItems.forEach(item => { + if (item.level === 'h2') { + // Create h2 item + const li = document.createElement('li'); + const a = document.createElement('a'); + a.href = `#${item.id}`; + a.className = 'side-nav-h2'; + a.textContent = item.text; + a.addEventListener('click', (e) => this.handleNavClick(e, item.id)); + + li.appendChild(a); + ul.appendChild(li); + currentH2Li = li; + } else if (item.level === 'h3' && currentH2Li) { + // Create h3 item under current h2 + let subUl = currentH2Li.querySelector('ul'); + if (!subUl) { + subUl = document.createElement('ul'); + currentH2Li.appendChild(subUl); + } + + const li = document.createElement('li'); + const a = document.createElement('a'); + a.href = `#${item.id}`; + a.className = 'side-nav-h3'; + a.textContent = item.text; + a.addEventListener('click', (e) => this.handleNavClick(e, item.id)); + + li.appendChild(a); + subUl.appendChild(li); + } + }); + } + + handleNavClick(e, targetId) { + e.preventDefault(); + + // Remove active class from all links + this.querySelectorAll('a').forEach(link => { + link.classList.remove('active'); + }); + + // Add active class to clicked link + e.target.classList.add('active'); + + // Smooth scroll to target + const targetElement = document.getElementById(targetId); + if (targetElement) { + targetElement.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); + } + } + + setupScrollListener() { + let ticking = false; + + const handleScroll = () => { + if (!ticking) { + requestAnimationFrame(() => { + this.highlightActiveSection(); + ticking = false; + }); + ticking = true; + } + }; + + window.addEventListener('scroll', handleScroll); + } + + highlightActiveSection() { + const scrollTop = window.pageYOffset || document.documentElement.scrollTop; + const offset = 100; // Offset for highlighting + + let activeId = ''; + + // Find the currently visible section + this.navItems.forEach(item => { + const element = item.element; + const rect = element.getBoundingClientRect(); + const elementTop = rect.top + scrollTop; + + if (elementTop <= scrollTop + offset) { + activeId = item.id; + } + }); + + // Update active state + this.querySelectorAll('a').forEach(link => { + link.classList.remove('active'); + }); + + if (activeId) { + const activeLink = this.querySelector(`a[href="#${activeId}"]`); + if (activeLink) { + activeLink.classList.add('active'); + } + } + } + + render() { + this.innerHTML = ` +
+

+ +
+ `; + } + + // Method to refresh the sidebar when content changes + refresh() { + this.scanHeaders(); + } + + // Method to set the sidebar title + setTitle(title) { + const titleElement = this.querySelector('.side-nav-title'); + if (titleElement) { + titleElement.textContent = title; + } + } +} + +// Register the custom element +customElements.define('app-sidebar', Sidebar); + +export default Sidebar; \ No newline at end of file diff --git a/_docs/pages/advanced/CAP.html b/_docs/pages/advanced/CAP.html new file mode 100644 index 0000000..1468fb9 --- /dev/null +++ b/_docs/pages/advanced/CAP.html @@ -0,0 +1,43 @@ + + + + + + + Spearhead Persistence + + + + + + + +
+ +
+
+
+ + +
+

Advanced Tutorial: CAP

+

+ You're a little early!
+ We're still working on this tutorial, but it will be available soon.
+

+
+
+ +
+ + + + +``` \ No newline at end of file diff --git a/classes/capClasses/CapAirbase.lua b/classes/capClasses/CapAirbase.lua index 68bae5b..62da3fe 100644 --- a/classes/capClasses/CapAirbase.lua +++ b/classes/capClasses/CapAirbase.lua @@ -306,6 +306,8 @@ function CapBase:CheckAndScheduleIntercept() local interceptZoneIDs = {} + local interceptZoneIDs = {} + local airbase = Airbase.getByName(self.airbaseName) if not airbase then return nil