Intermittent JavaScript action bug - losing text somewhere in the process

I have an action that loops through the text in a draft, and where it finds an Apple message link (x-apple-reminder://XXXXXX) it replaces that line with a checklist item containing the reminder ID, so:

preamble
some text x-apple-reminder://95E7E03F-A0AC-4BCA-8E6A-361FBFC65B5F
and more

becomes

preamble
x-apple-reminder://95E7E03F-A0AC-4BCA-8E6A-361FBFC65B5F.
and more

About half the time, the action discards most of the text, leaving only the last checklist item. No other text, no other checklist items, etc.

If I paste the original text back in and run the same action again, after one or two tries, it works.

I’m not clear how this is happening – the script is very simple, and nothing asynchronous is going on. All on macOS, v19.2.0, by the way. The script:

const lines = draft.content.split(/\n/);
const outlines = [];

lines.forEach((line) => {
    const matches = line.match(/x-apple-reminder:\/\/(.+)/);

    if (matches) {
        outlines.push(`[ ] ${matches[1]}`);
    }
    else {
        outlines.push(line);
    }
});

draft.content = outlines.join("\n");

I just tried here and can’t get it to fail as you describe after a number of attempts.

Is it anything specific about the text of the draft, or how you are calling the action (from list, action bar, menu, etc.) when it fails?

No - that’s what’s baffling. The same text, pasted back into the same draft, will run successfully. And sometimes it works on the first try.

The drafts are created via AppleScript, but I’m not sure how that would affect anything.

I’m calling it from the Action list, always – sometimes while focused on the draft text; sometimes just selecting the draft in the Inbox. No difference.

Is there a way to see logging info that’s more than one line? I’ve tried scattering app.displayInfoMessage() around, to see when the text is getting lost – before the split, after, during the final join, or somewhere outside of the script; but there’s just the one line of info visible, and trying to select/copy dismisses it.

For debugging, good old alert("Message") calls are useful.

Dug into the initial draft text. It’s coming through with CRs instead of LFs. So we see it was one big line, and therefore reduce to one checklist item. I may have been wrong about its sometimes working properly.

Copying the text and pasting back in, we get LFs and the script works as expected.

The text was created by piping a command’s output through pbcopy, then

osascript -e 'tell application "Drafts"' \
  -e 'set theText to (the clipboard as text)' \
  -e '  make new draft with properties {content: theText, flagged: true}' \
  -e 'end tell'

which seems to deliver carriage returns. The pasteboard was filled by cat filename | pbcopy, where the filename file does contain LF-terminated lines.

Anyway, having the script match [\r\n] solves the problem. Not sure if should be considered a bug that drafts created this way appear normal, but actually have oddball line endings.

I’ll make a note to look into it. At least the mystery is solved for now.