Loading a Nunjucks template with Electron.js - javascript

I would like to use a nunjucks render as my HTML for a window in my electron app but I can't find a way, is it possible? From what I have seen there are 2 ways to load HTML in window:
// Load a remote URL
win.loadURL('https://github.com')
// Or load a local HTML file
win.loadURL(`file://${__dirname}/app/index.html`)
And when I render my nunjucks template I have a string stored in a javascript variable:
render = nunjucks.render('./template/Template.html', data);
How can I use that string as an html for my window?
Many thanks everyone

You can pack your HTML into a data URI and pass that to win.loadURL:
const html = "<html><body><h1>Hello, world!</h1></body></html>";
win.loadURL("data:text/html;charset=utf-8," + encodeURI(html));
With your nunjucks render:
const render = nunjucks.render('./template/Template.html', data);
win.loadURL("data:text/html;charset=utf-8," + encodeURI(render));

Related

Feathers.js - Loading Static Content

I am evaluating feathers.js for a project. I like its aspirations. So, I decided to try and build a basic content management system just as a learning endeavor. Things have gone pretty smoothly. However, I want to load some static content (articles) into memory when the app starts. I can't figure out how to do that.
I have my articles in the data/articles directory. Each article is markdown named [title].md. I have a block of JavaScript that I tested in a console app that converts the markdown to HTML. That code uses markdown-js to get the HTML into a JSON object. It looks like this:
const fs = require('fs');
const markdownConverter = require('markdown');
let articles = [];
let files = fs.readdirSync('./data/articles');
for (let i=0; i<files.length; i++) {
let title = files[i].substr((files[i].lastIndexOf('/')+1), (files[i].length-3));
let markdown = fs.readFileSync(files[i], 'utf8');
let html = markdownConverter.toHTML(markdown);
articles[title] = html;
}
I've added a route in Feathers that works like this:
app.use('/articles/:slug', function(req, res) {
console.log('loading article: ' + req.params.slug);
let content = '';
// TODO: How to get access to the articles array.
// I want to get the HTML using content = articles[req.params.slug];
res.render('article', { content: content });
});
I'm not sure where to put the code that loads the markdown into an array that I can access when a user requests an article. Where does that belong? My guess is in the app.js file that gets generated when you create a Feathers project using the yeoman generator. Yet, I'm not sure what that actually looks like.
Since feathers is an Express app, you should be able to use express middleware. I recommend this one that allows you to create HTML templates for you markdown and serve them statically without creating any parsers or for loops.
https://github.com/natesilva/node-docserver
var docserver = require('docserver');
...
app.use(docserver({
dir: __dirname + '/docs', // serve Markdown files in the docs directory...
url: '/'} // ...and serve them at the root of the site
));
Or, this middleware that will preParse the Markdown before serving it as HTML in a Jade template.
https://www.npmjs.com/package/markdown-serve

Node JS, Ideas on Template For PDF Creation

How to create PDF Documents in Node.JS.? Is there any better solution to manage templates for different types of PDF creation.
I am using PDFKit to create PDF Documents and this will be server side using Javascript. I can not use HTML to create PDF. It will blob of paragraphs and sections with replacing tags with in.
Does anyone know Node.js has any npm package that can deal templates with paragraphs sections headers.
Something like
getTemplateByID() returns a template that contains sections , headers, paragraphs and then i use to replace appropriate tags within the template.
In my case, I have to get my HTML template from my database (PostgreSQL) stocked as stream. I request the db to get my template and I create a tmp file.
Inside my template, I have AngularJS tags so I compile this template with datas thanks to the 'ng-node-compile' module:
var ngCompile = require('ng-node-compile');
var ngEnvironment = new ngCompile();
var templateHTML = getTemplateById(id);
templateHTML = ngEnvironment.$compile(templateHTML)(datas);
Now I have my compiled template (where you can set your paragraph etc.) and I convert them into PDF thanks to a PhantomJS module 'phantom-html-to-pdf'
var phantomHTML2PDF = require('phantom-html-to-pdf')(options);
phantomHTML2PDF(convertOptions, function (error, pdf) {
if(error) console.log(error);
// Here you have 'pdf.stream.path' which is your tmp PDF file
callback(pdf);
});
Now you have your compiled and converted template (pdf), you can do whatever you want ! :)
Useful links:
https://github.com/MoLow/ng-node-compile
https://github.com/pofider/phantom-html-to-pdf
I hope this help !

Read Write text file using HTML code in Titanium Appcelerator

