Skip to content

Instantly share code, notes, and snippets.

@CemraJC
Created February 8, 2024 09:05
Show Gist options
  • Save CemraJC/8438a616740162661a9958c46c95315d to your computer and use it in GitHub Desktop.
Save CemraJC/8438a616740162661a9958c46c95315d to your computer and use it in GitHub Desktop.
Wiki.JS Version 2 - Dynamic Page Structure / TOC Generator
<script>
// ^^^
// Keep the <script> tags when copying into Wiki.JS page editor
async function fetchAllPages() {
const graphqlEndpoint = "/graphql";
const query = `
query GetAllPages {
pages{
list(limit: 1000, orderBy: PATH, orderByDirection: ASC) {
id
path
locale
title
createdAt
updatedAt
}
}
}
`;
try {
const response = await fetch(graphqlEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ query })
});
if (!response.ok) {
throw new Error(`Network error: ${response.statusText}`);
}
const jsonResponse = await response.json();
console.log(jsonResponse.data)
return jsonResponse.data.pages.list;
} catch (error) {
console.error('Fetching all pages failed:', error);
return []; // Return an empty array on failure
}
}
function generateTree(pages) {
const root = { children: [] };
pages.forEach(page => {
const parts = page.path.split('/').filter(Boolean); // Split path and remove empty parts
let current = root;
parts.forEach((part, index) => {
let child = current.children.find(child => child.name === part);
if (!child) {
child = { name: part, children: [], page: null };
current.children.push(child);
}
current = child;
});
current.page = page; // Assign the page to the last node
});
return root;
}
function buildHtmlFromTree(node) {
if (node.children.length === 0) {
return '';
}
let html = '<ul>';
node.children.forEach(child => {
const pageLink = child.page ? ` <a href="/en/${child.page.path}">${child.page.title}</a>` : child.name;
html += `<li>${pageLink}${buildHtmlFromTree(child)}</li>`;
});
html += '</ul>';
return html;
}
function removeElement(id) {
var elem = document.getElementById(id);
return elem.parentNode.removeChild(elem);
}
async function displayPageTree() {
try {
const pages = await fetchAllPages();
// Check if the pages array is empty right after fetching
if (pages.length === 0) {
document.getElementById('loadingMessage').innerHTML = '<p>No pages found.</p>';
return;
}
const treeRoot = generateTree(pages);
// Check if the generated tree has no children
// (i.e., is effectively empty - this may happen on algorithmic error
// with the tree generator, even if the pages list has pages in it)
if (treeRoot.children.length === 0) {
document.getElementById('loadingMessage').innerHTML = '<p>The tree could not be built.</p>';
return;
}
const treeHtml = buildHtmlFromTree(treeRoot);
document.getElementById('pageTree').innerHTML = treeHtml;
removeElement('loadingMessage');
} catch (error) {
console.error('Error displaying page tree:', error);
document.getElementById('loadingMessage').innerHTML = '<p>Failed to load the page tree. Please try again later.</p>';
}
}
window.boot.register('page-ready', () => {
displayPageTree();
});
</script>
<!-- This file should be the main page content (you need to use the Raw HTML editor) -->
<h1>Site Structure</h1>
<p>The following section shows the entire heirarchy of this wiki.</p>
<hr/>
<div id="pageTree">Loading pages...</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<i id="loadingMessage">If you are reading this, it probably should have loaded by now...</i>
<hr/>
@oyale
Copy link

oyale commented Mar 12, 2024

Thanks for sharing!

I've based on this gist to generate virtual folders index dynamically 🎉

I've made a few changes to how HTML is structured, using h2 tags and sections. I've also limited the displayed results to those that start with the same path as the current one

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment