Skip to content

Instantly share code, notes, and snippets.

@CemraJC
Created February 8, 2024 09:05
Show Gist options
  • Select an option

  • Save CemraJC/8438a616740162661a9958c46c95315d to your computer and use it in GitHub Desktop.

Select an option

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

@pgasidlo
Copy link

Nice one. One patch here https://gist.github.com/CemraJC/8438a616740162661a9958c46c95315d#file-site-structure-generator-js-L70

const pageLink = child.page ? ` <a href="/en/${child.page.path}">${child.page.title}</a>` : child.name;

to

const pageLink = child.page ? ` <a href="/${child.page.locale}/${child.page.path}">${child.page.title}</a>` : child.name;

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