I am creating HTML5 type of application in Titanium Appcelerator. I have written code in order to creates text file using using titanium code which executes properly and create text file at /Users/demoUser/Library/Developer/CoreSimulator/Devices/FE1CF0AC-D5BD-4FAB-9615-C58D80B5A9C6/data/Containers/Data/Application/40686DB0-BFB0-4D01-98BB-9E5758C4976D/Documents/file.txt
Now I am having a html file i.e index.html which I am loading in titanium webview within same application. Now I want to access content of file.txt in a function created in .html file.
Anyone who has worked on anything like this before ? Or any help or suggestion regarding this would be appreciated.
You can read a file either from resources directory or application directory and render it in html page like below.
var readContents;
var readFile = Titanium.Filesystem.getFile(Titanium.Filesystem.applicationDataDirectory,'data.txt');
if (readFile.exists()) {
readContents = readFile.read();
Ti.API.info('File Exists');
}
var docString = readContents.toString();
Ti.API.info('Contents = ' + docString);
var text_in_html = "<html><body><pre>" + docString + "</pre></body></html>";
// Create our Webview
var myWV = Ti.UI.createWebView({
html:text_in_html,
title:'Title goes here',
left:0,
right:0,
top:0,
bottom:0,
loading: true
});

Mustache.js - using partial inside an external template file

I'm using external template file and I want to use a partial inside the template file (.mst file inside another .mst file)
For example I have template.mst file with this code:
{{#comments}}
// Here I want to use another external .mst file
{{/comments}}
So I careated a comment.mst file beside the template.mst file and now I'm trying to use {{>comment}} to call this external template file - full example:
{{#comments}}
{{>comment}}
{{/comments}}
But it doesn't work. I tried to play with it a little bit, I tried to add the file extension {{>comment.mst}} and I tried to add the path {{>temmplates/comment}} and any pther option.
This is the code I use to load the template:
$.get('templates/template.mst', function(template) {
var rendered = Mustache.render(template, postData);
$('.inner-container').prepend(rendered);
});
I guess I missing something, Can someone give me an hint? Thanks!

Mustache.js external template (without jQuery)

I'm writing a component without jQuery as a dependency, and I'm hoping to find a way to load an external Mustache.js template without jQuery. Using jQuery's $.get method appears to work, but I'm trying to do this in vanilla JS.
I tried using an XMLHttpRequest and appending the template to the body, and then hydrating it with my JSON, but when my JS tries to put the JSON in the template, the template isn't there to be hydrated (cannot read property innerHTML of null). Here was my code (in CoffeeScript, test.js is the mustache template):
req2 = new XMLHttpRequest()
req2.onload = ->
foo = document.getElementById('thatsmyjam')
templ = document.createTextNode(this.responseText)
foo.insertAdjacentHTML('beforeEnd', templ)
req2.open('GET', 'test.js', { async: false})
req2.responseType = 'document'
req2.send()
This adds the literal text [object Text] in the DOM instead of treating it as HTML, so it seems to be evaluating the string of HTML rather than rendering it as such.
There's probably a better way. I'm basically trying to combine my App (getting the JSON), mustache.js, and the template into one concatenated, minified file for distribution as a UI widget.
I also looked into something like Hogan.js to precompile the template, but it felt complicated, and I'm not able to use Node in this project.
Update
If I update the above CoffeeScript to this:
req2 = new XMLHttpRequest()
req2.onload = ->
foo = document.getElementById('thatsmyjam')
window.templ = document.createTextNode(this.responseText)
foo.insertAdjacentHTML('beforeEnd', templ)
req2.open('GET', 'test.js', { async: false})
req2.send()
then it's treated as a string in the relevant part of my app that tries to render the template:
populateDom: =>
self = #
#request.addEventListener 'loadend', ->
if #status is 200 && #response
resp = self.responseAsJSON(#response)
# here, window.templ is a string returned from the XMLHttpRequest above,
# as opposed to an actual "template", so Mustache can't call render with it.
rendered = Mustache.render(window.templ, resp)
document.getElementById('thatsmyjam').innerHTML = rendered
self.reformatDate(resp)
So Mustache treats the string differently than a template inside of a script tag. Is there a way to get Mustache to recognize that string as a legitimate template?
I figured out how to retrieve an external template using core JavaScript using an implementation inspired by this SO answer. The process is, essentially, create a new div, retrieve the template with an XMLHttpRequest, and fill the created div's innerHTML with the template string. Here's the implementation in CoffeeScript:
class TemplateManager
templateUrl: '/path/to/template.mustache'
retrieveTemplate: ->
req = new XMLHttpRequest()
req.onload = ->
div = document.createElement('div')
div.innerHTML = this.responseText
window.mustacheTemplate = div
req.open('GET', #templateUrl, { async: false})
req.send()
You can then call
rendered = Mustache.render(window.mustacheTemplate.innerHTML, resp)
document.getElementById('YOURDIV').innerHTML = rendered
to render the template with resp, your JSON data.
Here's a 2018 alternative using fetch to get both the data and the template in parallel:
// Get external data with fetch
const data = fetch('data.json').then(response => response.json());
// Get external template with fetch
const template = fetch('template.mst').then(response => response.text());
// wait for all the data to be received
Promise.all([data,template])
.then(response => {
resolvedData = response[0];
resolvedTemplate = response[1];
// Cache the template for future uses
Mustache.parse(resolvedTemplate);
var output = Mustache.render(resolvedTemplate, resolvedData);
// Write out the rendered template
return document.getElementById('target').innerHTML = output;
}).catch(error => console.log('Unable to get all template data: ', error.message));

Categories