Feature/scenery targets (#60)
* Added Scenery targets * Documentation updates
This commit is contained in:
@@ -1,2 +1,5 @@
|
||||
import * as header from "./components/header.js";
|
||||
import * as sidebar from "./components/sidebar.js";
|
||||
import './components/code-block.js';
|
||||
import './components/code-inline.js';
|
||||
import './components/note.js';
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
class CodeBlock extends HTMLElement {
|
||||
connectedCallback() {
|
||||
// Get the code content as text, preserving whitespace
|
||||
let code = this.textContent.replace(/\r\n?/g, "\n");
|
||||
// Remove leading/trailing blank lines
|
||||
code = code.replace(/^\s*\n/, '').replace(/\n\s*$/, '');
|
||||
// Find leading spaces from the first non-empty line
|
||||
const lines = code.split("\n");
|
||||
const firstLine = lines.find(line => line.trim().length > 0) || '';
|
||||
const leadingSpaces = firstLine.match(/^\s*/)[0].length;
|
||||
// Remove that many leading spaces from all lines
|
||||
const stripped = lines.map(line => line.slice(leadingSpaces)).join("\n");
|
||||
// Escape HTML special characters
|
||||
const escaped = stripped
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
const lang = this.getAttribute('lang') || '';
|
||||
const langClass = lang ? `language-${lang}` : '';
|
||||
this.innerHTML = `<pre class=\"custom-code-block\"><code class=\"${langClass}\">${escaped}</code></pre>`;
|
||||
// If Prism or highlight.js is present, trigger highlighting
|
||||
if (window.Prism && Prism.highlightElement) {
|
||||
Prism.highlightElement(this.querySelector('code'));
|
||||
} else if (window.hljs && hljs.highlightElement) {
|
||||
hljs.highlightElement(this.querySelector('code'));
|
||||
}
|
||||
}
|
||||
}
|
||||
customElements.define('code-block', CodeBlock);
|
||||
@@ -0,0 +1,32 @@
|
||||
class CodeInline extends HTMLElement {
|
||||
connectedCallback() {
|
||||
// Get the code content as text
|
||||
let code = this.textContent;
|
||||
|
||||
// Escape HTML special characters
|
||||
code = code
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
|
||||
// Highlight variables: $variable, {variable}, or %variable%
|
||||
code = code.replace(/(\$[a-zA-Z_][\w]*)|(\{[^\}]+\})|(%[^%]+%)/g, match =>
|
||||
`<span class="inline-var">${match}</span>`
|
||||
);
|
||||
|
||||
// Get language attribute for potential syntax highlighting
|
||||
const lang = this.getAttribute('lang') || '';
|
||||
const langClass = lang ? `language-${lang}` : '';
|
||||
|
||||
this.innerHTML = `<code class="custom-inline-code ${langClass}">${code}</code>`;
|
||||
|
||||
// If Prism or highlight.js is present, trigger highlighting
|
||||
if (window.Prism && Prism.highlightElement) {
|
||||
Prism.highlightElement(this.querySelector('code'));
|
||||
} else if (window.hljs && hljs.highlightElement) {
|
||||
hljs.highlightElement(this.querySelector('code'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('code-inline', CodeInline);
|
||||
@@ -9,6 +9,7 @@ class Header extends HTMLElement {
|
||||
this.innerHTML = `
|
||||
<div class="header-box">
|
||||
<a class="logo" href="/index.html">Spearhead</a>
|
||||
<span class="subTitle">mission making, made easy</span>
|
||||
<div class="header-right">
|
||||
<nav>
|
||||
<a href="/index.html">Home</a>
|
||||
@@ -18,6 +19,7 @@ class Header extends HTMLElement {
|
||||
<div class="dropdown-content">
|
||||
<a href="/pages/tutorials.html">Quick Starts</a>
|
||||
<a href="/pages/advanced/CAP.html">Advanced: CAP</a>
|
||||
<a href="/pages/advanced/missions.html">Advanced: Missions</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,6 +27,7 @@ class Header extends HTMLElement {
|
||||
<a href="/pages/persistence.html">Persistence</a>
|
||||
<a href="/pages/reference.html">Reference</a>
|
||||
<a href="/pages/spearheadapi.html">API</a>
|
||||
<a href="/pages/about_us.html">About Us</a>
|
||||
</nav>
|
||||
<button id="theme-toggle" class="theme-toggle" title="Toggle light/dark theme">
|
||||
<svg id="moon-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
class Note extends HTMLElement {
|
||||
connectedCallback() {
|
||||
// Get the note content
|
||||
const content = this.innerHTML;
|
||||
|
||||
// Get optional type attribute for different note styles
|
||||
const type = this.getAttribute('type') || 'default';
|
||||
|
||||
// Get optional title attribute
|
||||
const title = this.getAttribute('title');
|
||||
|
||||
// Build the note HTML
|
||||
let noteHTML = '<div class="note';
|
||||
|
||||
// Add type-specific class if provided
|
||||
if (type !== 'default') {
|
||||
noteHTML += ` note-${type}`;
|
||||
}
|
||||
|
||||
noteHTML += '">';
|
||||
|
||||
// Add title if provided
|
||||
if (title) {
|
||||
noteHTML += `<h4 class="note-title">${title}</h4>`;
|
||||
}
|
||||
|
||||
// Add the content
|
||||
noteHTML += content;
|
||||
noteHTML += '</div>';
|
||||
|
||||
this.innerHTML = noteHTML;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('note-box', Note);
|
||||
@@ -15,11 +15,11 @@ class Sidebar extends HTMLElement {
|
||||
// Clear existing nav items
|
||||
this.navItems = [];
|
||||
|
||||
// Find all h2 and h3 elements with IDs in the content area
|
||||
// Find all h2, h3, and h4 elements with IDs in the content area
|
||||
const contentWrapper = document.querySelector('.content-wrapper');
|
||||
if (!contentWrapper) return;
|
||||
|
||||
const headers = contentWrapper.querySelectorAll('h2[id], h3[id]');
|
||||
const headers = contentWrapper.querySelectorAll('h2[id], h3[id], h4[id]');
|
||||
|
||||
headers.forEach(header => {
|
||||
const id = header.getAttribute('id');
|
||||
@@ -45,6 +45,7 @@ class Sidebar extends HTMLElement {
|
||||
ul.innerHTML = '';
|
||||
|
||||
let currentH2Li = null;
|
||||
let currentH3Li = null;
|
||||
|
||||
this.navItems.forEach(item => {
|
||||
if (item.level === 'h2') {
|
||||
@@ -59,6 +60,7 @@ class Sidebar extends HTMLElement {
|
||||
li.appendChild(a);
|
||||
ul.appendChild(li);
|
||||
currentH2Li = li;
|
||||
currentH3Li = null;
|
||||
} else if (item.level === 'h3' && currentH2Li) {
|
||||
// Create h3 item under current h2
|
||||
let subUl = currentH2Li.querySelector('ul');
|
||||
@@ -74,6 +76,24 @@ class Sidebar extends HTMLElement {
|
||||
a.textContent = item.text;
|
||||
a.addEventListener('click', (e) => this.handleNavClick(e, item.id));
|
||||
|
||||
li.appendChild(a);
|
||||
subUl.appendChild(li);
|
||||
currentH3Li = li;
|
||||
} else if (item.level === 'h4' && currentH3Li) {
|
||||
// Create h4 item under current h3
|
||||
let subUl = currentH3Li.querySelector('ul');
|
||||
if (!subUl) {
|
||||
subUl = document.createElement('ul');
|
||||
currentH3Li.appendChild(subUl);
|
||||
}
|
||||
|
||||
const li = document.createElement('li');
|
||||
const a = document.createElement('a');
|
||||
a.href = `#${item.id}`;
|
||||
a.className = 'side-nav-h4';
|
||||
a.textContent = item.text;
|
||||
a.addEventListener('click', (e) => this.handleNavClick(e, item.id));
|
||||
|
||||
li.appendChild(a);
|
||||
subUl.appendChild(li);
|
||||
}
|
||||
@@ -139,7 +159,7 @@ class Sidebar extends HTMLElement {
|
||||
link.classList.remove('active');
|
||||
});
|
||||
|
||||
if (activeId) {
|
||||
if (activeId !== nil && activeId !== '') {
|
||||
const activeLink = this.querySelector(`a[href="#${activeId}"]`);
|
||||
if (activeLink) {
|
||||
activeLink.classList.add('active');
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,3 +1,4 @@
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const themeToggle = document.getElementById('theme-toggle');
|
||||
const sunIcon = document.getElementById('sun-icon');
|
||||
|
||||
Reference in New Issue
Block a user