Execute JavaScript in Custom HTML Prompt – Why No Variable Processing?

@peternlewis - I want to first make sure I'm right about my assumption: In an "Execute JavaScript in Custom HTML Prompt" action, it appears that I have to hard-code the JavaScript that gets executed. I can't supply the script using variables, which means I can't build the script on the fly. I'm pretty sure I'm right about this, but if I'm wrong (and I'd love to be wrong), please let me know.

And I know this part, from the Wiki:

The JavaScript can access variables by using the window.KeyboardMaestro functions described in the Custom HTML Prompt action.

That helps, but it's not the same as building the javascript on the fly.

I'm currently getting around this by using some JXA code to build an "Execute JavaScript in Custom HTML Prompt" action, complete with my on-the-fly javascript code, and then using the engine's doScript() to run the action. This works fine, and I was thinking of posting a generic version that people can use to build their scripts on the fly.

But I was wondering why KM's action doesn't let you build the script on the fly? (In other words, it doesn't "process variables"). Is there a technical reason for it? And more importantly, is there a technical reason why I shouldn't be building it on the fly like I am?

Thanks.

There doesn't appear, at first sight, to be any obvious obstacle to evaluating code passed in as a Keyboard Maestro variable.

For example, defining the function f below in terms of the localCode variable, seems to work:

<html>
<head/>
<body>
<div/>
<script>
(() => {
    const km = window.KeyboardMaestro;
    
    km.SetVariable("localTemp", "Beta");

    const f = new Function(
        `return ${km.GetVariable("localCode")}`
    )

    document.querySelector("body > div")
    .innerHTML = [
        `<p>At launch: ${document.kmvar.localTemp}</p>`,
        `<p>Later on: ${km.GetVariable("localTemp")}</p>`,
        `<p>Evaluating a code variable: ${ f() }<p>`
    ].join("\n");
})()
</script>
</body>
</html>

Screenshot 2021-12-27 at 23.13.21

Executing code in KM variables.kmmacros (2.5 KB)

Footnote: the return expression could, of course, be placed at either end.

One variant might be:

followed by:

<html>
<head/>
<body>
<div/>
<script>
(() => {
    const f = new Function(
        `${window.KeyboardMaestro.GetVariable("localCode")}`
    )

    document.querySelector("body > div")
    .innerHTML = "<p>Evaluating a code variable:  "  + f() +  "<p>";
})()
</script>
</body>
</html>

Or stripping it back a bit:

<html>
<head/>
<body>
<div/>
<script>
Function(
    `${window.KeyboardMaestro.GetVariable("localCode")}`
)()
</script>
</body>
</html>

with:

image

IV Executing code in KM variables copy.kmmacros (2.0 KB)

1 Like

That is correct. Essentially token substitution never happens within code, which includes HTML.

You can use the file variant of the Custom HTML Prompt action, and write your variable to a file in the preceding action.

If there was an option to read the entire HTML from a variable, that would be reasonable, its just not done (and probably never will be). But processing tokens within code, which itself frequently uses percents to mean something, as well as typically requiring appropriate quoting etc, means it will cause problems far more often than work reliable, and those problems will likely depend on the inputs which change over time, so it would likely work in testing and then fail later when one of those inputs includes a quote or percent character you aren't expecting.

But there is nothing wrong with generating the full HTML and then executing that. Currently the easiest way to do that is via a file.

3 Likes