Homelab, Linux, JS & ABAP (~˘▾˘)~

[JavaScript] Regex to check if string only contains the newline escape sequence \n

This is the first time ChatGPT actually helped me to solve a problem. So far the answers have not been so helpful with coding problems, but it seems to work very well with regex. I asked it to create me a regex pattern that checks if a string contains only the newline escape sequence \n and the answer was correct.

const test1 = '\n' //true
const test2 = '\n\n\n\n' //true
const test3 = 'test \n test' //false
const test4 = 'abcdefghij' //false
const test5 = ' ' //false

const myRegex = /^(?:\n)+$/

console.log('test1: ' + myRegex.test(test1))
console.log('test2: ' + myRegex.test(test2))
console.log('test3: ' + myRegex.test(test3))
console.log('test4: ' + myRegex.test(test4))
console.log('test5: ' + myRegex.test(test5))

[nodejs] Extract first page of a PDF using pdf-lib

const { PDFDocument } = require('pdf-lib')

// file = { fileName: 'test1.pdf, content: arraybuffer }     

const originalPdf = await PDFDocument.load(file.content, { ignoreEncryption: true })
const newPdf = await PDFDocument.create()
const [firstPage] = await newPdf.copyPages(originalPdf, [0]) // <-- 0 is the first page
const firstPagePdf = await newPdf.save()

file.content = Buffer.from(firstPagePdf)

[JavaScript] Check if iterator is undefined when using a for…of loop

Just saw this trick, how you can do a for…of loop which also checks if the iterator is null or undefined. Normally, you would check this by another if statement before starting the for..of loop, like here

const d = undefined

if (d) { 
  for (const x of d ) {

or by using a try...catch

try {
  for (const x of d) {
} catch (e) {
  console.error(e) // TypeError: undefined is not iterable

But instead of if or try...catch, you could use d || [], to check if d is Falsy, and if it’s false, no iterations are performed and no errors are thrown. The disadvantage of this approach is that you create an unneeded array and the readability may be poor depending on the situation.

for (const x of d || []) {

Of course, the first and the last snippet can also be done in one line

if (d) for (const x of d ) console.log(x) 

for (const x of d || []) console.log(x)

[nodejs] Merge PDFs using pdf-lib


const { PDFDocument } = require('pdf-lib')

// files = [{ fileName: 'test1.pdf, content: arraybuffer },{ fileName: 'test2.pdf, content: arraybuffer }]

mergePdfs: async function (files) {
        try {
            const mergedPdf = await PDFDocument.create()

            for (let file of files) {
                const pdf = await PDFDocument.load(file.content)
                const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices())
                copiedPages.forEach((page) => mergedPdf.addPage(page))

            const mergedPdfFile = await mergedPdf.save()
            const buffer = Buffer.from(mergedPdfFile)
            return await buffer.toString('base64') // return as buffer or base64 encoded file
        } catch (err) {

[PDF.js] Get PDF Viewer when it’s available in DOM and fully initialized


<iframe id="pdf-js-viewer" src="/pdf/web/viewer.html?file=" title="webviewer" frameborder="0" width="100%" height="700" allowfullscreen="" webkitallowfullscreen=""/>
            displayPdf: async function (id) { 
                const pdfArrayBuffer= await getPdf(id)
                const pdfViewerIFrame = await getPdfViewer()
                await pdfViewerIFrame.contentWindow.PDFViewerApplication.initializedPromise
                await pdfViewerIFrame.contentWindow.PDFViewerApplication.open(pdfArrayBuffer)

            getPdfViewer: function (id = 'pdf-js-viewer') {
                return new Promise((resolve, reject) => {
                    let pdfViewerIFrame = document.getElementById(id)
                    //if already loaded in DOM, return it
                    if (pdfViewerIFrame?.contentWindow?.PDFViewerApplication) {
                    } else {
                        //if not loaded yet, set up eventListener
                        document.addEventListener("webviewerloaded", async () => {
                            pdfViewerIFrame = document.getElementById(id)

This logic helped me to get the PDFViewerApplication in every situation correctly, for example when reloading the page with F5 or when having the PDF viewer already loaded and just wanting to open another PDF file.

[SAPUI5] Adding Lanes to a Process Flow

Manually adding Lanes to a Process Flow Control:


In my case, there was no way to bind the model to the view, so I did the mapping for each ProcessFlowLaneHeader in the callback function after reading the oData entity.


<flow:ProcessFlow id="process-flow"/>


var oProcessFlow = this.getView().byId("process-flow")

var oRequestFilter = new sap.ui.model.Filter({
    path: "myId",
    operator: sap.ui.model.FilterOperator.EQ,
    value1: myId

this.getView().getModel().read("/WorkflowSet", {
    filters: [oFormularIdFilter],
    success: (oData, response) => {
        for (var i = 0; i < oData.results.length; i++) {
            var oLaneHeader = new ProcessFlowLaneHeader({
                laneId: oData.results[i].LaneId,
                iconSrc: oData.results[i].IconSrc,
                text: oData.results[i].Text,
                position: oData.results[i].Position,
                state: [{state: oData.results[i].State, value: "100"}]
    error: oError => {
        sap.m.MessageToast.show("An error occured while reading entity /WorkflowSet.")