Can't show folder selection dialog in Electron - node.js

How can I show a folder selection dialog in NodeJS or ElectronJS?
Currently, I'm using nw-dialog:
const dialog = require('nw-dialog')
dialog.openFileDialog(function() {
alert('test')
})
However, I am getting an exception:
ReferenceError: document is not defined

nw-dialog is intended to be used with nw, not with Electron.
If you want to open dialogs in Electron, you should use Electron's dialog module:
const {dialog} = require('electron')
console.log(dialog.showOpenDialog({properties: ['openFile', 'openDirectory', 'multiSelections']}))

Related

How can i transpile a jsx file imported dynamically in nodejs?

I am currently working on a nodejs command-line package that should dynamically import a React component basing on the path of the component passed as parameter. My code is the following:
const path = require('path')
const pathArg = process.argv[2]
const componentPath = path.join(filePath, '../../../', pathArg)
const {default} = await import(componentPath)
The component i want to import would be something like
// src/components/Button/index.jsx
function Button () {
return <button>Click me!</button>
}
module.exports = Button
However, when i run my script passing src/components/Button/index.jsx as param, i receive unexpected token "<" while reading <button>, since the file is in jsx.
How can i transpile the React file dynamically (e.g. with Babel) and get rid of the error?

How to get SVG.JS 3.0.+ working with svgdom and node.js

SVG.js 3.0.5 has been released and i wanted to update my nodejs app, which is generating svgs using the library from 2.7 to 3.0.5.
To run this library with node.js you need to use svgdom (https://github.com/svgdotjs/svgdom)
The problem here is that the constructor changed and i can't figure out how to use it with node.js.
//previous method to initialize svgjs 2.7
const svgWindow = require('svgdom');
const SVGJS = require("svg.js")(svgWindow);
//with version 3.0.5 the package name changed
const svgWindow = require("svgdom");
const SVGJS = require("#svgdotjs/svg.js");
SVGJS(svgWindow); //is not a function error
I went through the source code and it looks like this should work
const window = require("svgdom");
const SVG = require("#svgdotjs/svg.js");
SVG.registerWindow(window, window.document);
I updated the readme so that it reflects the new use better:
npm install #svgdotjs/svg.js svgdom
// returns a window with a document and an svg root node
const window = require('../svgdom')
const document = window.document
const {SVG, registerWindow} = require('#svgdotjs/svg.js')
// register window and document
registerWindow(window , window.document)
// create canvas
const canvas = SVG(document.documentElement)
// use svg.js as normal
canvas.rect(100,100).fill('yellow').move(50,50)
// get your svg as string
console.log(canvas.svg())
// or
console.log(canvas.node.outerHTML)
Please note, that svg.js v3 does not export this big object anymore. Instead you have to require the functions you need. More information in the readme: https://github.com/svgdotjs/svgdom

Export table data to excel from server side in nodejs

I am using json2xls npm, here is my code below:
exports.exportContactsXlsx = function (req, res) {
var data = req.body;
var xls = json2xls(data);
fs.writeFileSync('data.xlsx', xls, 'binary');
}
After clicking export button, successfully i got "data.xlsx" file, but when i hit Export button in UI, i want to get that data.xlsx is downloading in bottom left corner of chrome browser.
How to do that?
To setup a download link, on your anchor tag use the download attribute, and the src will be downloaded in the bottom corner

Electron PDF viewer

I have an Electron app that loads URL from PHP server. And the page contains an iFrame having a source to PDF. The PDF page seems absolutely ok in a normal web browser but asks for download in Electron. Any help?
My codes for html page is
<h1>Hello World!</h1>
Some html content here...
<iframe src="http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf" width="1200" height="800"></iframe>
And my js code is something like
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
app.on('ready', createWindow)
Any help would be really greatful...
Electron is shipping already with an integrated PDF viewer.
So you can load PDF files just like normal HTML files, the PDF viewer will automatically show up.
E.g. in BrowserWindow with .loadURL(…), in <iframes>, <object> and also with the, at the moment discouraged, <webview>.
PS: The need to enable the plugins property in the BrowserWindow or <webview> is no more needed since Electron 9.
You will need
https://github.com/gerhardberger/electron-pdf-window
Example:
const { app } = require('electron')
const PDFWindow = require('electron-pdf-window')
app.on('ready', () => {
const win = new PDFWindow({
width: 800,
height: 600
})
win.loadURL('http://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf')
})
This answer will focus on implementation with Angular.
After year of waiting (to be solved by the Electron) finally I decided to apply a workaround. For the people who needs it done, here it goes. Workaround comes with a cost of increasing bundle size totally 500K. (For Angular)
Workaround to use Mozilla PDF.js library.
NPM
GitHub
Implementation 1 (Setting nodeIntegration: true)
This implementation has no issue, you can implement by the document of the library mentioned. But if you run into additional problem like creating white window when route is changed, it is due to the setting nodeIntegration property to true. If so, use the following implementation.
Implementation 2 (Setting nodeIntegration: false)
This is the default by Electron. Using this configuration and viewing the PDF is bit tricky. Solution is to use Uint8Array instead of a blob or base64.
You can use the following function to convert base64 to Uint8Array.
base64ToArrayBuffer(data): Uint8Array {
const input = data.substring(data.indexOf(',') + 1);
const binaryString = window.atob(input ? input : data);
const binaryLen = binaryString.length;
const bytes = new Uint8Array(binaryLen);
for (let i = 0; i < binaryLen; i++) {
const ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes;
}
Or convert blob to array buffer
const blob = response;
let arrayBuffer = null;
arrayBuffer = await new Response(blob).arrayBuffer();
then pass the generated Uint8Array as the pdfSource to the ng2-pdfjs-viewer.
HTML
<ng2-pdfjs-viewer zoom="100" [pdfSrc]="pdfSource"></ng2-pdfjs-viewer>
Electron 9.0.0 has enabled PDF viewer already.
npm install electron#9.0.0

Does express.js have the concept of a home directory?

I have an express project where I have a directory structure like so,
my-app
routes
index.js
views
public
components
toolbar
test
components
toolbar
Now let's say from my routes I want to require the component toolbar I do it like this
toolbar = require(__dirname + '/../components/toolbar')
Now when I run my test for routes I need to require routes. When I do this I get an error at runtime that toolbar file could not be found.
Is there some global available like say __express_home that I could use in my require so that I would not run into this issue? I would then use it as so,
toolbar = require(__express_home + '/components/toolbar')
You can just do:
toolbar = require('../components/toolbar')
Here is an example from express's github repo.
var express = require('../..')
, app = express()
, site = require('./site')
, post = require('./post')
, user = require('./user');
just use a relative path from wherever you are require() it.
./routes/index.js
./config.js
from ./routes/index.js
var cfg = require('../config');

Resources