39
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.
(I had to change all references to data
URLs in code to da+ta
as dev.to crashes if I use actual code; link to the actual code at the end of the post)
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(`da`+`ta:text/html;charset=utf-8,${encodeURI(html)}`)
}
app.on("ready", createWindow)
app.on("window-all-closed", () => {
app.quit()
})
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 .
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))
}
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>
`
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(`da` + `ta: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.
And here's what we got:
See you in the next episode!
39