Templating in Electron? - javascript

Simple question here, but I found no useful resource. Is templating possible in Electron? Using Jade or Handlebars to display dynamic templates? I know there is .loadURL() that takes a static html file.
Is dynamic possible?
Thanks.

You could give electron-pug a chance. https://github.com/yan-foto/electron-pug

You can register a new buffer protocol via protocol.registerBufferProtocol.
main.js
var electron = require('electron');
var app = electron.app;
var protocol = electron.protocol;
var BrowserWindow = electron.BrowserWindow;
var pug = require('pug');
var window;
app.on('ready', function () {
// Define the `pug` scheme
protocol.registerBufferProtocol('pug', function (request, callback) {
var url = path.normalize(request.url.substr(7));
var content = pug.renderFile(url);
callback({
mimeType: 'text/html',
data: new Buffer(content)
});
});
window = new BrowserWindow({width: 600, height: 600});
// Load your file using the `pug` protocol
window.loadURL(url.format({
pathname: path.join(__dirname, 'index.pug'),
protocol: 'pug:',
slashes: true
}));
});
index.pug
html
head
title My title
body
h1 Hello world!

It would certainly be possible to use Jade or Handlebars for dynamic templating by running a local server in the Electron main process. I would not recommend this however, as it is kind of backwards. Electron is primarily a front end framework and while running a local server is good for some things, templating is not really one of them.
Most people use a frontend JS framework like Angular or React.

Probably too late to add here but thought it might be worthwhile. I have added a package to deal with adding views from any renderer and handle asset paths. So far I have just added the ejs renderer but plan on adding pug and haml as additional default renderers, but it is easy to extend and add your own as well. The package is called electron-view-renderer https://www.npmjs.com/package/electron-view-renderer
Hopefully this can help someone like it did our team. It is in its infancy, so all comments and contributions welcome

U can use ejs-electron to achieve the same purpose. U can check it out on github & simply install it as follows:
npm i ejs-electron --save
Just require it in ur main js file

Related

What is the Node.js equivalent of a PHP include?

I'm looking for a simple solution for server side includes of regular HTML and CSS (for repeated components like headers, footers, navigation, etc) that doesn't require extensive frameworks.
You're looking for the
require()
function. Check out the documentation for this and other Node.js things here
If you want to use newer import statement, you may do so; it's not yet fully implemented in Node, but you can use it by using the .mjs extension on the file you need to import and then using the following command:
node --experimental-modules someFile.mjs
In node js to include repetitive files like headers, footers etc. you will need a templating language such as ejs.
Using ejs here is a sample code snippet with the include tag
<%- include('./path/to/your/html/file') %>
You can use require to require multiple files. However, since node caches the files, you will need to delete them from the cache if you want to used an un-cached version of the file.
index.js
app.get('/path', (req, res) => {
clear()
let headers1 = require('/headers/a.js')
let headers2 = require('/headers/b.js')
res.set(headers1)
res.set(headers2)
})
// Remove from require cache
function clear() {
delete require.cache[require.resolve('/headers/a.js')]
delete require.cache[require.resolve('/headers/b.js')]
}
headers/a.js
module.exports = {
'Content-Type': 'application/json'
}
headers/b.js
module.exports = {
'Custom-Header': 'Brass Monkey'
}
I think you like require "view components". Exists multiple view engines for nodejs, for example pug , or ejs. In this case, you use include

Sails.js: Can I package some services/models as npm and load the npm in Sails.js app?

