Files
lit.ruv.wtf/website/index.html
Max Litruv Boonzaayer 35b049b833 Add static blog generator and initial blog posts
- Implement StaticBlogGenerator class for generating static HTML blog pages from markdown data.
- Create initial blog index page (blog.html) with links to posts.
- Add individual blog post pages for "Markdown Formatting Test", "Building Interactive Node Graphs", "Welcome to My Blog", "test d d d d", and "testddd".
- Include markdown rendering capabilities for formatting content in blog posts.
2026-05-10 19:46:31 +10:00

347 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Lit.ruv.wtf - Interactive Node Graph</title>
<meta name="description" content="Personal site of Lit.ruv.wtf. Graph editor edition">
<!-- Favicons -->
<link rel="icon" type="image/png" sizes="16x16" href="logos/16px.png">
<link rel="icon" type="image/png" sizes="32x32" href="logos/32px.png">
<link rel="icon" type="image/png" sizes="48x48" href="logos/48px.png">
<link rel="icon" type="image/png" sizes="64x64" href="logos/64px.png">
<link rel="icon" type="image/png" sizes="128x128" href="logos/128px.png">
<link rel="icon" type="image/png" sizes="256x256" href="logos/256px.png">
<link rel="apple-touch-icon" sizes="180x180" href="logos/256px.png">
<!-- Open Graph / Social Media -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://lit.ruv.wtf/">
<meta property="og:title" content="Lit.ruv.wtf - Interactive Node Graph">
<meta property="og:description" content="Personal site of Lit.ruv.wtf. Graph editor edition">
<meta property="og:image" content="https://lit.ruv.wtf/banner.webp">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:url" content="https://lit.ruv.wtf/">
<meta name="twitter:title" content="Lit.ruv.wtf - Interactive Node Graph">
<meta name="twitter:description" content="Personal site of Lit.ruv.wtf. Graph editor edition">
<meta name="twitter:image" content="https://lit.ruv.wtf/banner.webp">
<!-- Preconnect to external domains -->
<link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
<link rel="preconnect" href="https://unpkg.com" crossorigin>
<link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
<link rel="dns-prefetch" href="https://unpkg.com">
<link rel="stylesheet" href="styles/main.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-tomorrow.min.css">
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/prism.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-javascript.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-python.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-typescript.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-jsx.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-css.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-json.min.js"></script>
<script defer src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-bash.min.js"></script>
<script defer src="https://unpkg.com/@lottiefiles/lottie-player@latest/dist/lottie-player.js"></script>
</head>
<body>
<div id="workspaceCanvas" class="workspace-canvas">
<nav class="quick-links">
<a href="/blog.html" class="quick-link">blog</a>
<a href="/docs/" class="quick-link">docs</a>
<a href="https://github.com/litruv" target="_blank" rel="noopener" class="quick-link">github</a>
<a href="https://bsky.app/profile/lit.mates.dev" target="_blank" rel="noopener" class="quick-link">bluesky</a>
<a href="/materials" class="quick-link">materials</a>
</nav>
<svg id="connectionLayer" class="connection-layer"></svg>
<div id="worldLayer" class="world-layer">
<div id="nodeLayer" class="node-layer"></div>
</div>
<div class="hud">
<button id="resetViewBtn" class="hud-btn" title="Reset View">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
<polyline points="9 22 9 12 15 12 15 22"></polyline>
</svg>
</button>
<button id="draggableToggle" class="hud-btn-drag" title="Toggle Dragging">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 19l7-7 3 3-7 7-3-3z"></path>
<path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"></path>
<path d="M2 2l7.586 7.586"></path>
<circle cx="11" cy="11" r="2"></circle>
</svg>
<div class="hud-tooltip">
alt+click - disconnect pin
</div>
</button>
</div>
<div id="debugPanel" class="debug-panel collapsed">
<div class="debug-header">
<div class="debug-title">Debug</div>
<button class="debug-toggle-btn" title="Toggle debug panel" aria-label="Toggle debug panel">
<svg class="debug-eye-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path class="eye-visible" d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
<circle class="eye-visible" cx="12" cy="12" r="3"></circle>
<path class="eye-hidden" d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" style="display: none;"></path>
<line class="eye-hidden" x1="1" y1="1" x2="23" y2="23" style="display: none;"></line>
</svg>
</button>
</div>
<div class="debug-row">
<span class="debug-label">Zoom</span>
<span class="debug-value debug-zoom">1.000</span>
</div>
<div class="debug-row">
<span class="debug-label">DPR</span>
<span class="debug-value debug-dpr">1.0</span>
</div>
<div class="debug-row">
<span class="debug-label">Viewport</span>
<span class="debug-value debug-viewport">0 × 0</span>
</div>
<div class="debug-row">
<span class="debug-label">Center</span>
<span class="debug-value debug-center">0.0, 0.0</span>
</div>
<div class="debug-row">
<span class="debug-label">Viewbox</span>
<span class="debug-value debug-viewbox"></span>
</div>
<div class="debug-row">
<span class="debug-label">NodeAnchor</span>
<span class="debug-value debug-anchor"></span>
</div>
<div class="debug-divider"></div>
<label class="debug-row debug-check-row">
<span class="debug-label">Draggable</span>
<input class="debug-draggable-cb" type="checkbox" />
</label>
<label class="debug-row debug-check-row">
<span class="debug-label">WorldBoxes</span>
<input class="debug-worldbox-cb" type="checkbox" />
</label>
<label class="debug-row debug-check-row">
<span class="debug-label">Viewbox</span>
<input class="debug-viewbox-cb" type="checkbox" />
</label>
<div class="debug-divider"></div>
<button class="debug-copy-json-btn" title="Copy current graph as JSON">Copy JSON</button>
<button class="debug-show-properties-btn" title="Open properties panel">Show Properties</button>
<div class="debug-row debug-active-row" hidden>
<span class="debug-label debug-active-label"></span>
<span class="debug-value debug-active-pos">0.0, 0.0</span>
<button class="debug-copy-btn" title="Copy graph.json">Copy graph</button>
</div>
<div class="debug-divider" id="debugNodeEditorDivider" hidden></div>
<div id="debugNodeEditor" class="debug-node-editor" hidden>
<div class="debug-subtitle">Node Editor</div>
<div class="debug-row">
<span class="debug-label">ID</span>
<input class="debug-input debug-node-id" type="text" readonly />
</div>
<div class="debug-row">
<span class="debug-label">Type</span>
<input class="debug-input debug-node-type" type="text" readonly />
</div>
<div class="debug-row">
<span class="debug-label">Title</span>
<input class="debug-input debug-node-title" type="text" />
</div>
<div class="debug-row">
<span class="debug-label">X</span>
<input class="debug-input debug-node-x" type="number" step="1" />
</div>
<div class="debug-row">
<span class="debug-label">Y</span>
<input class="debug-input debug-node-y" type="number" step="1" />
</div>
<div class="debug-row">
<span class="debug-label">Width</span>
<input class="debug-input debug-node-width" type="number" step="1" />
</div>
<div class="debug-subtitle">Inputs</div>
<div id="debugInputsList" class="debug-pins-list"></div>
<button class="debug-add-btn debug-add-input-btn">+ Add Input</button>
<div class="debug-subtitle">Outputs</div>
<div id="debugOutputsList" class="debug-pins-list"></div>
<button class="debug-add-btn debug-add-output-btn">+ Add Output</button>
</div>
</div>
</div>
<!-- Properties Editor Panel (Right Side) -->
<div id="propertiesPanel" class="properties-panel collapsed">
<button class="properties-panel-tab" title="Open properties panel" aria-label="Open properties panel">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="7" height="7"></rect>
<rect x="14" y="3" width="7" height="7"></rect>
<rect x="14" y="14" width="7" height="7"></rect>
<rect x="3" y="14" width="7" height="7"></rect>
</svg>
</button>
<div class="properties-header">
<h2 class="properties-title">Properties</h2>
<button class="properties-toggle-btn" title="Close properties panel" aria-label="Close properties panel">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<polyline points="15 18 9 12 15 6"></polyline>
</svg>
</button>
</div>
<div class="properties-content">
<!-- Node Properties Section -->
<div id="nodePropertiesSection" class="properties-section" style="display: none;">
<div class="section-header">
<h3>Node</h3>
</div>
<div class="section-content">
<div class="prop-row">
<label class="prop-label">ID</label>
<input type="text" class="prop-input" id="propNodeId" readonly />
</div>
<div class="prop-row">
<label class="prop-label">Type</label>
<input type="text" class="prop-input" id="propNodeType" readonly />
</div>
<div class="prop-row">
<label class="prop-label">Title</label>
<input type="text" class="prop-input" id="propNodeTitle" />
</div>
<div class="prop-row">
<label class="prop-label">Position X</label>
<input type="number" class="prop-input" id="propNodeX" step="20" />
</div>
<div class="prop-row">
<label class="prop-label">Position Y</label>
<input type="number" class="prop-input" id="propNodeY" step="20" />
</div>
<div class="prop-row">
<label class="prop-label">Width</label>
<input type="number" class="prop-input" id="propNodeWidth" placeholder="Auto" />
</div>
</div>
</div>
<!-- Focus Options Section -->
<div id="focusOptionsSection" class="properties-section" style="display: none;">
<div class="section-header collapsible">
<h3>Focus Options</h3>
<button class="section-toggle"></button>
</div>
<div class="section-content">
<div class="prop-row">
<label class="prop-label">Duration (ms)</label>
<input type="number" class="prop-input" id="propFocusDuration" placeholder="550" />
</div>
<div class="prop-row">
<label class="prop-label">Anchor X</label>
<input type="number" class="prop-input" id="propFocusAnchorX" step="0.1" min="0" max="1" placeholder="0.5" />
</div>
<div class="prop-row">
<label class="prop-label">Anchor Y</label>
<input type="number" class="prop-input" id="propFocusAnchorY" step="0.1" min="0" max="1" placeholder="0.5" />
</div>
<div class="prop-divider"></div>
<h4 class="prop-subtitle">Default WorldBox</h4>
<div class="prop-row">
<label class="prop-label">Width</label>
<input type="number" class="prop-input" id="propWorldBoxWidth" placeholder="Auto" />
</div>
<div class="prop-row">
<label class="prop-label">Height</label>
<input type="number" class="prop-input" id="propWorldBoxHeight" placeholder="Auto" />
</div>
<div class="prop-divider"></div>
<h4 class="prop-subtitle">Responsive Breakpoints</h4>
<div id="breakpointsList" class="breakpoints-list"></div>
<button class="prop-btn-add" id="addBreakpointBtn">+ Add Breakpoint</button>
</div>
</div>
<!-- Graph Settings Section -->
<div id="graphSettingsSection" class="properties-section">
<div class="section-header collapsible">
<h3>Graph Settings</h3>
<button class="section-toggle"></button>
</div>
<div class="section-content">
<div class="prop-row">
<label class="prop-label">Draggable</label>
<input type="checkbox" class="prop-checkbox" id="propGraphDraggable" />
</div>
<div class="prop-row">
<label class="prop-label">Intro Duration (ms)</label>
<input type="number" class="prop-input" id="propIntroDuration" placeholder="700" />
</div>
<div class="prop-divider"></div>
<h4 class="prop-subtitle">Initial Viewport</h4>
<div class="prop-row">
<label class="prop-label">X</label>
<input type="number" class="prop-input" id="propInitViewX" />
</div>
<div class="prop-row">
<label class="prop-label">Y</label>
<input type="number" class="prop-input" id="propInitViewY" />
</div>
<div class="prop-row">
<label class="prop-label">Width</label>
<input type="number" class="prop-input" id="propInitViewWidth" />
</div>
<div class="prop-row">
<label class="prop-label">Height</label>
<input type="number" class="prop-input" id="propInitViewHeight" />
</div>
<div class="prop-divider"></div>
<button class="prop-btn-primary" id="applySettingsBtn">Apply Settings</button>
</div>
</div>
<!-- No Selection Message -->
<div id="noSelectionMessage" class="no-selection">
<p>Select a node to edit its properties</p>
</div>
</div>
</div>
<template id="nodeTemplate">
<article class="blueprint-node" draggable="false">
<header class="node-header">
<div class="node-title"></div>
</header>
<section class="node-io node-inputs"></section>
<section class="node-io node-outputs"></section>
</article>
</template>
<template id="pinTemplate">
<div class="pin" draggable="false">
<span class="pin-label"></span>
<span class="pin-handle" tabindex="-1"></span>
</div>
</template>
<!-- WorldBox Overlay Layer -->
<svg id="worldBoxLayer" class="worldbox-layer" style="display: none;"></svg>
<!-- Viewbox Overlay Layer -->
<svg id="viewboxLayer" class="viewbox-layer" style="display: none;"></svg>
<!-- JSON Editor Modal -->
<script type="module" src="scripts/main.js"></script>
</body>
</html>