would it be possible to get a base64 encoding of an attachement? This would allow easy inclusion of images within custom widgets, especially html rendering.
Firstly, since you need to run JS, there is a hidden way to allow that in the renderhtml widget. Use the widget by choosing Custom URL option, and use the URL of https://gristlabs.github.io/grist-widget/renderhtml?tags=script. (The tags=script option allows <script> tags in the HTML to be rendered.)
Second is you need a fairly sophisticated formula that combines Python and Javascript. The one in the example is this:
setImageSrcScript = """
<script>
grist.docApi.getAccessToken({readOnly: true})
.then(tokenInfo => {
for (let img of document.querySelectorAll('img')) {
if (img.dataset.att) {
img.src = `${tokenInfo.baseUrl}/attachments/${img.dataset.att}/download?auth=${tokenInfo.token}`;
}
}
})
</script>
"""
return """
<div style="padding: 24px; background-color: #F4F0FF">
{setImageSrcScript}
<h1>{Company}</h1>
<p>Hello world!
{att}
</div>
""".format(
setImageSrcScript=setImageSrcScript,
Company=$Company,
att='\n'.join('<p><img data-att="{}" width="100%">'.format(att.id) for att in $Attachments)
)
The setImageSrcScript part is meant to be reusable with no changes in other such image-rendering formulas; it goes through all <img> tags with data-att attribute equal to the id of an attachment, and adds a suitable src tag for those.
As for a better approach, the problem with using base64 encoding in a formula to compute HTML that includes the full body of attachments is that it can produce very large formula results. Grist doesn’t handle those very efficiently. For a large table, it could quickly become a problem. I think a more promising approach would be an improvement to the HTML Viewer widget that automatically does something similar to what’s done by the setImageSrcScript above.