Using docx.js in electron - issue over instantiating Document etc - javascript

I'm trying to use docx in the latest version of electron. I've used the docx library in an older version of electron and it works fine.
I install docx in the electron project using: npm install docx
I am using the following code:
<script>
const { Document, Paragraph, Packer, Table } = require('docx');
const fs = require('fs');
const index_document = new Document();
const table = new Table({
rows: 50,
columns: 3,
width: { size: 100, type: TableWidthType.PERCENTAGE },
});
table.getColumn(0).setWidth(20);
table.getColumn(1).setWidth(60);
table.getColumn(2).setWidth(20);
table.getCell(0, 0).addContent(new Paragraph("#"));
table.getCell(0, 1).addContent(new Paragraph("Document Description"));
table.getCell(0, 2).addContent(new Paragraph("Page No"));
for (let i = 1; i <= 50; i++) {
table.getCell(i, 0).addContent(new Paragraph(i.toString()));
table.getCell(i, 1).addContent(new Paragraph("Document Description " + i));
table.getCell(i, 2).addContent(new Paragraph("Page No " + i));
}
index_document.addTable(table);
const packer = new Packer();
packer.toBuffer(index_document).then((buffer) => {
fs.writeFileSync("table.docx", buffer);
console.log("Document created and saved!");
});
</script>
However, this throws the following error:
Uncaught TypeError: Cannot read properties of undefined (reading 'creator')
at new Ho (C:\Users\user\Desktop\electron-app\node_modules\docx\build\index.js:2:308022)
at index.html:277:24
This appears to be an issue within the docx index.js (version 7.8.2) itself but I am not sure what the issue is. Can anyone identify what the problem is?

Related

Get desktop file icons using NodeJs

I am trying to create a desktop launcher application in Electron that reads the number of files in the user's desktop and gathers the information from each file found. I am gathering the files and constructing the path based on the directory, but all I can get is the filenames. I am not sure how to store the file itself and extract the desktop icon from it. I haven't seen many solutions to it, other than using the AxtiveXobject however supposedly certain implementations do not work in the latest nodejs. Here is my code so far.
//requiring path and fs modules
const path = require('path');
const fs = require('fs');
//gets home directory
const homedir = require('os').homedir();
//specifies to desktop
const dir = `${homedir}/Desktop`;
var walk = require('walk');
var filepaths = [];
//storing desktop path
var desktopDir = dir;
console.log(desktopDir);
//gets the desktop files and paths
function getDesktopFiles(_dir){
//read directory
fs.readdir(_dir, (err, files) => {
if (err)
console.log(err);
else {
files.forEach(_file => {
//console.log(_file);
let _p = _dir + '/'+_file;
//changes slashing for file paths
let _path = _p.replace(/\\/g, "/");
filepaths.push(_path);
})
}
})
for(let p of filepaths){
console.log(p);
}
}
getDesktopFiles(desktopDir);
Here is a quick snippet of code which works for me in an Electron renderer process; it has been successfully tested on both macOS and Linux, and should be platform-independent.
It lists all the files located on the user's desktop and displays each file's icon and name at the end of the HTML page; it makes use of the following Electron API functions:
app.getPath
app.getFileIcon
image.toDataURL
image.getSize
const { app, nativeImage } = require ('electron').remote;
const path = require ('path');
const fs = require ('fs');
//
const desktopPath = app.getPath ('desktop');
let filePaths = fs.readdirSync (desktopPath);
for (let filePath of filePaths)
{
app.getFileIcon (filePath)
.then
(
(fileIcon) =>
{
let div = document.createElement ('div');
let img = document.createElement ('img');
img.setAttribute ('src', fileIcon.toDataURL ());
let size = fileIcon.getSize ();
img.setAttribute ('width', size.width);
img.setAttribute ('height', size.height);
div.appendChild (img);
div.appendChild (document.createTextNode (" " + path.basename (filePath)));
// For test purposes, add each file icon and name to the end of <body>
document.body.appendChild (div);
}
);
}
You may find some interesting hints about app.getFileIcon in the post: Is there a standard way for an Electron or Node.js app to access system-level icons?
Define a function for the same as:
function load(icon) {
if (cache[icon]) return cache[icon];
return cache[icon] = fs.readFileSync(__dirname + '/public/icons/' + icon, 'base64');
}
Here you can get the inspiration for the same.

How to read the zip file contents in react application using jszip preferably

I have a requirement to read the zip file contents , This is how the zip folder will look like Manifest.zip , The files in the Manifest.zip are outline.png, publish.png, manifest.json. I need to read the manifest.json(key value pairs) on the fly in a react application.
Basically requirement is when user clicks on "maifest" link a pop up needs to shown which show manifest.json contents in the UI react components.
I tried using JSZip library, and the code is as below
var zip = new JSZip();
zip.loadAsync("Manifest.zip")
.then(function (zip) {
console.log(zip.files);
// Expected outline.png, publish.png, manifest.json
});
I get the error as shown below?
Don't know what the error is about, have you tried another zip file?
Anyway, here is my tsx code with reactjs hooks:
const [files, setFiles] = useState<File[]>(undefined);
const [fileInfo, setFileInfo] = useState<IFileInfo>(undefined);
useEffect(() => {
if (files) {
const f = files[0];
const dateBefore = new Date();
JSZip.loadAsync(f) // 1) read the Blob
.then((zip) => {
const contents = [];
zip.forEach((relativePath, zipEntry) => { // 2) print entries
contents.push(zipEntry.name);
});
const loadTime = moment(new Date()).diff(moment(dateBefore));
setFileInfo({
loadTime,
contents: contents.sort(),
error: null
});
}, (e) => {
const loadTime = moment(new Date()).diff(moment(dateBefore));
setFileInfo({
loadTime,
contents: [],
error: "Error reading " + f.name + ": " + e.message
});
});
}
}, [files]);
// below some code that adds a file to files with drag and drop interface
Take a look at this library. Seems stable and easy to use.
var AdmZip = require('adm-zip');
// reading archives
var zip = new AdmZip("./my_file.zip");
var zipEntries = zip.getEntries(); // an array of ZipEntry records
zipEntries.forEach(function(zipEntry) {
console.log(zipEntry.toString()); // outputs zip entries information
});

IONIC 3 filePath (native path) issue in case of PDF or DOC files

I am trying to choose pdf of doc files using fileChooser plugin of IONIC 3 and I am getting the response like this
content://com.coloros.filemanager/file_share/storage/emulated/0/documents/certificatenew.pdf
then I am trying to get the native path in android devices using filePath plugin of IONIC 3 but I am getting an error like this
column '_data' does not exist
I am getting this issue in Android Naugat and Oreo. Also, getting the native path of the image file using the same process, working just fine.
The following is the part of the code,
.......
this.fileChooser.open().then((url) => {
this.filePath.resolveNativePath(url)
.then(filePath => {
let currentPath = filePath.substr(0, filePath.lastIndexOf('/') + 1);
let currentName = filePath.split('/')[filePath.split('/').length - 1];
let fileext = currentName.split(".").pop();
var d = new Date(),
n = d.getTime(),
newFileName = n + '.' + fileext;
.......
Can anyone tell me what to do? and what is the reason behind it?
This code is working for me,
this.fileChooser.open()
.then(
uri => {
this.filePath.resolveNativePath(uri)
.then(file => {
this.fileDir = file;
this.fileName = file.substring(file.lastIndexOf("/") + 1);
})
.catch(err => console.log(err));
}
)
.catch(error => {
this.showError(error);
});

Node.js - Cannot read property 'toString' of null when running package on Windows

I am using the gulp and hercule package on node.js to transclude some plain text files. On Unix, everything seems to work fine. However, some coworkers are having issues running it on Windows. They are getting the following error message only when running on Windows:
[13:02:01] TypeError: Cannot read property 'toString' of null at Object.transcludeStringSync (D:\project\node_modules\hercule\lib\hercule.js:136:36)
I have tried the above with hercule#3.0.5 as well as hercule#2.0.5, and both packages give the above error. However, given that this occurs only on Windows and across many versions of the package, I suspect this issue has something to due with the Node.js installation or path.
The code that is using the hercule package:
var fs = require('fs');
var path = require('path');
var gulp = require('gulp');
var drakov = require('drakov');
var hercule = require('hercule');
gulp.task('mock', ['i18n','build_minify_no_tests'], function() {
var mockSpecificationTemplate= fs.readFileSync('test/mock/mock-template.apib','utf8');
var transcludedMockSpecification = hercule.transcludeStringSync(mockSpecificationTemplate, {
relativePath: path.resolve('../../../')
});
fs.writeFileSync('test/mock/mock.apib', transcludedMockSpecification, 'utf-8');
// Running mock server
var drakovArgv = {
sourceFiles: 'test/mock/mock.apib',
serverPort: 9000,
staticPaths: [
'../../'
],
discover: true,
watch: true
};
drakov.run(drakovArgv);
});
node and npm version information:
$ node -v
v6.3.0
$ npm -v
3.10.3
hercule.transcludeStringSync simply runs another hercule process and sends input to it:
const result = childProcess.spawnSync('../bin/hercule', syncArgs, syncOptions);
with the script ../bin/hercule:
#!/usr/bin/env node
"use strict";
require('../lib/main.js');
...obviously doesn't work on Windows
If that task must be synchronized, you may use the following function instead:
function transcludeStringSync(input, options) {
const {dirname, join} = require('path')
const hercule = join(dirname(require.resolve('hercule')), 'main')
const args = [hercule, '--reporter', 'json-err']
for (let name in options) {
args.push(`--${name}`, `--${options[name]}`)
}
const result = require('child_process').spawnSync('node', args, {input})
const err = result.stderr.toString()
if (err) throw new Error('Could not transclude input')
return result.stdout.toString()
}

Check Cordova Version from Javascript

Is there any way to check from Javascript what version of Cordova an app is running?
Why I ask:
We've upgraded our Cordova from 2.8 to 4.0.2 and the new Cordova JS file does not work with the old Cordova Android code. We want to force the user to upgrade their app (to in turn update their Cordova Android version), however, we need to detect that they're on the old version first.
Why device.cordova won't work:
It seems that the old Cordova JS code never initializes because it can't communicate with the new Cordova Android code. So the plugins, such as the device plugin are never loaded. We get a message in the console stating:
deviceready has not fired after 5 seconds
EDIT: now the simplest solution is this:https://stackoverflow.com/a/65476892/1243247
Manual way
I made a functional hook script which I stored at hooks/setVersion.js. I just tested it now and it works (just in Android, for iOS you just need to replicate the wwwDir)
#!/usr/bin/env node
var wwwFileToReplace = 'index.html'
var fs = require('fs')
var path = require('path')
module.exports = function (context) {
var projectRoot = context.opts.projectRoot
const wwwDir = path.join(projectRoot, 'platforms', 'android', 'app', 'src', 'main', 'assets', 'www')
var configXMLPath = 'config.xml'
loadConfigXMLDoc(configXMLPath, (rawJSON) => {
var version = rawJSON.widget.$.version
console.log('Version:', version)
var fullfilename = path.join(wwwDir, wwwFileToReplace)
if (fs.existsSync(fullfilename)) {
replaceStringInFile(fullfilename, '%%VERSION%%', version)
console.log(context.hook + ': Replaced version in file: ' + path.relative(projectRoot, fullfilename))
} else {
console.error('File does not exist: ', path.relative(projectRoot, fullfilename))
process.exit(1)
}
})
}
function loadConfigXMLDoc (filePath, callback) {
var fs = require('fs')
var xml2js = require('xml2js')
try {
var fileData = fs.readFileSync(filePath, 'ascii')
var parser = new xml2js.Parser()
parser.parseString(fileData.substring(0, fileData.length), function (err, result) {
if (err) {
console.error(err)
process.exit(1)
} else {
// console.log("config.xml as JSON", JSON.stringify(result, null, 2))
console.log("File '" + filePath + "' was successfully read.")
callback(result)
}
})
} catch (ex) {
console.log(ex)
process.exit(1)
}
}
function replaceStringInFile (filename, toReplace, replaceWith) {
var data = fs.readFileSync(filename, 'utf8')
var result = data.replace(new RegExp(toReplace, 'g'), replaceWith)
fs.writeFileSync(filename, result, 'utf8')
}
You have also to add in config.xml
<hook src="hooks/setVersion.js" type="after_prepare"/>
This script replaces the text %%VERSION%% in a file with the app version from config.xml, so you can have in your index.html file something like
<html data-appversion="%%VERSION%%">
and in your JS
const version = document.documentElement.getAttribute("data-appversion");
You can use device.cordova to get the current version of Cordova.
Appropriate documentation

Categories

Resources