Skip to content

[WIP] Brew Scripts, a new tab for scripts that is specifically targeted to manipulating CSVs and modifying brew text#4881

Draft
ReinaSweet wants to merge 37 commits into
naturalcrit:masterfrom
ReinaSweet:scripteditor
Draft

[WIP] Brew Scripts, a new tab for scripts that is specifically targeted to manipulating CSVs and modifying brew text#4881
ReinaSweet wants to merge 37 commits into
naturalcrit:masterfrom
ReinaSweet:scripteditor

Conversation

@ReinaSweet

@ReinaSweet ReinaSweet commented Jun 25, 2026

Copy link
Copy Markdown

Description

Adds a new feature that allows user to author small scripts that can modify their brew.
The primary functionality for this is CSV manipulation and templating from it.

How to use

There's a new tab that lives near snippets with editable javascript.
Names for scripts must appear after \script
Everything on other lines is evaluated as javascript.
Scripts Tab

Once a script is authored, it's available in a menu near snippets. This is currently stuffed into a larger header called "This Brew" (this is intended to be changed later).
This Brew

Clicking this runs the script!
Executed Script

get functions in the API rely on a Promise-like interface. They also require a more quarantined set of interactions for certain get functions:
get function interface
From File Request

In the specific case above, the csv was a large math scratch sheet. The user could of manipulated this into place instead.
Stringified JSON

Errors are displayed over the editor. This is especially important for the sanitized api functions, which aim to prevent data injection. For example, if we tried to send the JSON block as is instead of as a string, we would've an invalid type error:
Error for invalid type

Significant Technical Details

The concept of scripts are fraught with, extremely valid, worries of XSS. Much of the implementation nuance was spent in providing multiple layers of security against that. In order:

  1. Brew Scripts are never ran or processed until explicitly requested by the user (who must be an author of the page)
  2. Brew Scripts are executed from a worker with all credentials stripped and asset requests denied. e.g. fetch() doesn't work.
  3. All API functions are double validated for both input types and number on both the worker side and host client side. Only strings and the occasional number are allowed through.
  4. Functions that deemed higher risk require an additional user input to be committed to.
  5. The worker's lifetime has a strict limit enforced by the host client and not the worker itself, to prevent intentional stalling or resource over-consumption.
  6. To avoid phishing text in the drop downs especially, all strings that result in user displayed text in anything but the brew itself are either controlled by the host client or are scrubbed to remove anything key details that make them appear like a link.

API Functions

  • doReplaceBetween(start:String, end:String, text:String)
  • doReplaceSelected(text:String)
  • doInsertAfter(target:String, text:String)
  • doAppendToStart(text:String)
  • doAppendToEnd(text:String)
  • doReportError(message:String, stack?:String)
  • getBetween(start:String, end:String)
  • getSelected()
  • getCSVFromFile(message?:String)
  • getCSVFromSheets(sheetsId:String, gid:Number, message?:String)

Known Development TODO

  • Finish full battery of XSS testing
  • Address the "This Brew" and resolve what that menu looks like, especially with consideration of outside themes
    • /new/ page should just have scripts disabled until you save
  • Potential api additions
    • getInputNumber
    • getInputButtons

ReinaSweetSprocket and others added 30 commits June 6, 2026 23:48
First checkin with a functioning user scripts. Lives very close to snippets. Allows executing scripts (plain javascript) with a limited api to manipulate the brew text. Useful for doing things such as pulling from a csv. Various API functions are stubbed out.
Instead of working through a chain of React props, now talks directly to the editor. And the API itself lives in its own file, to be converted to a React Class later (with the dangling snippetUploadFile, which is still to be extracted).
Prevents onload script attacks and has a nice benefit of only seeing parse errors on execute.
Error is wrapped in try-catch so that we can override it later.
…te list

File uploading is the most awkward part of this, so feeding it through a dialog for now.
Don't let script requests to sit and block the termination of a worker.
Script requests will go away after 60 seconds and prevent further requests. Entire worker goes away 10 seconds later (preventing case where a user late clicks the request from not having enough time to actually process).
Errors are still persisted even after the worker dies.
@calculuschild

Copy link
Copy Markdown
Member

Just as a note so we can be clear in our expectations: as was discussed in the Gitter chat, I think it will be highly unlikely that the Homebrewery will ever support user-authored scripting. Even with sandboxing, this introduces a large and ongoing security surface for a very niche workflow, and it pushes the project outside its intended scope.

The Homebrewery is deliberately a Markdown‑to‑HTML tool, not a data‑processing or templating engine, and features like CSV manipulation or custom script execution tread into a territory that feels like it would be better suited to an external tool (or a specialized fork). For example there are other sites out there that read from JSON input for D&D Monsters (from the SRD, etc.), have a GUI to customize the values, and then emit Homebrewery-compatible Markdown. We just have to be somewhat selective in accepting new features into the Homebrewery itself if we want to keep the it focused and purposeful about what it provides.

If there is a specific use case for importing CSVs that you have in mind, it would be helpful to open an issue describing that root question so we can evaluate whether there’s a simpler, non‑scripting solution that fits the project’s goals, and have a record of any decisions.

@dbolack-ab

Copy link
Copy Markdown
Collaborator

While I am not in favor of this feature, if integrated, the scripts should be part of the Brew Snippets structure as to properly mimic the Static Theme snippets,

@ericscheid

Copy link
Copy Markdown
Collaborator

While I am not in favor of this feature, if integrated, the scripts should be part of the Brew Snippets structure as to properly mimic the Static Theme snippets,

Indeed. Though some of the built in snippets only insert static text, some go further and insert the results of running a script (e.g. TOC).

@ReinaSweet

Copy link
Copy Markdown
Author

While I am not in favor of this feature, if integrated, the scripts should be part of the Brew Snippets structure as to properly mimic the Static Theme snippets,

Would you be able to clarify what you mean by this? Do you mean specifically for the UI, for the Editor page, and/or for how the brew is stored (i.e. the yaml file)? Or something else?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

5 participants