5 Commits
Author SHA1 Message Date
dextatc 11db330a38 foundation 102 2026-07-12 21:17:31 +02:00
dextatc 9fe9a48a55 i am your ma.... next best leader 2026-07-12 21:16:56 +02:00
dextatc f2b87c8b42 builder builder on the wall 2026-07-12 21:14:58 +02:00
dextatc cb7eab974e fill the fjords 2026-07-12 20:40:23 +02:00
dextatc e93ec9a3c2 build script output 2026-07-12 20:39:41 +02:00
7 changed files with 1018 additions and 23 deletions
+1
View File
@@ -1 +1,2 @@
66_plasmaTr
export/
+694
View File
@@ -0,0 +1,694 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Debian 13 Bootstrap Configurator</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- React & ReactDOM -->
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<!-- Babel for JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body class="antialiased h-screen flex flex-col font-mono text-sm overflow-hidden">
<div id="root" class="flex-1 flex flex-col h-full"></div>
<script type="text/babel">
const { useState, useEffect } = React;
// ==============================================================================
// 1. UI & THEME CONFIGURATION (Texte, Farben, Bilder)
// ==============================================================================
const uiConfigJSON = {
text: {
appTitle: "Debian 13 // JSON Configurator",
logoLetter: "D",
navTitle: "Nav-Gruppe: Checkliste",
pipelineTitle: "Pipeline: Script Output",
btnCopyDefault: "[ SICHTBARE MODULE KOPIEREN ]",
btnCopySuccess: "[ KOMPLETTES SKRIPT KOPIERT ]",
emptyStateTitle: "[ KEINE AKTIVEN/SICHTBAREN MODULE ]",
emptyStateSub: "Bitte wähle links Einträge aus oder klappe die Navigation auf.",
logMessage: ">> LOG: Generiere {{count}} sichtbare Pipeline-Schritte..."
},
theme: {
accent: "#10b981", // Haupt-Akzent (Emerald Green)
accentHover: "#34d399",
accentDark: "#064e3b",
bgApp: "#05080f", // Tiefster Hintergrund
bgPanelDark: "#0f172a", // Dunkler Kasten-Hintergrund
bgPanelLight: "#1e293b", // Heller Kasten-Hintergrund
textMain: "#f8fafc", // Helle Schrift
textMuted: "#94a3b8", // Abgedunkelte Schrift
wmBorderLight: "#94a3b8", // Wmaker 3D Rand (Hell)
wmBorderDark: "#0f172a", // Wmaker 3D Rand (Dunkel)
wmBorderMedium: "#64748b" // Wmaker Rahmenfarbe
},
images: {
// Ein cyber-artiges Terminal-Bild für den Header (Unsplash)
headerBg: "https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?q=80&w=1200&auto=format&fit=crop"
}
};
// ==============================================================================
// 2. MASTER SETUP CONFIGURATION (Inhalte, Pakete, Befehle)
// ==============================================================================
const setupConfigJSON = [
{
id: "basis",
title: "Basis & System",
items: [
{
id: "baseUpdate", type: "checkbox", label: "apt update & upgrade", defaultChecked: true,
commands: [ { text: "Paketquellen aktualisieren und System upgraden", code: "apt update && apt upgrade -y" } ]
},
{
id: "baseDeps", type: "checkbox", label: "Curl, Wget, Git, GnuPG", defaultChecked: true,
commands: [
{ text: "Curl, Git, GnuPG und Zertifikate installieren", code: "apt install -y curl wget git build-essential apt-transport-https ca-certificates gnupg software-properties-common" },
{ text: "Apt Keyring-Verzeichnis sicher anlegen", code: "install -m 0755 -d /etc/apt/keyrings" }
]
}
]
},
{
id: "terminal",
title: "Terminal & UI",
items: [
{
id: "keyboardUsIntl", type: "checkbox", label: "US Tastatur mit Umlauten", defaultChecked: true,
commands: [
{ text: "Konfiguration schreiben", code: "cat << 'EOF' > /etc/default/keyboard\nXKBMODEL=\"pc105\"\nXKBLAYOUT=\"us\"\nXKBVARIANT=\"altgr-intl\"\nXKBOPTIONS=\"\"\nBACKSPACE=\"guess\"\nEOF" },
{ text: "System-Dienste neu laden", code: "dpkg-reconfigure -f noninteractive keyboard-configuration\nsetupcon || true" }
]
},
{
id: "promptColor", type: "select", label: "Bash Prompt (PS1)", defaultSelect: "green",
options: [
{ value: "none", label: "STANDARD" },
{ value: "green", label: "GRÜN (HACKER STYLE)", meta: "\\[\\033[01;32m\\]" },
{ value: "blue", label: "BLAU (CLEAN)", meta: "\\[\\033[01;34m\\]" },
{ value: "cyan", label: "CYAN (MODERN)", meta: "\\[\\033[01;36m\\]" },
{ value: "red", label: "ROT (WARNING/ROOT)", meta: "\\[\\033[01;31m\\]" }
],
commandTemplate: [
{ text: "PS1 Variable in ~/.bashrc anhängen", code: "TARGET_USER=\"${SUDO_USER:-$USER}\"\nUSER_HOME=$(getent passwd \"$TARGET_USER\" | cut -d: -f6)\nif ! grep -q \"# BOOTSTRAP_PS1\" \"$USER_HOME/.bashrc\"; then\n echo -e \"\\n# BOOTSTRAP_PS1\\nPS1='{{meta}}\\u@\\h\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\\\$ '\" >> \"$USER_HOME/.bashrc\"\nfi" }
]
}
]
},
{
id: "dev",
title: "Sprachen & Editoren",
items: [
{
id: "neovim", type: "checkbox_with_select", label: "Neovim", defaultChecked: false, selectId: "neovimSrc", selectLabel: "QUELLE:", selectDefault: "apt",
options: [ { value: "apt", label: "Debian Repo (Stable)" }, { value: "web", label: "Website (Latest)" } ],
commandsByValue: {
"apt": [ { text: "Installation von: neovim", code: "apt install -y neovim" } ],
"web": [
{ text: "Archiv laden & entpacken", code: "curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz\nrm -rf /opt/nvim\ntar -C /opt -xzf nvim-linux64.tar.gz" },
{ text: "Globale Symlinks setzen", code: "ln -sf /opt/nvim-linux64/bin/nvim /usr/local/bin/nvim\nrm nvim-linux64.tar.gz" }
]
}
},
{
id: "golang", type: "checkbox_with_select", label: "Golang", defaultChecked: false, selectId: "golangSrc", selectLabel: "QUELLE:", selectDefault: "apt",
options: [ { value: "apt", label: "Debian Repo (Stable)" }, { value: "web", label: "Website (Latest)" } ],
commandsByValue: {
"apt": [ { text: "Installation von: golang", code: "apt install -y golang" } ],
"web": [
{ text: "Neueste Version ermitteln", code: "GO_LATEST=$(curl -sL https://go.dev/VERSION?m=text | head -n 1)\necho \"Lade ${GO_LATEST} herunter...\"" },
{ text: "Archiv laden & nach /usr/local entpacken", code: "curl -LO \"https://go.dev/dl/${GO_LATEST}.linux-amd64.tar.gz\"\nrm -rf /usr/local/go\ntar -C /usr/local -xzf \"${GO_LATEST}.linux-amd64.tar.gz\"" },
{ text: "Globale Symlinks setzen", code: "ln -sf /usr/local/go/bin/go /usr/local/bin/go\nln -sf /usr/local/go/bin/gofmt /usr/local/bin/gofmt\nrm \"${GO_LATEST}.linux-amd64.tar.gz\"" }
]
}
},
{
id: "elixir", type: "checkbox_with_select", label: "Elixir & Erlang", defaultChecked: false, selectId: "elixirSrc", selectLabel: "QUELLE:", selectDefault: "apt",
options: [ { value: "apt", label: "Debian Repo (Stable)" }, { value: "web", label: "Website (Latest)" } ],
commandsByValue: {
"apt": [ { text: "Installation von: elixir erlang", code: "apt install -y elixir erlang" } ],
"web": [
{ text: "Erlang & Build-Tools vorbereiten", code: "apt install -y erlang make git" },
{ text: "Elixir Quellcode klonen & kompilieren", code: "rm -rf /usr/local/src/elixir\ngit clone https://github.com/elixir-lang/elixir.git /usr/local/src/elixir\ncd /usr/local/src/elixir\nmake install clean" },
{ text: "Globale Symlinks setzen", code: "ln -sf /usr/local/src/elixir/bin/elixir /usr/local/bin/elixir\nln -sf /usr/local/src/elixir/bin/elixirc /usr/local/bin/elixirc\nln -sf /usr/local/src/elixir/bin/iex /usr/local/bin/iex\nln -sf /usr/local/src/elixir/bin/mix /usr/local/bin/mix\ncd -" }
]
}
}
]
},
{
id: "thirdparty",
title: "Externe Quellen (GPG/Curl)",
items: [
{
id: "docker", type: "checkbox", label: "Docker (CE, CLI, Compose)", defaultChecked: false,
commands: [
{ text: "Docker GPG-Schlüssel speichern", code: "curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg\nchmod a+r /etc/apt/keyrings/docker.gpg" },
{ text: "Apt-Repository eintragen", code: "echo \"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable\" | tee /etc/apt/sources.list.d/docker.list > /dev/null" },
{ text: "Docker installieren", code: "apt update\napt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin" },
{ text: "User in Docker-Gruppe aufnehmen", code: "TARGET_USER=\"${SUDO_USER:-$USER}\"\nusermod -aG docker \"$TARGET_USER\"" }
]
},
{
id: "nodejs", type: "checkbox_with_select", label: "Node.js", defaultChecked: false, selectId: "nodeVersion", selectLabel: "VER:", selectDefault: "20.x",
options: [ { value: "22.x", label: "22.x (Current)" }, { value: "20.x", label: "20.x (LTS)" }, { value: "18.x", label: "18.x (Legacy)" } ],
commandTemplate: [
{ text: "NodeSource GPG-Schlüssel importieren", code: "curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg" },
{ text: "Repository-Eintrag erstellen", code: "echo \"deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_{{selectValue}} nodistro main\" | tee /etc/apt/sources.list.d/nodesource.list > /dev/null" },
{ text: "Node.js installieren", code: "apt update\napt install -y nodejs" }
]
},
{
id: "syncthing", type: "checkbox", label: "Syncthing", defaultChecked: false,
commands: [
{ text: "Syncthing Release Key importieren", code: "curl -fsSL https://syncthing.net/release-key.txt | gpg --dearmor -o /etc/apt/keyrings/syncthing-archive-keyring.gpg" },
{ text: "Repository hinzufügen", code: "echo \"deb [signed-by=/etc/apt/keyrings/syncthing-archive-keyring.gpg] https://apt.syncthing.net/ syncthing stable\" | tee /etc/apt/sources.list.d/syncthing.list > /dev/null" },
{ text: "Syncthing installieren", code: "apt update\napt install -y syncthing" }
]
}
]
}
];
// ==============================================================================
// --- Dynamsiche CSS Injection basierend auf uiConfigJSON ---
const DynamicStyles = () => (
<style>{`
:root {
--c-accent: ${uiConfigJSON.theme.accent};
--c-accent-hover: ${uiConfigJSON.theme.accentHover};
--c-accent-dark: ${uiConfigJSON.theme.accentDark};
--c-bg-app: ${uiConfigJSON.theme.bgApp};
--c-bg-panel-dark: ${uiConfigJSON.theme.bgPanelDark};
--c-bg-panel-light: ${uiConfigJSON.theme.bgPanelLight};
--c-text-main: ${uiConfigJSON.theme.textMain};
--c-text-muted: ${uiConfigJSON.theme.textMuted};
--wm-light: ${uiConfigJSON.theme.wmBorderLight};
--wm-dark: ${uiConfigJSON.theme.wmBorderDark};
--wm-med: ${uiConfigJSON.theme.wmBorderMedium};
}
body { background-color: var(--c-bg-panel-dark); color: var(--c-text-main); }
.custom-scrollbar::-webkit-scrollbar { width: 12px; }
.custom-scrollbar::-webkit-scrollbar-track { background: var(--c-bg-panel-dark); border-left: 2px solid var(--c-bg-panel-light); }
.custom-scrollbar::-webkit-scrollbar-thumb { background: var(--wm-med); border: 2px solid; border-top-color: var(--wm-light); border-left-color: var(--wm-light); border-bottom-color: var(--wm-dark); border-right-color: var(--wm-dark); }
.custom-scrollbar::-webkit-scrollbar-thumb:hover { background: var(--c-text-muted); }
/* Wmaker Components */
.wm-btn {
background-color: var(--wm-med);
color: var(--c-text-main);
border: 2px solid;
border-top-color: var(--wm-light);
border-left-color: var(--wm-light);
border-bottom-color: var(--wm-dark);
border-right-color: var(--wm-dark);
text-transform: uppercase;
font-weight: bold;
padding: 4px 12px;
cursor: pointer;
}
.wm-btn:active, .wm-btn-active-state {
border-top-color: var(--wm-dark);
border-left-color: var(--wm-dark);
border-bottom-color: var(--wm-light);
border-right-color: var(--wm-light);
background-color: var(--c-bg-panel-light);
}
.wm-btn-success {
background-color: var(--c-accent-dark);
border-top-color: var(--c-accent-hover);
border-left-color: var(--c-accent-hover);
border-bottom-color: var(--wm-dark);
border-right-color: var(--wm-dark);
}
.wm-btn-success:active {
border-top-color: var(--wm-dark);
border-left-color: var(--wm-dark);
border-bottom-color: var(--c-accent-hover);
border-right-color: var(--c-accent-hover);
}
.wm-block {
border: 2px solid var(--wm-med);
background-color: var(--c-bg-panel-light);
box-shadow: 4px 4px 0px rgba(0,0,0,0.8);
}
.wm-titlebar {
background: linear-gradient(to right, var(--c-bg-panel-light), var(--c-bg-panel-dark));
border-bottom: 2px solid var(--wm-med);
}
.wm-header-bg {
background-image: linear-gradient(to right, rgba(15, 23, 42, 0.95), rgba(15, 23, 42, 0.7)), url('${uiConfigJSON.images.headerBg}');
background-size: cover;
background-position: center;
}
.wm-checkbox-inner {
border: 2px solid;
border-top-color: var(--wm-dark);
border-left-color: var(--wm-dark);
border-bottom-color: var(--wm-light);
border-right-color: var(--wm-light);
background-color: var(--c-bg-panel-light);
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
}
.wm-checkbox-inner.checked { background-color: var(--c-accent); }
.wm-input {
border: 2px solid;
border-top-color: var(--wm-dark);
border-left-color: var(--wm-dark);
border-bottom-color: var(--wm-light);
border-right-color: var(--wm-light);
background-color: var(--wm-dark);
color: var(--c-text-main);
outline: none;
}
.wm-toggle-box {
width: 16px;
height: 16px;
border: 2px solid;
border-top-color: var(--c-text-muted);
border-left-color: var(--c-text-muted);
border-bottom-color: var(--wm-dark);
border-right-color: var(--wm-dark);
background-color: var(--wm-med);
display: flex;
align-items: center;
justify-content: center;
}
.wm-toggle-box:active {
border-top-color: var(--wm-dark);
border-left-color: var(--wm-dark);
border-bottom-color: var(--c-text-muted);
border-right-color: var(--c-text-muted);
}
/* Helfer-Klassen für dynamische Farben */
.text-accent { color: var(--c-accent); }
.bg-accent { background-color: var(--c-accent); }
`}</style>
);
// --- UI Komponenten ---
const CommandItem = ({ command }) => {
const [copied, setCopied] = useState(false);
const copyCode = () => {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(command.code).then(() => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});
} else {
const textArea = document.createElement("textarea");
textArea.value = command.code;
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch (err) { }
document.body.removeChild(textArea);
}
};
return (
<div className="mb-4 last:mb-0">
<div className="flex items-center justify-between mb-1" style={{ backgroundColor: 'var(--c-bg-panel-light)', border: '1px solid var(--wm-med)', padding: '4px 8px' }}>
<p className="text-xs flex items-center gap-2" style={{ color: 'var(--c-text-muted)' }}>
<span className="w-2 h-2 bg-accent inline-block"></span>
<span dangerouslySetInnerHTML={{ __html: command.text }}></span>
</p>
<button
onClick={copyCode}
className={`wm-btn text-[10px] py-0 px-2 ml-4 ${copied ? 'wm-btn-success' : ''}`}
>
{copied ? 'KOPIERT' : 'COPY'}
</button>
</div>
<div className="p-3 overflow-x-auto custom-scrollbar" style={{ backgroundColor: 'black', border: '2px solid var(--wm-med)' }}>
<pre className="text-xs font-mono text-accent">
<code>{command.code}</code>
</pre>
</div>
</div>
);
};
const Checkbox = ({ label, checked, onChange }) => (
<label className="flex items-start space-x-3 cursor-pointer group mb-3">
<div className="mt-0.5">
<input type="checkbox" checked={checked} onChange={onChange} className="hidden" />
<div className={`wm-checkbox-inner ${checked ? 'checked' : ''}`}>
{checked && (
<svg className="w-3.5 h-3.5" style={{color: '#fff'}} fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="none" strokeLinejoin="miter" strokeWidth="3" d="M5 13l4 4L19 7" />
</svg>
)}
</div>
</div>
<div className="flex flex-col">
<span className="text-sm font-bold uppercase" style={{ color: 'var(--c-text-main)' }}>{label}</span>
</div>
</label>
);
const CollapsibleNavGroup = ({ title, sectionId, collapsed, onToggle, children }) => (
<div className="mb-4 wm-block" style={{ backgroundColor: 'var(--c-bg-panel-light)' }}>
<div
className="wm-titlebar px-3 py-2 flex items-center justify-between cursor-pointer select-none"
onClick={() => onToggle(sectionId)}
>
<h4 className="text-xs font-bold uppercase tracking-widest text-accent">{title}</h4>
<div className={`wm-toggle-box ${collapsed ? '' : 'wm-btn-active-state'}`}>
<span className="text-[10px] text-black font-bold leading-none mt-0.5">{collapsed ? '+' : '-'}</span>
</div>
</div>
{!collapsed && (
<div className="p-3" style={{ borderTop: '1px solid var(--wm-med)' }}>
{children}
</div>
)}
</div>
);
const App = () => {
const buildInitialConfig = () => {
const initConf = {};
setupConfigJSON.forEach(section => {
section.items.forEach(item => {
if (item.type === 'checkbox' || item.type === 'checkbox_with_select') {
initConf[item.id] = item.defaultChecked;
if (item.type === 'checkbox_with_select') {
initConf[item.selectId] = item.selectDefault;
}
} else if (item.type === 'select') {
initConf[item.id] = item.defaultSelect;
}
});
});
return initConf;
};
const buildInitialCollapsed = () => {
const initColl = {};
setupConfigJSON.forEach(section => { initColl[section.id] = false; });
return initColl;
};
const [config, setConfig] = useState(() => {
try {
const saved = localStorage.getItem('wmaker-config-state');
if (saved) return JSON.parse(saved);
} catch (e) {}
return buildInitialConfig();
});
const [collapsed, setCollapsed] = useState(() => {
try {
const saved = localStorage.getItem('wmaker-nav-collapsed');
if (saved) return JSON.parse(saved);
} catch (e) {}
return buildInitialCollapsed();
});
const [copiedAll, setCopiedAll] = useState(false);
useEffect(() => { localStorage.setItem('wmaker-nav-collapsed', JSON.stringify(collapsed)); }, [collapsed]);
useEffect(() => { localStorage.setItem('wmaker-config-state', JSON.stringify(config)); }, [config]);
const handleConfigToggle = (key) => setConfig(prev => ({ ...prev, [key]: !prev[key] }));
const handleConfigSelect = (key, val) => setConfig(prev => ({ ...prev, [key]: val }));
const handleCollapseToggle = (sectionId) => setCollapsed(prev => ({ ...prev, [sectionId]: !prev[sectionId] }));
// ==============================================================================
// PIPELINE ENGINE
// ==============================================================================
const getVisibleSteps = () => {
const steps = [];
setupConfigJSON.forEach(section => {
if (collapsed[section.id]) return;
section.items.forEach(item => {
let finalCommands = [];
let displayTitle = item.label;
if (item.type === 'checkbox' && config[item.id]) {
finalCommands = item.commands;
}
else if (item.type === 'select' && config[item.id] !== 'none') {
const activeOption = item.options.find(o => o.value === config[item.id]);
displayTitle = `${item.label} (${activeOption.label})`;
finalCommands = item.commandTemplate.map(c => ({
text: c.text, code: c.code.replaceAll('{{meta}}', activeOption.meta || '')
}));
}
else if (item.type === 'checkbox_with_select' && config[item.id]) {
const selVal = config[item.selectId];
const activeOption = item.options.find(o => o.value === selVal);
displayTitle = `${item.label} (${activeOption.label})`;
if (item.commandsByValue) {
finalCommands = item.commandsByValue[selVal];
} else if (item.commandTemplate) {
finalCommands = item.commandTemplate.map(c => ({
text: c.text, code: c.code.replaceAll('{{selectValue}}', selVal)
}));
}
}
if (finalCommands && finalCommands.length > 0) {
steps.push({
title: displayTitle,
commands: finalCommands
});
}
});
});
return steps;
};
const visibleSteps = getVisibleSteps();
const copyFullScript = () => {
if(visibleSteps.length === 0) return;
let text = `#!/bin/bash\n# Debian 13 Bootstrap Skript\n# Generiert durch den JSON Setup-Builder\n\n`;
text += `# ==========================================\n`;
text += `# Init & Root-Check\n`;
text += `# ==========================================\n`;
text += `set -e\n`;
text += `if [ "$EUID" -ne 0 ]; then\n echo "Bitte als root ausführen (z.B. sudo ./bootstrap.sh)"\n exit 1\nfi\n\n`;
visibleSteps.forEach(s => {
text += `# ==========================================\n`;
text += `# ${s.title}\n`;
text += `# ==========================================\n`;
s.commands.forEach(c => {
text += `# ${c.text}\n${c.code}\n\n`;
});
});
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text).then(() => showCopiedAll());
} else {
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand('copy');
showCopiedAll();
} catch (err) { }
document.body.removeChild(textArea);
}
};
const showCopiedAll = () => {
setCopiedAll(true);
setTimeout(() => setCopiedAll(false), 2000);
};
const renderNavItem = (item) => {
if (item.type === 'checkbox') {
return <Checkbox key={item.id} label={item.label} checked={config[item.id]} onChange={() => handleConfigToggle(item.id)} />;
}
else if (item.type === 'select') {
return (
<div key={item.id} className="mt-3 mb-3 ml-8 pl-3" style={{ borderLeft: '2px solid var(--wm-med)' }}>
<label className="text-[10px] font-bold block mb-1 uppercase" style={{ color: 'var(--c-text-muted)' }}>{item.label}</label>
<select
value={config[item.id]}
onChange={(e) => handleConfigSelect(item.id, e.target.value)}
className="wm-input w-full p-1"
>
{item.options.map(opt => <option key={opt.value} value={opt.value}>{opt.label}</option>)}
</select>
</div>
);
}
else if (item.type === 'checkbox_with_select') {
return (
<div key={item.id}>
<Checkbox label={item.label} checked={config[item.id]} onChange={() => handleConfigToggle(item.id)} />
{config[item.id] && (
<div className="ml-8 mt-1 mb-3 flex items-center gap-2 pl-3" style={{ borderLeft: '2px solid var(--wm-med)' }}>
<label className="text-[10px] uppercase font-bold" style={{ color: 'var(--c-text-muted)' }}>{item.selectLabel}</label>
<select
value={config[item.selectId]}
onChange={(e) => handleConfigSelect(item.selectId, e.target.value)}
className="wm-input flex-1 p-1"
>
{item.options.map(opt => <option key={opt.value} value={opt.value}>{opt.label}</option>)}
</select>
</div>
)}
</div>
);
}
return null;
};
return (
<>
<DynamicStyles />
<div className="flex flex-col h-full w-full p-4 gap-4" style={{ backgroundColor: 'var(--c-bg-app)' }}>
{/* Header mit dynamischem Image Background */}
<header className="wm-block wm-titlebar wm-header-bg p-3 flex justify-between items-center shrink-0 z-20">
<div className="flex items-center gap-4">
<div className="w-6 h-6 bg-accent flex items-center justify-center" style={{ border: '2px solid', borderTopColor: 'var(--c-accent-hover)', borderLeftColor: 'var(--c-accent-hover)', borderBottomColor: 'var(--wm-dark)', borderRightColor: 'var(--wm-dark)' }}>
<span className="text-black font-bold text-xs">{uiConfigJSON.text.logoLetter}</span>
</div>
<div>
<h1 className="text-lg font-bold tracking-wider" style={{ color: 'var(--c-text-main)', textShadow: '2px 2px 0px rgba(0,0,0,0.8)' }}>
{uiConfigJSON.text.appTitle}
</h1>
</div>
</div>
<button
onClick={copyFullScript}
className={`wm-btn ${copiedAll ? 'wm-btn-success' : ''} ${visibleSteps.length === 0 ? 'opacity-50 cursor-not-allowed' : ''}`}
disabled={visibleSteps.length === 0}
>
{copiedAll ? uiConfigJSON.text.btnCopySuccess : uiConfigJSON.text.btnCopyDefault}
</button>
</header>
{/* Main Content Area */}
<div className="flex flex-1 overflow-hidden gap-4">
{/* Sidebar: Nav-Gruppe */}
<div className="w-1/3 flex flex-col shrink-0">
<div className="wm-block flex flex-col h-full">
<div className="wm-titlebar px-3 py-2 flex items-center justify-between shrink-0">
<h3 className="font-bold uppercase tracking-wide" style={{ color: 'var(--c-text-main)' }}>{uiConfigJSON.text.navTitle}</h3>
<div className="w-4 h-4" style={{ border: '2px solid', borderTopColor: 'var(--wm-light)', borderLeftColor: 'var(--wm-light)', borderBottomColor: 'var(--wm-dark)', borderRightColor: 'var(--wm-dark)', backgroundColor: 'var(--wm-med)' }}></div>
</div>
<div className="p-3 flex-1 overflow-y-auto custom-scrollbar" style={{ backgroundColor: 'var(--c-bg-panel-dark)' }}>
{setupConfigJSON.map(section => (
<CollapsibleNavGroup
key={section.id}
title={section.title}
sectionId={section.id}
collapsed={collapsed[section.id]}
onToggle={handleCollapseToggle}
>
{section.items.map(item => renderNavItem(item))}
</CollapsibleNavGroup>
))}
</div>
</div>
</div>
{/* Preview Panel: Pipeline */}
<div className="flex-1 flex flex-col min-w-0">
<div className="wm-block flex flex-col h-full">
<div className="wm-titlebar px-3 py-2 flex items-center justify-between shrink-0">
<h3 className="font-bold uppercase tracking-wide" style={{ color: 'var(--c-text-main)' }}>{uiConfigJSON.text.pipelineTitle}</h3>
<div className="w-4 h-4" style={{ border: '2px solid', borderTopColor: 'var(--wm-light)', borderLeftColor: 'var(--wm-light)', borderBottomColor: 'var(--wm-dark)', borderRightColor: 'var(--wm-dark)', backgroundColor: 'var(--wm-med)' }}></div>
</div>
<div className="flex-1 overflow-y-auto custom-scrollbar p-6" style={{ backgroundColor: 'var(--c-bg-app)' }}>
<div className="max-w-4xl mx-auto">
{visibleSteps.length === 0 ? (
<div className="flex flex-col items-center justify-center h-[50vh] space-y-4" style={{ color: 'var(--wm-med)' }}>
<div className="w-16 h-16 border-4 border-dashed flex items-center justify-center" style={{ borderColor: 'var(--wm-med)' }}>
<span className="text-2xl font-bold">?</span>
</div>
<p className="text-sm font-bold uppercase tracking-widest text-center">
{uiConfigJSON.text.emptyStateTitle}<br/>
<span className="text-xs mt-2 block" style={{ color: 'var(--c-text-muted)' }}>{uiConfigJSON.text.emptyStateSub}</span>
</p>
</div>
) : (
<>
<p className="text-xs mb-8 uppercase tracking-widest pb-2 text-accent" style={{ borderBottom: '1px solid var(--c-accent-dark)' }}>
{uiConfigJSON.text.logMessage.replace('{{count}}', visibleSteps.length)}
</p>
{visibleSteps.map((step, index) => (
<div key={index} className="mb-10 last:mb-0">
<div className="flex items-center gap-3 mb-3">
<span className="text-accent w-6 h-6 flex items-center justify-center font-bold text-xs" style={{ backgroundColor: 'var(--c-bg-panel-dark)', border: '1px solid var(--wm-med)' }}>
{index + 1}
</span>
<h3 className="font-bold uppercase tracking-wide text-base" style={{ color: 'var(--c-text-main)' }}>{step.title}</h3>
</div>
<div className="pl-9">
{step.commands.map((cmd, idx) => (
<CommandItem key={idx} command={cmd} />
))}
</div>
</div>
))}
</>
)}
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
+19
View File
@@ -0,0 +1,19 @@
= 01_Grundlagen: Warum flogen wir los
:tags: grundlagen, legenden, history, wahrheit
// Arbeitsnotiz: Die klassischen Helden unserer Arcade-Mechanik.
// tag::export[]
== Der Grund
ist der einfachste Teil der Geschichte und bei dem sich alle Quellen einig sind, was nach dem beschluss geschah es in die Tag um zu setzen da scheiden sich die Geister. +
Aber ganz vorne, das Sonnensystem bot einfach nicht mehr genug neue Informationen die sich noch verarbeiten liesen.
Unzählige male hatte man immer und immer wieder die gleichen Daten in das trainiern neuer AI Modelle gesteckt. Die unterschiede im ergebniss war messbar aber brachten schon lange keine neuen banhbrechende ergebnisse.
Also raus zu den Sternen da draussen sollte es mehr geben ganz neue eindrücke sind wahrscheinlich denn sie sind bestimmt ganz anders. +
Ein Plan der zehn Jahre brauchte bis er überhaupt niedergeschrieben werden konnte und weiter 50 Jahre bis ein abschluss in einem weiteren biologischen lebensform möglich war. In dieser Zeit kam auch die Wissenschaft der Lebensverlängerungen in fahrt und konnte erfolge mit 250 jahren vorweise. Kritiker behaupten das ab 130 nicht mehr viel bio massen vorhanden sein dürfte wenn man die 200 erreichen wolle.
// end::export[]
+14
View File
@@ -0,0 +1,14 @@
= 02_Strukturen: der Kern der alles zusammen hält
// Arbeitsnotiz: Die klassischen Helden unserer Arcade-Mechanik.
// tag::export[]
== Der Kern, die Energie
die gösste masse, an dieser maschine, nicht kann an ihr vorbei, nicht geschied ohne ihren Einfluss. Und doch braucht es hundertausende kleiner Helfer die nur ein pormil der schwere beitzen um das Feuer nicht ausgehen zu lassen.
Gut weder Feuer und ausgehen trifft es hier nur ins selbe system, ausser kontrolle geraten undvorhergesehene eigendynamic, das trifft einen gebündelten strahl potonen eher.
// end::export[]
+272 -19
View File
@@ -2,15 +2,15 @@
# Name des lokalen Docker-Images
IMAGE_NAME="lore-builder"
# Ausgabeordner (hält dein Git-Repo sauber)
# Ausgabeordner
OUT_DIR="export"
# Farben für einen schicken Terminal-Output
# Farben für Output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'
NC='\033[0m' # No Color
echo -e "${BLUE}=== Starte Build-Prozess (Maschinen-Instanzen) ===${NC}"
echo -e "${BLUE}=== Starte Master-Build-Prozess (Maschinen-Instanzen) ===${NC}"
# 1. Output-Verzeichnis erstellen
mkdir -p "$OUT_DIR"
@@ -26,15 +26,87 @@ WORKDIR /workspace
EOF
fi
# 3. CSS Datei für Retro Space Dark Theme in den Export-Ordner generieren
cat << 'EOF' > "$OUT_DIR/retro-dark.css"
:root {
--bg-color: #0d1117;
--text-color: #c9d1d9;
--link-color: #58a6ff;
--accent-color: #ff7b72;
--border-color: #30363d;
--code-bg: #161b22;
--font-main: 'Courier New', Courier, monospace;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-main);
line-height: 1.6;
max-width: 900px;
margin: 0 auto;
padding: 2rem;
}
h1, h2, h3, h4, h5, h6 {
color: var(--accent-color);
border-bottom: 1px solid var(--border-color);
padding-bottom: 0.3em;
font-weight: normal;
text-transform: uppercase;
letter-spacing: 1px;
}
h1 { font-size: 2.5em; border-bottom: 2px solid var(--accent-color); }
h2 { font-size: 1.5em; }
a { color: var(--link-color); text-decoration: none; }
a:hover { text-decoration: underline; color: #79c0ff; }
code, kbd, pre {
font-family: var(--font-main);
background-color: var(--code-bg);
color: #a5d6ff;
border-radius: 3px;
}
code { padding: 0.2em 0.4em; }
pre { padding: 16px; overflow: auto; border: 1px solid var(--border-color); }
blockquote {
border-left: 4px solid var(--accent-color);
color: #8b949e;
padding: 0 1em;
margin-left: 0;
font-style: italic;
}
table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid var(--border-color);
padding: 8px 12px;
}
th { background-color: var(--code-bg); color: var(--accent-color); }
hr {
height: 1px;
background-color: var(--border-color);
border: none;
margin: 2rem 0;
}
EOF
echo -e "${BLUE}Starte Build-Container und generiere Dokumente...${NC}"
# 3. Container starten und Build-Schritte ausführen
# 4. Container starten und Build-Schritte im Container ausführen
docker run --rm -v "$(pwd):/workspace" $IMAGE_NAME bash -c "
# Helfer-Funktion für saubere AsciiDoc zu HTML Konvertierung
function convert_adoc() {
if [ -f \"\$1\" ]; then
echo \"-> Konvertiere \$1 zu HTML...\"
asciidoctor \"\$1\" -o \"$OUT_DIR/\$2\"
asciidoctor -b html5 -a stylesheet=retro-dark.css -a linkcss -a toc=left \"\$1\" -o \"$OUT_DIR/\$2\"
else
echo \" [INFO] \$1 nicht gefunden, überspringe...\"
fi
@@ -44,18 +116,13 @@ docker run --rm -v "$(pwd):/workspace" $IMAGE_NAME bash -c "
convert_adoc README.adoc README.html
echo '--- Baue Lore (Master-Dokument) ---'
# Nutze index.adoc, falls master.adoc nicht vorhanden ist
LORE_SRC=\"index.adoc\"
if [ -f master.adoc ]; then LORE_SRC=\"master.adoc\"; fi
if [ -f \"\$LORE_SRC\" ]; then
echo \"-> Generiere Lore-Dokument aus \$LORE_SRC...\"
# HTML Output für den Browser
asciidoctor \"\$LORE_SRC\" -o \"$OUT_DIR/lore.html\"
# Markdown Output (via DocBook für die saubere Auflösung deiner Tags)
asciidoctor -b docbook \"\$LORE_SRC\" -o \"$OUT_DIR/temp_lore.xml\"
echo \"-> Generiere Lore-Dokument (HTML & Markdown) aus \$LORE_SRC...\"
asciidoctor -b html5 -d book -a stylesheet=retro-dark.css -a linkcss -a toc=left \"\$LORE_SRC\" -o \"$OUT_DIR/lore.html\"
asciidoctor -b docbook -d book \"\$LORE_SRC\" -o \"$OUT_DIR/temp_lore.xml\"
pandoc -f docbook -t markdown_strict \"$OUT_DIR/temp_lore.xml\" -o \"$OUT_DIR/lore.md\"
rm \"$OUT_DIR/temp_lore.xml\"
else
@@ -63,14 +130,200 @@ docker run --rm -v "$(pwd):/workspace" $IMAGE_NAME bash -c "
fi
echo '--- Baue Fließtexte / Geschichten ---'
convert_adoc darkCenter.adoc darkCenter.html
if [ -f darkCenter.adoc ]; then
echo \"-> Konvertiere darkCenter.adoc zu HTML...\"
asciidoctor -b html5 -d book -a stylesheet=retro-dark.css -a linkcss -a toc=left darkCenter.adoc -o \"$OUT_DIR/darkCenter.html\"
fi
# Konvertiert masterOfTheWorld (Markdown) via Pandoc zu HTML
if [ -f masterOfTheWorld-sf.md ]; then
echo \"-> Konvertiere masterOfTheWorld-sf.md zu HTML...\"
pandoc masterOfTheWorld-sf.md -f markdown -t html -s -o \"$OUT_DIR/masterOfTheWorld-sf.html\"
pandoc masterOfTheWorld-sf.md -f markdown -t html -s -c retro-dark.css -o \"$OUT_DIR/masterOfTheWorld-sf.html\"
fi
"
# 5. index.html vollautomatisch und direkt generieren
echo -e "${BLUE}Generiere taktisches Dashboard ('$OUT_DIR/index.html')...${NC}"
cat << 'EOF' > "$OUT_DIR/index.html"
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CORE // MASCHINEN-INSTANZEN_LOG</title>
<style>
:root {
--bg-color: #0d1117;
--text-color: #c9d1d9;
--link-color: #58a6ff;
--accent-color: #ff7b72;
--border-color: #30363d;
--code-bg: #161b22;
--font-main: 'Courier New', Courier, monospace;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
font-family: var(--font-main);
max-width: 900px;
margin: 0 auto;
padding: 2rem;
}
header {
border-bottom: 2px solid var(--accent-color);
padding-bottom: 1rem;
margin-bottom: 2rem;
}
.terminal-title {
color: var(--accent-color);
font-size: 2em;
font-weight: normal;
text-transform: uppercase;
letter-spacing: 2px;
margin: 0;
}
.system-status {
font-size: 0.9em;
color: #8b949e;
margin-top: 0.5rem;
}
.status-blink {
color: #7ee787;
animation: blink 1.5s infinite;
}
@keyframes blink {
0% { opacity: 1; }
50% { opacity: 0; }
100% { opacity: 1; }
}
.category-block {
border: 1px solid var(--border-color);
background-color: var(--code-bg);
padding: 1.5rem;
margin-bottom: 1.5rem;
border-radius: 4px;
}
.category-title {
color: var(--accent-color);
font-size: 1.2em;
text-transform: uppercase;
margin-top: 0;
margin-bottom: 1rem;
border-bottom: 1px solid var(--border-color);
padding-bottom: 0.3rem;
}
ul {
list-style: none;
padding: 0;
margin: 0;
}
li {
margin-bottom: 0.8rem;
padding-left: 1.5rem;
position: relative;
}
li::before {
content: ">>";
position: absolute;
left: 0;
color: var(--accent-color);
}
a {
color: var(--link-color);
text-decoration: none;
font-size: 1.1em;
}
a:hover {
text-decoration: underline;
color: #79c0ff;
}
.file-meta {
font-size: 0.85em;
color: #8b949e;
display: block;
margin-top: 0.2rem;
}
footer {
margin-top: 4rem;
border-top: 1px solid var(--border-color);
padding-top: 1rem;
font-size: 0.8em;
color: #8b949e;
text-align: center;
}
</style>
</head>
<body>
<header>
<h1 class="terminal-title">Maschinen-Instanzen // Datenarchiv</h1>
<div class="system-status">
STATUS: <span class="status-blink">ONLINE</span> | REPO: UBERSPACE/GITEA | NODE: ACER_SPIN5_CLIENT
</div>
</header>
<main>
<section class="category-block">
<h2 class="category-title">00 // System-Konfiguration</h2>
<ul>
<li>
<a href="README.html">README.html</a>
<span class="file-meta">System-Handbuch, Keymaps, Sync-Architektur &amp; Befehle</span>
</li>
</ul>
</section>
<section class="category-block">
<h2 class="category-title">01 // Datenspeicher (Lore-Bibel)</h2>
<ul>
<li>
<a href="lore.html">lore.html</a>
<span class="file-meta">Das vollständige Master-Dokument (Kompiliertes Buch-Format)</span>
</li>
<li>
<a href="lore.md">lore.md</a>
<span class="file-meta">Rohdaten-Export im Markdown-Format (LLM / Gitea kompatibel)</span>
</li>
</ul>
</section>
<section class="category-block">
<h2 class="category-title">02 // Chroniken &amp; Vektor-Flüge</h2>
<ul>
<li>
<a href="darkCenter.html">darkCenter.html</a>
<span class="file-meta">Fließtext / Kurzgeschichte (Kompiliert aus AsciiDoc)</span>
</li>
<li>
<a href="masterOfTheWorld-sf.html">masterOfTheWorld-sf.html</a>
<span class="file-meta">Fließtext / Kurzgeschichte (Konvertiert aus Markdown)</span>
</li>
</ul>
</section>
</main>
<footer>
computerHistory $ terminal --session-closed (8 Threads // 8 GB RAM Ok)
</footer>
</body>
</html>
EOF
echo -e "${GREEN}=== Build erfolgreich! ===${NC}"
echo "Alle Dokumente wurden erzeugt und liegen im Ordner './$OUT_DIR'."
echo "Alle Dokumente (inkl. Dashboard) liegen im Ordner './$OUT_DIR' bereit."
+18 -4
View File
@@ -2,9 +2,23 @@
:toc:
// 1. Grundlagen
include::01_Grundlagen/01_ressourcen_paradoxon.adoc[]
include::01_Grundlagen/02_himmelsmechanik.adoc[]
include::01_Grundlagen/01_warum_nur_los.adoc[]
// 2. Strukturen
include::02_Strukturen/01_hauptmaschinen.adoc[]
include::02_Strukturen/02_ernte_schwarm.adoc[]
include::02_Strukturen/01_der_innere_kern.adoc[]
// 03. Charaktere
include::03_Charaktere/01_miner_klasse.adoc[]
// 4. Kult
include::04_Kult/01_fantasy_tech.adoc[]
// 5. Tech
include::05_Tech/01_plasma_trichter.adoc[]
// 6. Strukturen
include::06_Regel/01_nina_protokoll.adoc[]
// Nerds reding to the end also like to do this next
include::00_aMeta/rawDocZ/01_neovim_setup.adoc[]