How to use HTML in Express framework with nunjucks- no jade - html

I have been using sendFile method to render Html in Express project.
I would like to use partials with my project. And, not switch to jade.
Is there a way to use traditional HTML with partials in Express 3.x.
I have tried ejs, but dont understand it completely.

A more 'HTML-like' templating engine would be nunjucks (whose syntax is similar to Jinja2, which you have experience with).
Here's a simple setup. This assumes both Express and Nunjucks are installed, if not:
npm install express
npm install nunjucks
– app.js
var nunjucks = require('nunjucks');
var express = require('express');
var app = express();
app.listen(3012);
nunjucks.configure('views', {
autoescape: true,
express : app
});
app.get('/', function(req, res) {
res.render('index.html', {
title : 'My First Nunjucks Page',
items : [
{ name : 'item #1' },
{ name : 'item #2' },
{ name : 'item #3' },
{ name : 'item #4' },
]
});
});
– views/index.html
<!doctype html>
<html>
<head>
<title>welcome to {{ title }}</title>
</head>
<body>
<ul>
{% for item in items %}
{% include "item.html" %}
{% endfor %}
</ul>
</body>
</html>
– views/item.html
<li>{{ item.name }}</li>

Related

Eleventy / Nunjucks: minify JS with terser within minified HTML

I try to minify partial HTML in which I minify some JS using terser (using a jsmin filter as showed in 11ty docs):
<!doctype html>
<html lang="fr"><head><meta charset="utf-8"><title></title></head>
{% set html %}
<body>
<div class="foo">
Bar
</div>
<script>{% set js %}
var foo = 'foo',
bar = 'bar';
{% endset %}{{ js | jsmin | safe }}</script>
{% endset %}
{{ html | htmlmin | safe }}
</body>
</html>
But since the terser process is asynchronous, it throws an error in 11ty (callback is not a function, and <script>[object Promise]</script> in the generated file).
Same problem if I try to minify all the HTML using an 11ty transform (as suggested in their docs: Minify HTML Output – and removing all the {% set html %} / {{ html | … }} tags): it throws some similar Promise errors (Having trouble writing template … Cannot read properties of undefined … at async Promise.all)
Problem solved if I move the script part outside of the Nunjucks set declaration:
<!doctype html>
<html lang="fr"><head><meta charset="utf-8"><title></title></head>
{% set html %}
<body>
<div class="foo">
Bar
</div>
{% endset %}
{{ html | htmlmin | safe }}
<script>{% set js %}
var foo = 'foo',
bar = 'bar';
{% endset %}{{ js | jsmin | safe }}</script>
</body>
</html>
But that's not what I want.
Trying to make terser synchronous seems to need some more npm packages so I'm hoping there's an easier way before trying it.
Edit: tried to use html-minifier-terser instead of html-minifier, with this code for the htmlmin filter:
const TerserHTML = require('html-minifier-terser');
…
eleventyConfig.addNunjucksAsyncFilter('htmlmin', async function(code, callback) {
try {
let minified = await TerserHTML.minify(code, {
removeComments: true,
collapseWhitespace: true
});
callback(null, minified);
} catch (err) {
console.error('Terser HTML error: ', err);
callback(null, code);
}
});
→ same issue

Can I use Rust / Yew / Trunk to generate just a DOM node and script for use in HTML templates?

