undefined / index.html
michaeldoconnor's picture
Create a page that converts a NedDB file to json in Foundry VTT format.
84860c5 verified
Raw History Blame Contribute Delete
12.5 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JSON to Foundry Converter</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vanta@latest/dist/vanta.waves.min.js"></script>
<style>
.code-area {
font-family: 'Courier New', monospace;
}
.vanta-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
opacity: 0.3;
}
</style>
</head>
<body class="bg-gray-100 min-h-screen">
<div id="vanta-bg" class="vanta-bg"></div>
<div class="container mx-auto px-4 py-12">
<header class="text-center mb-12">
<h1 class="text-4xl font-bold text-indigo-700 mb-2 flex justify-center items-center">
<i data-feather="wand" class="mr-3"></i>
JSON to Foundry Wizardry
</h1>
<p class="text-lg text-gray-600">Transform your JSON data into Foundry VTT compatible format with magic!</p>
</header>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
<!-- Input Section -->
<div class="bg-white rounded-xl shadow-lg p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Input JSON</h2>
<button id="sample-btn" class="text-sm bg-indigo-100 hover:bg-indigo-200 text-indigo-700 px-3 py-1 rounded-md transition">
<i data-feather="file-text" class="inline mr-1"></i> Load Sample
</button>
</div>
<textarea id="input-json" class="code-area w-full h-96 p-4 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" placeholder='Paste your JSON here or click "Load Sample"'></textarea>
</div>
<!-- Output Section -->
<div class="bg-white rounded-xl shadow-lg p-6">
<div class="flex justify-between items-center mb-4">
<h2 class="text-xl font-semibold text-gray-800">Foundry Output</h2>
<div>
<button id="copy-btn" class="text-sm bg-indigo-100 hover:bg-indigo-200 text-indigo-700 px-3 py-1 rounded-md transition mr-2">
<i data-feather="copy" class="inline mr-1"></i> Copy
</button>
<button id="download-btn" class="text-sm bg-indigo-100 hover:bg-indigo-200 text-indigo-700 px-3 py-1 rounded-md transition">
<i data-feather="download" class="inline mr-1"></i> Download
</button>
</div>
</div>
<textarea id="output-json" class="code-area w-full h-96 p-4 border border-gray-300 rounded-lg bg-gray-50" placeholder="Your Foundry VTT compatible JSON will appear here" readonly></textarea>
</div>
</div>
<!-- Conversion Options -->
<div class="mt-8 bg-white rounded-xl shadow-lg p-6">
<h2 class="text-xl font-semibold text-gray-800 mb-4">Conversion Options</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<label class="block text-gray-700 mb-2">Foundry Entity Type</label>
<select id="entity-type" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="Actor">Actor</option>
<option value="Item">Item</option>
<option value="Scene">Scene</option>
<option value="JournalEntry">Journal Entry</option>
<option value="RollTable">Roll Table</option>
</select>
</div>
<div>
<label class="block text-gray-700 mb-2">System</label>
<select id="system-type" class="w-full p-2 border border-gray-300 rounded-lg">
<option value="dnd5e">D&D 5e</option>
<option value="pf2e">Pathfinder 2e</option>
<option value="swade">SWADE</option>
<option value="custom">Custom</option>
</select>
</div>
<div class="flex items-end">
<button id="convert-btn" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white py-2 px-4 rounded-lg transition flex items-center justify-center">
<i data-feather="zap" class="mr-2"></i> Convert Now
</button>
</div>
</div>
</div>
<!-- Help Section -->
<div class="mt-12 bg-indigo-50 rounded-xl p-6">
<h2 class="text-xl font-semibold text-indigo-800 mb-4 flex items-center">
<i data-feather="help-circle" class="mr-2"></i> How It Works
</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-white p-4 rounded-lg shadow">
<h3 class="font-medium text-indigo-700 mb-2">1. Paste Your JSON</h3>
<p class="text-gray-600">Insert your existing JSON data or use our sample data to get started.</p>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<h3 class="font-medium text-indigo-700 mb-2">2. Select Options</h3>
<p class="text-gray-600">Choose the Foundry entity type and system you're working with.</p>
</div>
<div class="bg-white p-4 rounded-lg shadow">
<h3 class="font-medium text-indigo-700 mb-2">3. Convert & Use</h3>
<p class="text-gray-600">Get your Foundry-compatible JSON and import it into your game!</p>
</div>
</div>
</div>
</div>
<footer class="bg-gray-800 text-white py-6 mt-12">
<div class="container mx-auto px-4 text-center">
<p>Made with <i data-feather="heart" class="inline text-red-400"></i> for Foundry VTT enthusiasts</p>
<p class="text-gray-400 text-sm mt-2">Not affiliated with Foundry Virtual Tabletop</p>
<div class="mt-4">
<a href="nedb-converter.html" class="text-purple-300 hover:text-purple-100 text-sm">
<i data-feather="database" class="inline mr-1"></i> Need to convert NedDB files?
</a>
</div>
</div>
</footer>
<script>
feather.replace();
// Initialize Vanta.js background
VANTA.WAVES({
el: "#vanta-bg",
color: 0x5b6ee1,
waveHeight: 20,
shininess: 50,
waveSpeed: 1.0,
zoom: 0.8
});
// Sample JSON data
const sampleData = {
"name": "Ancient Red Dragon",
"type": "dragon",
"hp": 546,
"ac": 22,
"stats": {
"str": 30,
"dex": 10,
"con": 29,
"int": 18,
"wis": 15,
"cha": 23
},
"attacks": [
{
"name": "Bite",
"damage": "2d10+10 piercing plus 2d6 fire"
},
{
"name": "Claw",
"damage": "2d6+10 slashing"
}
],
"specialAbilities": [
"Fire Breath",
"Frightful Presence",
"Legendary Resistance"
]
};
// DOM Elements
const inputJson = document.getElementById('input-json');
const outputJson = document.getElementById('output-json');
const convertBtn = document.getElementById('convert-btn');
const sampleBtn = document.getElementById('sample-btn');
const copyBtn = document.getElementById('copy-btn');
const downloadBtn = document.getElementById('download-btn');
const entityType = document.getElementById('entity-type');
const systemType = document.getElementById('system-type');
// Load sample data
sampleBtn.addEventListener('click', () => {
inputJson.value = JSON.stringify(sampleData, null, 2);
});
// Copy output
copyBtn.addEventListener('click', () => {
outputJson.select();
document.execCommand('copy');
// Show feedback
const originalText = copyBtn.innerHTML;
copyBtn.innerHTML = '<i data-feather="check" class="inline mr-1"></i> Copied!';
setTimeout(() => {
copyBtn.innerHTML = originalText;
feather.replace();
}, 2000);
});
// Download output
downloadBtn.addEventListener('click', () => {
if (!outputJson.value) return;
const blob = new Blob([outputJson.value], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `foundry-${entityType.value.toLowerCase()}.json`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
});
// Conversion function
function convertToFoundryFormat(input, type, system) {
try {
const data = JSON.parse(input);
let foundryData = {};
// Base structure
foundryData.name = data.name || "Unnamed Entity";
foundryData.type = type;
foundryData.data = {};
// System-specific conversions
if (system === "dnd5e" && type === "Actor") {
foundryData.data = {
attributes: {
hp: {
value: data.hp || 0,
max: data.hp || 0
},
ac: {
value: data.ac || 10
}
},
abilities: {
str: { value: data.stats?.str || 10 },
dex: { value: data.stats?.dex || 10 },
con: { value: data.stats?.con || 10 },
int: { value: data.stats?.int || 10 },
wis: { value: data.stats?.wis || 10 },
cha: { value: data.stats?.cha || 10 }
}
};
if (data.attacks) {
foundryData.items = data.attacks.map(attack => ({
name: attack.name,
type: "weapon",
data: {
damage: {
parts: [[attack.damage || "1d6", ""]]
}
}
}));
}
} else {
// Generic conversion for other types
foundryData.data = data;
}
return JSON.stringify(foundryData, null, 2);
} catch (e) {
return `Error: ${e.message}`;
}
}
// Convert button click handler
convertBtn.addEventListener('click', () => {
if (!inputJson.value.trim()) {
outputJson.value = "Please enter some JSON to convert";
return;
}
outputJson.value = convertToFoundryFormat(
inputJson.value,
entityType.value,
systemType.value
);
});
</script>
</body>
</html>