My experience with GPT to write an XWiki macro - here: make chapter and paragraphs collapsable

I had the idea of trying out GPT for programming an XWiki macro.
Here is my first attempt with a surprisingly good, because working result:

My instruction was:

Write a macro for XWiki, after which the chapters of a document can be opened and closed with a click. Apart from the macro call itself, the document should not have to be customised. The colour and background of the heading should be changed when the document is collapsed. The mouse cursor should be “s-size” when the chapter is collapsed and “n-size” otherwise.

I got the following result and moved it into a working macro: (The layout is just from copy/paste unchanged!):


To create a macro for XWiki that makes the chapters of a document collapsible by clicking on them, changes the color and background of the heading when collapsed, and changes the mouse cursor to “s-size” when collapsed and “n-size” otherwise, follow these steps:

1. Create the Macro

Go to Wiki Administration > Content > Macros and create a new macro named CollapsibleChapters.

Macro Definition (CollapsibleChaptersMacro.xml)
<macro>
  <id>collapsibleChapters</id>
  <name>Collapsible Chapters</name>
  <description>Makes chapters collapsible by clicking on them, changes the header color and background when collapsed, and changes the mouse cursor.</description>
  <parameters>
    <!-- No parameters needed for this macro -->
  </parameters>
  <content type="text/html">
    <![CDATA[
    {{velocity}}
    #set ($discard = $xwiki.ssx.use('collapse.css'))
    #set ($discard = $xwiki.jsx.use('collapse.js'))
    {{/velocity}}

    {{html clean="false"}}
    <script>
    document.addEventListener("DOMContentLoaded", function() {
        var headers = document.querySelectorAll("h1, h2, h3, h4, h5, h6");
        headers.forEach(function(header) {
            var content = header.nextElementSibling;
            while (content && !content.tagName.match(/^H[1-6]$/i)) {
                if (content.style) {
                    content.classList.add("collapsible-content");
                }
                content = content.nextElementSibling;
            }
            header.classList.add("collapsible-header");
            header.addEventListener("click", function() {
                var next = this.nextElementSibling;
                var isCollapsed = false;
                while (next && !next.tagName.match(/^H[1-6]$/i)) {
                    if (next.style) {
                        if (next.style.display === "none" || next.style.display === "") {
                            next.style.display = "block";
                            isCollapsed = false;
                        } else {
                            next.style.display = "none";
                            isCollapsed = true;
                        }
                    }
                    next = next.nextElementSibling;
                }
                if (isCollapsed) {
                    this.style.color = "white"; // Change to desired color when collapsed
                    this.style.backgroundColor = "black"; // Change to desired background color when collapsed
                    this.style.cursor = "s-resize"; // Change cursor to s-resize when collapsed
                } else {
                    this.style.color = ""; // Reset to default color when expanded
                    this.style.backgroundColor = ""; // Reset to default background color when expanded
                    this.style.cursor = "n-resize"; // Change cursor to n-resize when expanded
                }
            });
        });
    });
    </script>
    {{/html}}
    ]]>
  </content>
</macro>
2. Create the JavaScript and CSS Files

Upload the following files to your XWiki:

collapse.js
document.addEventListener("DOMContentLoaded", function() {
    var headers = document.querySelectorAll(".collapsible-header");
    headers.forEach(function(header) {
        header.addEventListener("click", function() {
            var content = this.nextElementSibling;
            var isCollapsed = false;
            while (content && !content.tagName.match(/^H[1-6]$/i)) {
                if (content.style) {
                    if (content.style.display === "none" || content.style.display === "") {
                        content.style.display = "block";
                        isCollapsed = false;
                    } else {
                        content.style.display = "none";
                        isCollapsed = true;
                    }
                }
                content = content.nextElementSibling;
            }
            if (isCollapsed) {
                this.style.color = "white"; // Change to desired color when collapsed
                this.style.backgroundColor = "black"; // Change to desired background color when collapsed
                this.style.cursor = "s-resize"; // Change cursor to s-resize when collapsed
            } else {
                this.style.color = ""; // Reset to default color when expanded
                this.style.backgroundColor = ""; // Reset to default background color when expanded
                this.style.cursor = "n-resize"; // Change cursor to n-resize when expanded
            }
        });
    });
});
collapse.css
.collapsible-content {
    display: none;
    padding: 10px;
    border: 1px solid #ccc;
    margin-top: 5px;
}

.collapsible-header {
    cursor: n-resize;
    padding: 10px;
    background-color: #f1f1f1;
    border: 1px solid #ccc;
    margin-top: 5px;
}
3. Use the Macro in Your Document

Insert the macro into your XWiki document:

{{collapsibleChapters/}}
Summary

By following these steps, you have created a macro that makes chapters in an XWiki document collapsible by clicking on them, changes the color and background of the heading when collapsed, and changes the mouse cursor to “s-resize” when collapsed and “n-resize” otherwise. The macro automatically includes the necessary JavaScript and CSS files and marks the chapters accordingly.

I am impressed.

Norbert

Nice and promising. Thx for reporting.

I had tried chatGPT (was 3.5 back then I believe) and got mixed results. In the end it took a lot of tries (around 20-30) to find the right prompt for something basic (i has asked to write a velocity script in xwiki to list all attachments attached to the current page). But maybe it’s improved substantially with 4o or even o1.

FYI:

I am using Model: GPT 4o

The prompt

write a velocity script for xwiki to list all attachment for the current file.

gives the following output, which works and generates HTML code:


To list all attachments for the current page in XWiki using a Velocity script, you can use the XWiki API. The following Velocity script can be added to a page or a macro to display a list of all attachments for the current page:

## Get the current document
#set ($doc = $xwiki.getDocument($doc.fullName))

## Get the list of attachments
#set ($attachments = $doc.getAttachmentList())

## Check if there are any attachments
#if ($attachments.size() == 0)
  ## No attachments found
  <p>No attachments found for this page.</p>
#else
  ## List all attachments
  <ul>
  #foreach ($attachment in $attachments)
    <li>
      <a href="$xwiki.getURL($doc.fullName, 'download', "filename=$attachment.filename")">$attachment.filename</a>
      (Size: $attachment.filesize bytes)
    </li>
  #end
  </ul>
#end
Explanation
  1. Get the current document: The script retrieves the current document using $xwiki.getDocument($doc.fullName).
  2. Get the list of attachments: The script retrieves the list of attachments for the current document using $doc.getAttachmentList().
  3. Check if there are any attachments: The script checks if the list of attachments is empty.
  4. List all attachments: If there are attachments, the script iterates over the list and displays each attachment as a link. The link allows users to download the attachment, and the size of the attachment is also displayed.
Usage
  1. Edit the page: Go to the page where you want to list the attachments and switch to the “Wiki” editor.
  2. Add the script: Copy and paste the above Velocity script into the page content.
  3. Save the page: Save the page to see the list of attachments.

This script will dynamically list all attachments for the current page, providing download links and displaying the file sizes.

Thx, yes, this is close to what I had back then. What I had to modify in the prompt:

  • It’s missing the velocity macro markers
  • You need to ask it to use xwiki syntax 2.1 instead of HTML
  • getURL is not the right api to use

I remember that the issue was that when I modified the prompt it also changed the result and got worse results… I had to write like 5 or more sentences in the prompt to get exactly what I wanted.

Even with the free version of Copilot without an Microsoft account I got mixed results on smaller projects that were still very useful to start things. Most of the times the issues were methods that are not part of xwiki or are named differently.

It’s insane how creating own macros for own specialized needs will become so much easier in the future with AI, and as XWiki is so easy to expand, this will probably give XWiki a big benefit over comparable wiki solutions.

That’s an interesting idea. In addition, being open source means that it’s easy for all the LLMs out there to learn from all the XWiki content out there. Continuing to enrich the developer doc on xwiki.org and https://snippets.xwiki.org/ is probably a good direction.

Thanks

1 Like