Hacks & Customizations
These hacks are unsupported customizations meant as unofficial workarounds.
They can cause instability, introduce issues and may conflict with future updates. Apply at your own risk!

WYSIWYG Docx Import

  • Author: @ssddanbrown
  • Created: 7th Jun 2023
  • Updated: 7th Jun 2023
  • Last Tested On: v23.05

This hack adds the ability to import “.docx” files into the WYSIWYG editor, by dragging and dropping a “docx” file into the editor area. The file contents are converted to HTML then inserted into the editor at the current cursor position.

Conversion is performed browser-side using the mammoth.js library. Warning messages from the conversion will be logged to the browser console, and a popup warning notification will advise of this.

Considerations

  • This hack uses an externally hosted library, hosted on jsdelivr.net. You could host this locally instead if desired.
  • The conversion is relatively simplistic, to result in clean HTML for use in BookStack. Not all formatting is supported by the conversion and you’ll likely loose layout or formatting. Don’t expect a replica result in BookStack, this is more for easy importing of existing content.
  • Images will be within content, base64 included, until save when BookStack will attempt to extract them out. This may cause editor performance to be particular slow until first save after import.
  • You will likely see a “Dropped file type is not supported” warning message pop-up in the editor.

Code

head.html
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<script src="https://cdn.jsdelivr.net/npm/mammoth@1.5.1/mammoth.browser.min.js" defer></script>

<script type="module">
    // Convert the given "file" instance to HTML and insert the results
    // into the given TinyMCE "editor" instance.
    function convertAndInsertDocx(editor, file) {
        // Use a FileReader to handle conversion via an ArrayBuffer
        const reader = new FileReader();
        reader.onload = async function(loadEvent) {
            // Get and convert the ArrayBuffer version of the file
            const arrayBuffer = loadEvent.target.result;
            const {value: html, messages} = await window.mammoth.convertToHtml({arrayBuffer});
            // If warnings exists from conversion, log them to the browser console then
            // show a warning alert via BookStack's event system.
            if (messages.length > 0) {
                console.error(messages);
                window.$events.emit('warning', `${messages.length} warnings logged to browser console during conversion`);
            }
            // Insert the resulting HTML content insert the editor
            editor.insertContent(html);
        }
        reader.readAsArrayBuffer(file);
    }

    // Listen to BookStack emmitted WYSWIYG editor setup event
    window.addEventListener('editor-tinymce::setup', event => {
        // Get a reference to the editor and listen to file "drop" events
        const editor = event.detail.editor;
        editor.on('drop', event => {
            // For each of the files in the drop event, pass them, alonside the editor instance
            // to our "convertAndInsertDocx" function above if they're docx files.
            const files = event?.dataTransfer?.files || [];
            for (const file of files) {
                if (file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' && window.mammoth) {
                    convertAndInsertDocx(editor, file);
                }
            }
        });
    });
</script>

Request an Update

Hack not working on the latest version of BookStack?
You can request this hack to be updated & tested for a small one-time fee.
This helps keeps these hacks updated & maintained in a sustainable manner.


Latest Hacks