Skip to content

Instantly share code, notes, and snippets.

@thejoester
Last active August 6, 2025 09:30
Show Gist options
  • Select an option

  • Save thejoester/15719ea0da2eed70cea2926a5bb8aa44 to your computer and use it in GitHub Desktop.

Select an option

Save thejoester/15719ea0da2eed70cea2926a5bb8aa44 to your computer and use it in GitHub Desktop.
FoundryVTT - Show cleaned up and sorted Roll Table list
const LINK_REMOVER = /@\w+\[([^\]]+)\]\{([^}]+)\}/g;
// Sort entries alphabetically ignoring numbers by name (or text), then description
function compareLabels(a, b) {
const clean = str => (str || "")
.replaceAll(LINK_REMOVER, "$2") // Strip Foundry links
.replace(/^\d+\s*/, "") // Remove leading numbers + optional space
.trim()
.toLowerCase(); // Optional: ignore case
const textA = clean(a.text);
const textB = clean(b.text);
const textCompare = textA.localeCompare(textB);
if (textCompare !== 0) return textCompare;
const descA = clean(a.description);
const descB = clean(b.description);
return descA.localeCompare(descB);
}
// Build dropdown options
const tableOptions = game.tables.map(t =>
`<option value="${t.uuid}">${t.name}</option>`
).join("");
new foundry.applications.api.DialogV2({
window: { title: "Select RollTable to Preview" },
content: `
<label for="table">Choose a table:</label><br>
<select name="table" style="width: 100%; margin-top: 0.5em;">${tableOptions}</select>
`,
buttons: [{
action: "preview",
label: "Show Sorted Preview",
default: true,
callback: (event, button, dialog) => {
const select = button.form.elements.table;
return select?.value || null;
}
}],
submit: async (uuid) => {
if (!uuid) return;
const table = await fromUuid(uuid);
if (!table) return ui.notifications.error("Table not found.");
const entries = Array.from(table.getEmbeddedCollection("TableResult"));
entries.sort(compareLabels);
const contentText = entries.map((e, i) => {
// Clean both text and description
const cleanedText = (e.text || "").replaceAll(LINK_REMOVER, "$2");
const cleanedDesc = (e.description || "").replaceAll(LINK_REMOVER, "$2");
// Prefer cleanedText if available, otherwise fallback to cleanedDesc
return cleanedText || cleanedDesc || "(no text)";
}).join("\n");
new foundry.applications.api.DialogV2({
window: { title: `Sorted Preview: ${table.name}` },
content: `
<div style="min-width: 500px; max-height: 70vh; overflow-y: auto; padding-right: 1em;">
<textarea readonly style="width: 100%; height: 400px; font-family: monospace;">${contentText}</textarea>
</div>
`,
buttons: [{
action: "close",
label: "Close",
default: true
}]
}).render(true);
}
}).render(true);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment