Reading a part of file in NodeJs - node.js

Goal: To read a part/particular section of file using NodeJS.
My code:
fs = require('fs')
fs.readFile('/test/index.html', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
console.log(data);
});
Problem: This is reading whole file. And i want to read the text between body tag of html file.
Output in console:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h2>Card</h2>
<div class="card">
<img src="https://www.w3schools.com/howto/img_avatar.png" alt="Avatar" style="width:100%">
<div class="container">
<h4><b>John Doe</b></h4>
<p>Engineer</p>
</div>
</div>
</body>
</html>

You need parse the text, and extract the desired part.
using Regex its possible but problematic.
for parse html its recommended use cheerio (see example), in your case (select by node) you can also use "simple" xml reader as xml2js.
using cheerio :
const cheerio = require('cheerio')
fs = require('fs')
fs.readFile('/test/index.html', 'utf8', function (err,data) {
if (err) {
return console.log(err);
}
const $ = cheerio.load(data);
console.log($('body'));
});

Related

Node, Ejs, Express, passing variables to partial views. issues with re-using the same code in the express routes. Need to condense code

I am a newbie to node, express and ejs. I am creating a blog website project. I want to make use of EJS partials to stop repeating elements of code on my website. The simplified structure is
Blog
--js
--sql-helpers.js
--routes
--routes.js
--views
--homepage.ejs
--aboutpage.ejs
--header(Partial).ejs
The partial header ejs file is to be used on all webpages as it displays the title and author of the blog.
Here is a snippet of code from the routes file:
routes.js
router.get('/homepage', (req, res) => {
const sql = 'SELECT * FROM authors';
global.db.all(sql,[], function(err,rows){
const blogInfo = rows[0];
const params = {
authorName:blogInfo.author_name,
authorBlogTitle:blogInfo.authors_blog_title,
authorSubtitle:blogInfo.authors_blog_subtitle
};
res.render('homepage', params);
});
});
router.get('/aboutpage', (req,res) => {
const sql = 'SELECT * FROM authors';
global.db.all(sql,[], function(err,rows){
const blogInfo = rows[0];
const params = {
authorName:blogInfo.author_name,
authorBlogTitle:blogInfo.authors_blog_title,
authorSubtitle:blogInfo.authors_blog_subtitle
};
res.render('aboutpage', params);
});
});
As you can see I am having to re-use the same code in each of the routes to fill the variables in the header(partial).ejs file.
The homepage.ejs file code is as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Page</title>
</head>
<body>
<%- include('header(Partial)') %>
</body>
</html>
The header(partial).ejs file looks like this:
<header>
<section>
<h1 ><strong><%= authorBlogTitle %></strong></h1>
<span><%= authorSubtitle %></span>
<p ><small><%= authorName %></small></p>
</section>
</header>
To try and stop re-peating the same code i created a sql-helpers js file. as follows
const blogheader = function(callback){
const sql = 'SELECT * FROM authors';
global.db.all(sql,[], function(err,rows){
const blogInfo = rows[0];
const params = {
authorName:blogInfo.author_name,
authorBlogTitle:blogInfo.authors_blog_title,
authorSubtitle:blogInfo.authors_blog_subtitle
};
callback(params);
});
}
module.exports = {blogheader};
updated routes.js file:
const helpers = require("../public/js/sql_scripts");
router.get('/settings', (req,res) => {
let bloginfo = helpers.blogheader()
res.render('settings', blogheader);
});
My problems is I when i try and use this sql helper function in the routes I am getting a undefined value. Is this the best way to do it? How can wrap up my sql query so i dont have to repeat the same code in the routes? Is there a better way to use ejs partials?
I have been stuck on this issue for a number of days, searching the internet for an answer but I just havent found anything that helps me.

How to upload and display a file in Node.js?

I'm new to Node and have some problems with uploading files. I'm trying to to upload images (both jpg and png) and text files in text/plain and then display them at the post-route ('/upload)'. I've tried both multer and formidable but cannot get it right. Would really appreciate some help.
I tried all different kinds of events and callbacks, but I'm missing some crucial steps. Here is the html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Testform</title>
</head>
<body>
<form method="post" enctype="multipart/form-data"
action="/upload">
<div>
<input type="file" name="file" size="35">
</div>
<button type="submit" value="Click me" name="submit-btn">Click me</button>
</form>
</body>
</html>
And here is the server code:
const formidable = require('formidable')
const express = require('express')
const path = require('path')
const app = express()
app.get('/', (req, res) => {
res.sendFile(path.resolve('views', 'index.html'))
})
app.post('/upload', (req, res) => {
const form = new formidable.IncomingForm()
form.uploadDir = __dirname + '/uploads/'
form.parse(req)
form.on('fileBegin', (name, file) => {
file.path = form.uploadDir + file.name
res.write(`<img src="./uploads/${file.name}">`)
res.end()
})
})
app.listen(3000)
My root folder contains app.js, views/index.html, and a directory called uploads.
The code is my test case for image uploads. When I run the program a file with the correct name and content get uploaded into the directory './uploads'. However, I cannot see the uploaded image in the response of the post request ('/upload'). Would be great if anyone could help me with this and also for other text files (text/plain). Cheers!
In the response of the request you can send values, so something like res.end(value here) works!

Play MP4 videos in Node WebKit

I'm using nodebob for making a nodewebkit (nw.js) desktop app, but the MP4 videos wouldn't play in it ... what should I do?
I tried putting ffmpegso.dll in the same folder where my release exe is but no use
If i use webm video the following code works but for mp4 it says file not found
Here's the code I'm using
<html>
<head>
<meta charset='utf-8'>
<title>Secure Video Browsing</title>
<link rel="icon" type="image/png" href="hammer.png" />
<link rel="stylesheet" href="js/floplayer/skin/skin.css">
<!-- 3. flowplayer -->
<script src="js/floplayer/flowplayer.min.js"></script>
<script>
var encryptor = require('file-encryptor');
var $ = require('jquery');
var path = require('path');
var gui = require('nw.gui');
var win = gui.Window.get();
var key = 'My Super Secret Key';
var options = {algorithm: 'aes256'};
window.addEventListener('keydown', function (e) {
e.preventDefault();
});
var execPath = path.dirname(process.execPath);
$(document).ready(function () {
$(".close").click(function () {
win.close();
});
encryptor.decryptFile(execPath + '/wild.eng', execPath + '/wild.mp4', key, options, function (err) {
var container = document.getElementById("player");
flowplayer(container, {
clip: {
sources: [
{type: "video/mp4",
src: execPath + '/wild.mp4'}
]
}
});
});
});
</script>
</head>
<body>
<button class="close">Close</button>
<div id="player">
</div>
</body>
The easiest way to enable proprietary codecs is to download community binaries for the matching NW.js version number you are using:
https://github.com/iteufel/nwjs-ffmpeg-prebuilt/releases
More information is here:
https://nwjs.readthedocs.io/en/latest/For%20Developers/Enable%20Proprietary%20Codecs/

How can I deploy the auth0 app to bluemix

I am using a sample project from auth0.com to customize the login page for my app and enable social media login. However I encounter some problem when I try to deploy it to bluemix.
The video tutorial I follow is https://www.youtube.com/watch?v=sHhNoV-sS_I&t=559s
however the sample project is a little bit different from the one in video. It required the command "npm serve" to run it. When I push my project using cf push it shows noappdecked. How can I deploy my project to bluemix?
the app.js code and html code is like
<!DOCTYPE html>
<html>
<head>
<title>Auth0-VanillaJS</title>
<meta charset="utf-8">
<!-- Auth0 lock script -->
<script src="//cdn.auth0.com/js/lock/10.3.0/lock.min.js"></script>
<script src="auth0-variables.js"></script>
<script src="app.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<img alt="avatar" id="avatar" style="display:none;">
<p>Welcome <span id="nickname"></span></p>
<button type="submit" id="btn-login">Sign In</button>
<button type="submit" id="btn-logout" style="display:none;">Sign Out</button>
</body>
window.addEventListener('load', function() {
var lock = new Auth0Lock(AUTH0_CLIENT_ID, AUTH0_DOMAIN);
// buttons
var btn_login = document.getElementById('btn-login');
var btn_logout = document.getElementById('btn-logout');
btn_login.addEventListener('click', function() {
lock.show();
});
btn_logout.addEventListener('click', function() {
logout();
});
lock.on("authenticated", function(authResult) {
lock.getProfile(authResult.idToken, function(error, profile) {
if (error) {
// Handle error
return;
}
localStorage.setItem('id_token', authResult.idToken);
// Display user information
show_profile_info(profile);
});
});
//retrieve the profile:
var retrieve_profile = function() {
var id_token = localStorage.getItem('id_token');
if (id_token) {
lock.getProfile(id_token, function (err, profile) {
if (err) {
return alert('There was an error getting the profile: ' + err.message);
}
// Display user information
show_profile_info(profile);
});
}
};
var show_profile_info = function(profile) {
var avatar = document.getElementById('avatar');
document.getElementById('nickname').textContent = profile.nickname;
btn_login.style.display = "none";
avatar.src = profile.picture;
avatar.style.display = "block";
btn_logout.style.display = "block";
};
var logout = function() {
localStorage.removeItem('id_token');
window.location.href = "/";
};
retrieve_profile();
});
You would use the package.json method documented at https://console.ng.bluemix.net/docs/runtimes/nodejs/index.html#nodejs_runtime , first to declare the serve package as one of your dependencies, then to indicate what the scripts.start script should do (which is run npm serve). You can use npm init (https://docs.npmjs.com/cli/init) to create a starting package.json file if you don't already have one.

Node.js jsdom set document root

I am trying to load local javascripts with jsdom.
Now I am wondering how I can make jsdom loading the javascripts from "__dirname/../public".
Can someone help me?
My current code is:
var fs = require('fs');
var jsdom = require('jsdom');
jsdom.defaultDocumentFeatures = {
FetchExternalResources: ["script"],
ProcessExternalResources: ["script"],
MutationEvents : '2.0',
QuerySelector : false
};
exports.test = function(req, res) {
var html = fs.readFileSync(__dirname+'/../public/html/lame.html');
var document = jsdom.jsdom(html, null, {documentRoot: __dirname+'/../public/'});
var window = document.createWindow();
window.addEventListener('load', function () {
//window.$('script').remove();
//window.$('[id]').removeAttr('id');
res.send(window.document.innerHTML);
window.close();
});
}
The simple HTML page is:
<html>
<head>
<title id="title">bum</title>
<script type="text/javascript" src="/javascripts/jquery.min.js"></script>
<script type="text/javascript" src="/javascripts/stuff.js"></script>
</head>
<body>
<h1>hello world</h1>
<h2 id="bam">XXX</h2>
</body>
</html>
I've run into the same issue and got it to work. Try these, in order:
documentRoot is not documented. The option which is documented is url. So replace documentRoot with url.
If the above is not enough, then add a base element. I've set my templates like this:
<head>
<base href="#BASE#"></base>
<!-- ... -->
</head>
where #BASE# is replaced with the same value as the one passed to url.
The solutions above are extracted from actual code in use in a test suite.

Resources