I want to create two different Sails.js app such as hello-world and hello-world-admin. In two app, I want to make two apps use same services/models. So I'm thinking that packaging services/models in hello-world app as a npm, and loading it in two.
But Sails.js models must be extended accordingly in lifting phase. So just using 'require' doesn't satisfy it at all. Is there any correct/good way to achieve it (using same models in two app)?
I'm thinking using hooks to extend models but I couldn't find good example. Any comments/info would be appreciated.
Updated
I'm trying to use "installable hooks" to extending models. I prepared sails-hook-models package in node_modules which has index.js below.
module.exports = function(sails) {
return {
defaults: {
},
initialize: function(cb) {
var ModelA = require('./models/ModelA');
ModelA.identity = 'modela';
ModelA.globalid = 'ModelA';
var ModelB = require('./models/ModelB');
ModelB.identity = 'modelb';
ModelB.globalid = 'ModelB';
sails.models['modela'] = ModelA;
sails.models['modelb'] = ModelB;
return cb();
},
};
After Sails has lifted, the models have been extended by waterline so I can call Model's method via sails.models['modela']. I'm not sure this is a good way.. Please tell me if you have alternatives / better ways.
Yes, and there is a way to do this already: https://github.com/tjwebb/sails-generate-entities. You define a manifest of which services/models/controllers/etc you'd like to install.
An example is here: https://github.com/tjwebb/sails-permissions
Yes, use the Sails Generator project to do this.

How to add configuration settings to locals on Sails.js

I'm building a webapp using Sails.js and I'm wondering how to have different configurations on development and production modes. I thought that I just had to put a configuration key in config/local.js but it doesn't work. Here's an example of what I'm trying to do:
config: {
linkedIn_key: 'abcde',
linkedIn_secret: '13mcas',
linkedIn_url: 'http://localhost:1337/user/login'
}
I tried to access config in the UserController.js but I wasn't able to get the value. What is the right way to do it?
Best regards,
João
It should appear in sails.config. You can also try to create a new file: linkedin.js under the config folder and place your configurations there:
var linkedIn = {
key: 'abcde',
secret: '13mcas',
url: 'http://localhost:1337/user/login'
};
module.exports.linkedin = linkedIn;
and access it in your controller via
sails.config.linkedin

sharing settings/config between client and backend

I have an application using node.js backend and require.js/backbone frontend.
My backend has a config/settings system, which depending on the environment (dev, production, beta) can do different things. I would like to propagate some of the variables to the client as well, and have them affect some template rendering (e.x change the Title or the URL of the pages).
What is the best way to achieve that?
I came up with a way to do it, and it seems to be working but I don't think its the smartest thing to do and I can't figure out how to make it work with requirejs optimizer anyway.
What I do is on the backend I expose an /api/config method (through GET) and on the client
I have the following module config.js:
// This module loads an environment config
// from the server through an API
define(function(require) {
var cfg = require('text!/api/config');
return $.parseJSON(cfg);
});
any page/module that needs config will just do:
var cfg = require('config');
As I said I am having problem with this approach, I can't compile/optimize my client code
with requirejs optimizer since /api/config file doesn't exist in offline during optimization. And I am sure there are many other reason my approach is a bad idea.
If you use use module bundlers such as webpack to bundle JavaScript files for usage in a browser, you can reuse your Node.js module for the client running in a browser. In other words, put your settings or configuration in Node.js modules, and share them between the backend and the client.
For example, you have the following settings in config.js:
Normal Node.js module: config.js
const MY_THIRD_PARTY_URL = 'https://a.third.party.url'
module.exports = { MY_THIRD_PARTY_URL }
Use the module in Node.js backend
const config = require('path-to-config.js')
console.log('My third party URL: ', config.MY_THIRD_PARTY_URL)
Share it in the client
import config from 'path-to-config.js'
console.log('My third party URL: ', config.MY_THIRD_PARTY_URL)
I do the following (note that this is Jade, i have never used require.js or backbone, however as long as you can pass variables from express into your templating language, you should be able to place JSON in data-* attributes on any element you want.)
// app.js
app.get('/', function(req, res){
var bar = {
a: "b",
c: Math.floor(Math.random()*5),
};
res.locals.foo = JSON.stringify(bar);
res.render('some-jade-template');
});
// some-jade-template.jade
!!!
html
head
script(type="text/javascript"
, src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js")
script(type="text/javascript")
$.ready(init);
function init(){
var json = $('body').attr('data-stackoverflowquestion');
var obj = JSON.parse(json);
console.log(obj);
};
body(data-stackoverflowquestion=locals.foo)
h4 Passing data with data-* attributes example

How to set the source path in Ace editor

I am embedding Ace locally offline and so am not using the hosted package and am subject to the same origin policy.
How do you tell ace to look in a particular folder for it's source of modes, themes and workers?
You used to be able to use:
editor.config.set("modePath", "Scripts/Ace");
editor.config.set("workerPath", "Scripts/Ace");
editor.config.set("themePath", "Scripts/Ace");
But that doesn't work in the latest version.
How can this be achieved?
Thanks in advance
I had a similar issue and you can actually let Ace know what's the base folder path this way:
ace.config.set("basePath", "/Scripts/Ace");
This work with the latest version I have, v1.1.3
The simple way to achieve the same thing is to embed all scripts from the Ace source folder into the web page manually, excluding the worker-xxx.js files. This is still a bodge though.
The answer from #rorofromfrance solve my problem of the base folder path on loading Ace script on the fly:
$.getScript($('#js')[0].href, function() {
$('.theme').change(function() {draw.change();});
$.getScript("/ace/src-min/ace.js", function() {
if (!editor) {ace.config.set("basePath", "/ace/src-min"); draw.editor();};
$.getScript("/underscore/underscore-min.js", function() {
editor.getSession().on('change', _.debounce(function() {draw.diagram();}, 100));
$.getScript("/tensorflow/tf.min.js", function() {
$.ajax({
type: "GET",
dataType: "xml",
url: "/sitemap.xml",
success: draw.getJSON(xml)
});
});
});
});
});
I have a similar requirement in a current project of mine.
I created an Angular project with all the files bundles in a single directory without access to node_modules in runtime, using a remote package for the ace basePath was out of the question.
Then I stumbled upon the Ace embedding guide and it clued me that I can import the relevant modes and themes straight from my dependencies and just use new instead of a path string.
https://ajaxorg.github.io/ace-api-docs/index.html#embedding-ace
from the docs:
var JavaScriptMode = ace.require("ace/mode/javascript").Mode;
editor.session.setMode(new JavaScriptMode());
So I just imported the mode and theme I went and provided them straight to Ace
import DraculaTheme from "ace-builds/src-noconflict/theme-dracula";
import JavaScriptMode from "ace-builds/src-noconflict/mode-javascript";
const aceEditor = ace.edit(this.editor.nativeElement);
aceEditor.session.setValue("function greet() {\n\tconsole.log('hello world');\n}\n");
aceEditor.setTheme(DraculaTheme);
aceEditor.session.setMode(new JavaScriptMode.Mode());
Notice that I didn't set any basePath !!!

Categories