Electron Adventures: Episode 4: Image Gallery with Dynamic HTML
Let's do something a little more advanced with Electron - generate some HTML dynamically, and load it into the browser window.
There's no direct functionality for this, but we can use data:
URLs.
Load data URL into the web view
let { app, BrowserWindow } = require("electron")
let html = `
<!DOCTYPE html>
<html>
<body>
<h1>Welcome To The Internet!</h1>
</body>
</html>
`
function createWindow() {
let win = new BrowserWindow({})
win.maximize()
win.loadURL(`data:text/html;charset=utf-8,${encodeURI(html)}`)
}
app.on("ready", createWindow)
app.on("window-all-closed", () => {
app.quit()
})
ARGV parsing
Well, we managed to pass generated HTML, but it's not doing anything interesting yet.
Let's pick a directory to display images from. The way we run Electron apps, argv starts with electron
, .
, so only third arg is the image directory.
let imageDir
let argv = process.argv
if (argv.length >= 3) {
imageDir = argv[2]
} else {
imageDir = `${__dirname}/images`
}
For testing I included a folder with some US state flags in the repo, in images
.
We can check that this part worked, by displaying it in the browser:
let html = `
<!DOCTYPE html>
<html>
<body>
<h1>Image Gallery - ${imageDir}</h1>
</body>
</html>
You can run this either as:
$ npx electron . /path/to/images
$ npx electron .
Find all images in directory
We can use fs
and path
to get all the images in a directory.
let fs = require("fs")
let path = require("path")
let findImages = (dir) => {
let files = fs.readdirSync(dir)
files.sort()
return files
.filter(x => /\.(png|jpg|jpeg|gif)/i.test(x))
.map(x => path.join(dir, x))
}
Display images
We're almost there. Let's change the HTML to display the images. Also switching it all to dark mode, as I had enough of all white screen.
let html = `
<!DOCTYPE html>
<html>
<head>
<style>
body { background-color: black; color: white; }
img { padding: 10px; }
</style>
</head>
<body>
<h1>Image Gallery</h1>
${ findImages(imageDir).map(x => `<img src="file://${x}" />`).join("") }
</body>
</html>
`
Web security
This should work but it doesn't. Let's try to figure out why.
In Electron you can go to View menu and select "Toggle Developer Tools". Or use appropriate keyboard shortcut like Cmd-Option-I. You get all the usual Chrome debugging tools!
In this case we can see that our image requests were all blocked. This makes sense. Letting data:
URLs load arbitrary file:
URLs doesn't sound terribly safe.
As this is just a tutorial one-off, let's disable web security rules without thinking too much about the consequences of that.
function createWindow() {
let win = new BrowserWindow({webPreferences: { webSecurity: false }})
win.maximize()
win.loadURL(`data:text/html;charset=utf-8,${encodeURI(html)}`)
}
Electron app security is a big topic. If you're writing an Electron app, and not just a PWA, you likely do it because you need access to something the browser won't let you have. And if so, you're largely leaving browser's protection, and you're now responsible for security of your app.
Result
And here's what we got:
All the code for the episode is here.
See you in the next episode!