Is it possible to replace a word document loop tag for a new loop tag (DocxTemplater)?

24 views Asked by At

I want to replace some variable tags inside a Word Document using the DocxTemplater library. E.g. I have a loop tag as follows:

{#gid_123}
    ...content...
{/gid_123}

And I just want to replace the tags with new IDs:

{#gid_999}
    ...content...
{/gid_999}

I am able to replace expressions that are not loops, but I just cannot get the loop tags to be replaced even tho I am using a custom parser function.

My implementation looks as follows:

let doc = new DocxTemplater(zip, {
    paragraphLoop: true,
    linebreaks: true,
    parser(expression) {
        // The default regex is used to match the groups variables.
        let variablesRegex = /(?<type>gid)_(?<id>\d+)/g
        let variablesMatches = expression.match(variablesRegex) ?? []
        // If no group variables are found, the regex is changed to match the rest of the variables.
        if (variablesMatches.length === 0) {
            variablesRegex.lastIndex = 0
            variablesRegex = /(?<type>qid|tax|fee)_(?<id>\d+)(?:_(?<property>description|amount|percentage))?/g
            variablesMatches = expression.match(variablesRegex) ?? []
        }
        return {
            get: function (scope, context) {
                let newExpression = expression
                if (variablesMatches.length === 0)
                    return `{${newExpression.trim()}}`
                for (let match of variablesMatches) {
                    variablesRegex.lastIndex = 0
                    let {symbol = null, type, id, property} = variablesRegex.exec(match).groups
                    let newId = null
                    let newTag = null
                    let isTaxOrFee = ['tax', 'fee'].includes(type)
                    let isGroup = type === 'gid'
                    let isQuestion = type === 'qid'
                    // ?: tax, fee, qid (questions) and qid (question groups) are the only available variables to replace.
                    if (!isTaxOrFee && !isGroup && !isQuestion)
                        throw new Error(`Invalid variable type ${type}`)
                    if (isTaxOrFee) {
                        newId = tax_fee_id_relations.find(rel => rel.old_tax_or_fee_id === Number(id))?.tax_or_fee_id
                        newTag = `${type}_${newId}_${property}`
                    } else if (isQuestion) {
                        newId = question_id_relations.find(rel => rel.old_question_id === Number(id))?.new_question_id
                        newTag = `${type}_${newId}`
                    } else if (isGroup) {
                        let isOpeningTag = context.meta.part.raw.startsWith('#')
                        newId = group_id_relations.find(rel => rel.old_group_id === Number(id))?.new_group_id
                        // newTag = `${type}_${newId}`
                        newTag = isOpeningTag ?
                            `#${type}_${newId}` :
                            `/${type}_${newId}`
                    }
                    newExpression = newExpression.replaceAll(match, newTag)
                }
                return `{${newExpression.trim()}}`
            },
        }
    },
})

I have tried implementing a custom parsing method that identifies the tags I want to replace, creates the new tag and returns it inside the get() function, but that is just not working. The resulting document has blank spaces where the new loop tags should be.

I want to get a new document with the new tags for all the loops inside the document.

0

There are 0 answers