When I add images to podfeet.com for blog posts, I use my blogging software of choice, MarsEdit. I just drag an image into the text of a post, and MarsEdit does all the formatting automatically, and uploads it to my server and links it up. On occasion I want to upload a different kind of media and then I have to do things by hand.
Take last week when I played an audio excerpt of my AI voice from early 2023 created by Eleven Labs. To make this available to you for playback from within the blog post, I had to go through some manual gyrations. First, I launched my FTP client of choice, Transmit from Panic. I have a bookmark in Transmit to the folder on my server where uploaded media belongs. All of the images and this audio file go into blahblahblah/uploads/year/month.
I dragged the audio file up to blahblahblah/uploads/year/month, which made available to link within a blog post. The problem is that I don’t have memorized what the URL would be for this file. I called the folder blahblahblah/uploads/year/month on purpose because blahblahblah is the problematic part.
I can right-click on the file in Transmit that I’ve just uploaded and it offers to copy the URL. Unfortunately, Transmit doesn’t know about my website, it knows where the file is on my server. WordPress takes these files on my server and builds a website, but Transmit doesn’t know anything about that. So if I copy the URL from Transmit, it doesn’t even start with https://
. It starts with sftp://
for secure FTP. The sftp://
is followed by the IP address of my server, not the name of my website. There are a few more annoying folders in the URL from Transmit that only someone who works on web servers would appreciate, //srv/websites/podfeet/public_html
.
sftp://138.68.36.215//srv/websites/podfeet/public_html/blog/wp-content/uploads/2024/10/somefile.mp3
After all of the server glop information, the rest of the URL is actually helpful to determine the location of the URL on the website: /blog/wp-content/uploads/2024/10/somefile.mp3
. Might sound like nonsense to you, but if you right click on any media on my website, it will have that same info.
The beginning server glop, sftp://138.68.36.215//srv/websites/podfeet/public_html
needs to be replaced with https://www.podfeet.com
.
https://www.podfeet.com/blog/wp-content/uploads/2024/10/somefile.mp3
Now that I explain it, it really isn’t all that hard to fix the URL so I can plop it into a blog post, but it’s hard to remember. I’ve been doing this for 19+ years and just last week I had to go study an old embedded file to figure it out yet again.
Bart and I noodled the problem a little bit and we came to the conclusion that a JavaScript string replace script embedded in TextExpander might make my life easier. My goal was to be able to right click on the file I’ve uploaded to Transmit, choose Copy URL, and then use a TextExpander snippet to paste and it would be in the web server-friendly format.
While I call myself a developer, my JavaScript has gotten rusty from misuse. I recently decided to start paying for ChatGPT 4o, so I thought I’d ask for a wee bit of assistance in writing the script. Spoiler, in a small handful of conversational interactions with ChatGPT, I have a working TextExpander script. I want to walk through it as a way to illustrate what I mean by conversational, and how you have to hone your question to get the right answer.
Here’s the conversation.
My initial query went like this.
Starting with the first text string, write a JavaScript script that strips off the front matter and changes it to the second string.
I then gave it the sftp
server location of the file, and the https
webserver URL with which I wanted it replaced. I used a specific example for this first foray. ChatGPT assigned variable names to the first string, and then defined the second string as the first string but replacing that front matter with the front matter from the second string. In other words, it said to just replace the sftp
glop with the https
glop. It then plopped the second string into a console command to print it out.
let firstString = 'sftp://138.68.36.215//srv/websites/podfeet/public_html/blog/wp-content/uploads/2024/10/elevenlabsdotiofrommarch2023.mp3';
// Replace the front part with the desired base URL
let secondString = firstString.replace('sftp://138.68.36.215//srv/websites/podfeet/public_html', 'https://www.podfeet.com');
console.log(secondString);
This is a classic case of a computer doing exactly what you asked it to do, not what you meant to ask it to do! Since ChatGPT has memory of the continuing conversation I was able to adjust my query by saying:
I need this to be generic. The first text string will be in the clipboard and the front matter will always be: sftp://138.68.36.215//srv/websites/podfeet/public_html/blog/wp-content/uploads/ which always needs to be replaced with: https://www.podfeet.com/blog/wp-content/uploads/
ChatGPT happily answered,
Here’s a JavaScript script that works generically, assuming you are reading the first text string from the clipboard. This script will always replace the specific front matter you mentioned:
The new script was only slightly more complicated. Since I told it I was starting with something in the clipboard, it helpfully put the final URL into the clipboard for me.
// Replace the front matter of the clipboard contents with the desired base URL
navigator.clipboard.readText().then((firstString) => {
// Define the front matter to be replaced
let frontMatter = 'sftp://138.68.36.215//srv/websites/podfeet/public_html';
// Define the replacement string
let newBaseURL = 'https://www.podfeet.com';
// Replace the front matter in the clipboard content
let secondString = firstString.replace(frontMatter, newBaseURL);
// Output or use the modified string (example: log it to console)
console.log(secondString);
// Optionally, copy the result back to the clipboard
navigator.clipboard.writeText(secondString).then(() => {
console.log("New URL copied to clipboard: " + secondString);
});
});
One of the helpful features of ChatGPT is that it not only gives you the code, it also explains how it works.
- It reads the current clipboard content using
navigator.clipboard.readText()
.- It replaces the front matter (
sftp://138.68.36.215//srv/websites/podfeet/public_html`) with the new URL (
https://www.podfeet.com`).- It logs the new string to the console, and optionally, it writes the modified URL back to the clipboard using
navigator.clipboard.writeText()
.
Now we’re getting somewhere. I created a new snippet in TextExpander, changed the text format to JavaScript, and splatted in the code ChatGPT gave me. I tried the snippet, but it threw an error. Rather than try to figure it out myself, I added to my conversation with ChatGPT:
“This throws the following error: JavaScript Error: TypeError - undefined is not an object (evaluating 'navigator.clipboard.readText')"
Notice that I didn’t ask it a question, I just told it about the error. ChatGPT simply explained why it didn’t work:
The error you’re encountering is because navigator.clipboard.readText() is part of the Clipboard API, which only works in secure contexts (i.e., over HTTPS) and in certain browser environments. If you’re running this outside of such an environment, you can use a different approach to access clipboard data depending on the platform.
Well that’s interesting. It went on to explain how I could fix the problem by installing a package through the node package manager, but I figured this could be solved more simply and elegantly if I just gave ChatGPT the information I should have given it in the first place. You see, I never told ChatGPT that I wanted this to run inside TextExpander. Once I told ChatGPT the context, it splatted out a new set of code for me.
(() => {
// Define the front matter to be replaced
let frontMatter = 'sftp://138.68.36.215//srv/websites/podfeet/public_html';
// Define the replacement string
let newBaseURL = 'https://www.podfeet.com';
// Get the clipboard content
let app = Application.currentApplication();
app.includeStandardAdditions = true;
let firstString = app.theClipboard();
// Replace the front matter in the clipboard content
let secondString = firstString.replace(frontMatter, newBaseURL);
// Output the modified string
return secondString;
})();
How this works:
- It uses JXA (JavaScript for Automation), which is supported in TextExpander snippets.
- app.theClipboard() grabs the current clipboard contents.
- It replaces the specified front matter with the new URL.
- The result is returned and can be inserted by TextExpander.
You can paste this script into a TextExpander snippet that runs JavaScript, and it will transform the URL when expanded.
I copied the new code, splatted it into a TextExpander snippet, and assigned an abbreviation to trigger it. I opened Transmit, copied the URL of a file, and then pasted into a text editor and there was my happy web-friendly URL.
Lessons Learned
I haven’t made fire here or anything. Lots of people have been using ChatGPT for coding for quite some time now. But I wanted to walk through the experience to stimulate you to think about the lessons learned.
- I was able to save myself a lot of time in creating the JavaScript/TextExpander snippet using ChatGPT
- Because I used ChatGPT, I didn’t actually learn how to do it myself
- If I thought ahead and made my initial query more specific I could have gotten to the right answer more quickly
- Perhaps it was quicker though to let ChatGPT highlight the problems in my query so maybe it was quick enough?
- Being able to have a conversation including memory with a large language model (LLM) is the dream we’ve always had of how a digital assistant should be able to help us
- Having access to ChatGPT makes coding more accessible to the novice, and can speed up laborious typing of code even for the accomplished programmer
A lesson we’ve probably all learned by now is that you have to test and verify whatever ChatGPT tells you. This really isn’t all that different from getting an answer from a human on the web though, is it? You want to study and understand what you’re being told no matter the source.
I’m sure my perspective will rankle some folks. If you’re one of those people, I hope you’ll tell me where you think I’ve gone astray. I truly welcome the discussion because we’re all figuring this out right now.