guigrpa / docx-templates

Template-based docx report creation
MIT License
882 stars 145 forks source link

[Question / Suggestion] Case sensitive placeholders #333

Open MatthieuGC opened 11 months ago

MatthieuGC commented 11 months ago

Hi there !

I'd like to know if there is a way to handle upcased placeholders. I currently run into an error for unrecognised command. e.g. {{FOO.BAR}} isn't understood as {{foo.bar}}

Context: Customers can generate template themselves. Some of them mess around and send documents with upcased placeholders.

I didn't find an option like: caseSensitive: false which could be useful imho 🤷‍♂️ .

Any idea ? Thanks !

jjhbw commented 11 months ago

Hah, I have the same problem... Why can't those pesky customers just do it right?? 😂 Haven't gotten around to implementing a solution yet, though.

Core of the problem is that everything between the command delimiters is essentially javascript syntax interpreted by a javascript VM. It is case sensitive to the extent that javascript is...

One solution would be to lowercase both the keys of the provided data object and each command before interpretation. This is not as trivial as it sounds, though, because commands can contain arbitrary javascript that cannot just be lowercased and expected to work correctly.

If you're just worried about ALL CAPS or all lowercase commands (and don't care about mixed-case commands) you could just create copies for all keys in your data object to have both lowercase and uppercase versions.

Let me know if you think of something, though.

MatthieuGC commented 11 months ago

I didn't really wanted to duplicate each of my values since it represent A LOT of values and it can be deep so I'm currently trying a workaround using a custom error handler :

createReport({
  ...,
  errorHandler: (err, command_code) => {
    if (err instanceof ReferenceError) {
      const args = command_code?.toLowerCase().split('.')
      const value = args?.reduce((acc, curr) => acc?.[curr], data)

      if (value) return value
      else throw err
    } else {
      throw err
    }
  }
)