TLDR
Total n00b with rust, yew and trunk.
I want to find out how to rust, yew and trunk to build an HTML file containing just one DOM node, not a whole HTML page.
Background
Day-to-day, I use Django, the python web framework. Its admin console uses HTML template rendering, and an example of a template might look like this:
{% extends 'django_twined/question_changeform.html' %}
{% block object-tools-items %}
{% if show_set_active %}
<li>Set active</li>
{% endif %}
{{ block.super }}
{% endblock %}
Where in this example the {% %} and {{ }} get evaluated at render time into a valid HTML structure (from other template files), and the <li> is an extra node that gets added to the DOM.
Instead of a vanilla li element, I want to build a complex DOM node using Rust/Yew/Trunk. Then I can include the resulting head and body elements file in a django template, something like:
{% extends 'django_twined/question_changeform.html' %}
{% block head %}
{{ block.super }}
<!-- Include the scripts generated by trunk build -->
{% include 'my-dom-node-head.html' %}
{% endblock %}
{% block object-tools-items %}
<!-- Include the elements generated by trunk build -->
{% include 'my-dom-node-body.html' %}
{{ block.super }}
{% endblock %}
Where I'm at
I've used the yew starter app to get myself to an app. The input index.html is:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Yew App</title>
</head>
</html>
And the main.rs file looks like:
use yew::prelude::*;
enum Msg {
AddOne,
}
struct Model {
value: i64,
}
impl Component for Model {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context<Self>) -> Self {
Self {
value: 0,
}
}
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
match msg {
Msg::AddOne => {
self.value += 1;
// the value has changed so we need to
// re-render for it to appear on the page
true
}
}
}
fn view(&self, ctx: &Context<Self>) -> Html {
// This gives us a component's "`Scope`" which allows us to send messages, etc to the component.
let link = ctx.link();
html! {
<div>
<button onclick={link.callback(|_| Msg::AddOne)}>{ "+1" }</button>
<p>{ self.value }</p>
</div>
}
}
}
fn main() {
yew::start_app::<Model>();
}
After trunk build, the output index.html looks like:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Yew App</title>
<link
rel="preload"
href="/yew-app-caccf6c60742c530_bg.wasm"
as="fetch"
type="application/wasm"
crossorigin=""
/>
<link rel="modulepreload" href="/yew-app-caccf6c60742c530.js" />
</head>
<body>
<script type="module">
import init from "/yew-app-caccf6c60742c530.js";
init("/yew-app-caccf6c60742c530_bg.wasm");
</script>
</body>
</html>
Where next?
So basically I need to get the <link> and <script> elements added by trunk build and put them into my template.
What should I do next? Would you suggest I try to:
Get trunk build --filehash false to output deterministic .js and .wasm file names without the hash (caccf6c60742c530 in this case) so that I can directly write the includes into my template (I'm concerned this will cause me development problems down the road)?
Get trunk build to output separate head link and body script?
Post-process the output index.html to extract the inserted scripts?
Alter main.rs in some way to output only what I need/want?

Binding vue js app to django template not showing any content

I am trying to binding vue js component into django HTML template file, but it is not showing any content. I am not getting any error. Just blank component.
Here is my django HTML template:
{% load render_bundle from webpack_loader %}
{% render_bundle 'product-filter-app' %}
{% block section_more %}
<section id="section_more" class="guide_section">
<div id="product-filter-app">
<product-filter-app></product-filter-app>
</div>
</section>
{% endblock %}
Here is my vue js app.
main.js
import Vue from 'vue'
import * as Sentry from '#sentry/browser'
import 'vue-select/dist/vue-select.css'
import ProductFilterApp from './ProductFilterApp'
import { sentryOptions } from '#/utils/settings'
if (process.env.VUE_APP_MODE !== 'dev') {
Sentry.init(sentryOptions)
}
new Vue({
components: { ProductFilterApp }
}).$mount('#product-filter-app')
Here is ProductFilterApp.vue
<template>
<h1>Test</h1>
</template>
<script>
export default {
name: 'ProductFilterApp',
components: {
},
props: {
},
data () {
return {
}
},
methods: {
}
}
</script>
<style scoped>
</style>
Web-pack is generating app successfully there is not any error but just showing empty component as per screen shot.
Any help will be appreciated.
Actually, you shouldn't really even need to include the template in your view, as long as your element with ID of #product-filter-app is there. Give this a shot:
new Vue({
el: '#product-filter-app',
components: { ProductFilterApp },
template: '<ProductFilterApp/>'
})
And you can remove <ProductFilterApp><ProductFilterApp/> from your view.

Query data from mongoose and display it on a html page

This is my schema
var productSchema = new mongoose.Schema({
name: String,
description: String
});
var Product = mongoose.model('Product', productSchema);
In my index.js i am using
exports.welcome = function(req,res) {
Product.find({},{},function(err,docs) {
res.render('welcome', {
"productlist" : docs
});
});
};
In my app.js i am calling this statement where routes is my variable to call welcome in index.js
app.get('/welcome',routes.welcome);
My schema is also written in index.js. What i want to do is display all the products with their name and description in my html page named "welcome.html".
Can anyone tell me like what should i write in my html page to do this.
From your latest comment, it means you are using EmbeddedJS as templating engine. Your answer is well documented here.
For complicity, an example of welcome.html to display results is:
<!DOCTYPE html>
<html>
<head>
<title>My Products</title>
</head>
<body>
<ul>
<% for(var i=0; i<productlist.length; i++) {%>
<li><%= productlist[i].name %> : <%= productlist[i].description %></li>
<% } %>
</ul>
</body>
</html>

angularjs (1.2.0) not printing results to page

I've got an angularjs view that I'm trying to print its results and even though the indexing and console output show the data I can't get it to show up in the actual page.
My console output of the json data received:
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
0: Object
$$hashKey: "004"
_id: Object
$oid: "527994c48776385b2e4a6e78"
__proto__: Object
author: "Undefined author"
content: "Undefined content"
title: "stfu"
__proto__: Object
1: Object
$$hashKey: "005"
_id: Object
$oid: "52799b0a8776385c490cd268"
__proto__: Object
author: "adam-stokes"
content: "some content here"
title: "dieeeee"
My controller code:
'use strict';
var cagewebControllers = angular.module('cagewebControllers', []);
cagewebControllers.controller('IndexCtrl', ['$scope', '$http',
function($scope, $http) {
$http.get('http://localhost:9000/entity/page').
success(function(data, status, headers, config) {
$scope.pages = data;
console.log($scope.pages);
});
}
]);
My app code:
'use strict';
var cageweb = angular.module('cageweb', [
'ngRoute',
'cagewebControllers'
]);
cageweb.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
» when('/', {
» templateUrl: 'partials/index',
» controller: 'IndexCtrl'
» }).
» otherwise({
» redirectTo: '/'
» });
}]);
my template partial:
<h1>Pages</h1>
{{pages.length}}
<div ng-repeat="page in pages track by $id(page)">
page {{$$hashKey}} - {{page.title}}
</div>
my template layout:
<!DOCTYPE html>
<html ng-app="cageweb">
<head>
<title>{{ title }}</title>
<link rel='stylesheet' href='/stylesheets/style.css' />
<script src="javascripts/lib/jquery/jquery-1.10.2.min.js"></script>
<script src="javascripts/lib/angular/angular.js"></script>
<script src="javascripts/lib/angular/angular-animate.min.js"></script>
<script src="javascripts/lib/angular/angular-resource.min.js"></script>
<script src="javascripts/lib/angular/angular-route.min.js"></script>
<script src="javascripts/app.js"></script>
<script src="javascripts/controllers.js"></script>
</head>
<body>
<h1>cage-webbbbb</h1>
<div class="view-container">
<div ng-view class="view-frame"></div>
</div>
</body>
</html>
$scope.pages does contain the json data and I can see the data with console.log($scope.pages) but for whatever reason I can not get it to print on the page itself. im not sure if its something easy im missing but a second set of eyes would be much appreciated.
thanks
Thanks to the comments I was able to narrow down my issue. I probably should've mentioned that the application server was nodejs with expressjs using hogan as the templating engine...and guess what, hogan uses the same syntax as angular for processing variables :\ once I switched to ejs I was able to print to the page.
thanks!