generating templates with grunt - looking for a task - javascript

I've got an HTML file with following content:
<html>
<body>
<span>{{ secret }}</span>
</body>
</html>
I'm looking for a grunt task that could take this source file, take a map of values:
grunt.initConfig({
myTask: {
myTarget: {
src: ...
dest: ...
values: {
secret: 'ABC'
}
}
}
})
and generate output file:
<html>
<body>
<span>ABC</span>
</body>
</html>
Is there any task like this? I saw grunt-mustache-html but it forces lots of things to exist which I really don't need and I don't want to use it. I want simply to take a single mustache (or hbs or whatever), fill it with data from grunt-level object and dump the result into another HTML file, that's all.

You could try grunt-template which processed lo-dash templates. Here's a basic setup to solve your problem:
//Gruntfile.js
config.template = {
myTask: {
options: {
data: function () {
return {
secret: 'ABC'
};
}
},
files: {
'output.html: ['template.html.tpl']
}
}
};
//template.html.tpl
<html>
<body>
<span><%= secret %></span>
</body>
</html>

#1. One options is to make use of grunt.template utility (see lagerone's answer). With custom delimiters you can achieve pretty close result to what you want:
grunt.template.addDelimiters('myDelimiters', '{{', '}}');
In this case your template will have to use {{= secret }} tags.
#2. Another option is that you can always write you own simple task. In your case it can look like this:
grunt.initConfig({
myTask: {
options: {
data: {
secret: 'ABC'
},
src: 'index.html',
dest: 'index.output.html'
}
}
});
grunt.registerTask('myTask', function() {
var options = this.options(),
template = grunt.file.read(options.src);
var content = template.replace(/\{\{\s*(.*?)\s*\}\}/g, function(a, b) {
return typeof options.data[b] !== undefined ? options.data[b] : '';
});
grunt.file.write(options.dest, content);
});
grunt.registerTask('default', ['myTask']);

I have used grunt-include-replace in the past. Is easy to use. In your gruntfile you will create a task similar to this one (Example taken from official github repo):
grunt.initConfig({
includereplace: {
your_target: {
options: {
// Task-specific options go here.
},
// Files to perform replacements and includes with
src: '*.html',
// Destination directory to copy files to
dest: 'dist/'
}
}
})

Related

Inject varables in css, html, js with Webpack

I have problem, that in my project I use constants, variables in css, html, js and if I wanna something change some constants I need find it in html or css or js, that take long time. And wonder if it possible have separate js file with variables and constants, and inject value from that to html, js, css (sass). Pseudocode below. I wanna know, is even possible do with webpack, if yes, how or where I should look?
document.getElementById(${=name}).style.color = 'white';
.box {
width: ${=width}
}
<div class="box box_${=id}">
Some text
</div>
const css = {
width: '250px',
};
const html = {
id: '2'
};
const js = {
id: 'haha',
};
You can use a webpack plugin for doing all replacement.
for instance:
https://github.com/jamesandersen/string-replace-webpack-plugin
It can replace in any files you want...
for JS (for instance) you would have something like:
module: {
loaders: [
// configure replacements for file patterns
{
test: /.js$/,
loader: StringReplacePlugin.replace({
replacements: [
{
pattern: /DEFAULT_WIDTH/ig,
replacement: function () {
return '100px';
}
}
]})
}
]
},

How to integrate mailchimp with nuxt js app?

I'd like to embed the following script into my component in nuxtjs app. But since nuxt has no solution for this. I'd like to ask the vue community to see if there was a better way of embedding external 3rd party js scripts?
Where should I be embedding this type of scipt? And what sort of external configurations do I need to add to enable this to work?
I tried adding directly into my template but it doesn't seem to be working.
<script type="text/javascript" src="//downloads.mailchimp.com/js/signup-forms/popup/embed.js" data-dojo-config="usePlainJson: true, isDebug: false"></script><script type="text/javascript">require(["mojo/signup-forms/Loader"], function(L) { L.start({"baseUrl":"mc.us17.list-manage.com","uuid":"XXXXXX","lid":"XXXXXX"}) })</script>
Thanks!
Open up your nuxt.config.js file, and search for the head object. You can add your third party scripts there like this:
// nuxt.config.js
module.exports = {
head: {
title: 'My title',
// etc.
script: [
{ src: "//downloads.mailchimp.com/js/signup-forms/popup/embed.js" },
// You can add multiple third-party scripts here
]
},
// Other stuff
}
Docs: How to use external resources?
I haven't tested it, but I think, since the other part is just javascript, you can add into your page you wan't to show it or a layout file (if you want to show it on multiple pages), like this:
// layout/default.vue
<template>
<!-- Your template -->
</template>
<script>
require(["mojo/signup-forms/Loader"], function(L) { L.start({"baseUrl":"mc.us17.list-manage.com","uuid":"XXXXXX","lid":"XXXXXX"}) });
export default {
// etc...
}
</script>
Although the require part might mess things up...
Let me know if this works!
Insert the MailChimp code inside the <head>
head() {
return {
script: [
{
type: "text/javascript", // mailchimp universal script
src:
"//downloads.mailchimp.com/js/signup-forms/popup/unique-methods/embed.js",
"data-dojo-config": "usePlainJson: true, isDebug: false"
},
{
type: "text/javascript", // mailchimp script for specific popup form
innerHTML: this.getMailchimp
}
],
__dangerouslyDisableSanitizers: ["script"]
};
},
computed: {
getMailchimp() {
if (process.client) {
return JSON.stringify(
window.dojoRequire(["mojo/signup-forms/Loader"], function(L) {
L.start({
baseUrl: "your base url",
uuid: "your uuid",
lid: "your lid",
uniqueMethods: true
});
})
);
}
}
}

Grunt.js templates: Use the name of the target in a task?

I'm trying to use the name of the target in a template. Should be simple enough, right?
My scenario is this:
copy:
{
all: {
src: 'commonFiles/**', dest: 'build/<%= grunt.???? =>/common'
},
apple: { ... },
orange:{ ... },
banana:{ ... },
...
}
grunt.registerTask('default', ['apple', 'orange', 'banana']);
grunt.registerTask('apple' , 'copy:all copy:apples ... ... ...');
grunt.registerTask('orange', 'copy:all copy:orange ... ... ...');
grunt.registerTask('banana', 'copy:all copy:banana ... ... ...');
grimt.registerTask(...);
...
many, many more fruit
I've scoured the docs, I've console.log'd grunt but found no string that is the parent task. The closest I found was grunt.task.current.name but that ends up being copy:all.
The goal would be to get a directory structure like this for all my fruit:
build/apple/common/...
build/orange/common/...
build/banana/common/...
build/.../common/...
...
commonFiles/...
I'm sending a fruit basked to whomever can figure this out.
A dynamic alias task would probably be better suited for this use case.
See http://gruntjs.com/frequently-asked-questions#dynamic-alias-tasks
grunt.initConfig({
buildDir: 'all',
copy: {
all: {
src: 'commonFiles/**',
dest: 'build/<%= buildDir =>/common',
},
apple: { ... },
orange:{ ... },
banana:{ ... },
},
});
grunt.registerTask('build', function(target) {
if (target == null) {
return grunt.warn('Build target must be specified, like build:apple.');
}
grunt.config('buildDir', target);
grunt.task.run('copy:' + target);
});

How does package location work in Dojo?

I'm working through the example at http://dojotoolkit.org/documentation/tutorials/1.7/hello_dojo/demo/module.html and I've created a directory structure as follows
w:/djt2/index.html
w:/djt2/js/mymodule.js (exact copy of http://dojotoolkit.org/documentation/tutorials/1.7/hello_dojo/demo/myModule.js)
I then set the Tinyweb web-server to serve localhost from w:/djt2
I've changed index.html a tiny bit, to adjust for putting mymodule.js inside the js subdirectory (I've removed comments too below):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tutorial: Hello Dojo!</title>
<script>
var dojoConfig = {
async: true,
packages: [{
name: "djt2",
location: '/js' /* Location #1 */
}]
};
</script>
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js"></script>
</head>
<body>
<h1 id="greeting">Hello</h1>
<script>
require(["djt2/mymodule"], function(myModule){ /* Location #2 */
myModule.setText("greeting", "Hello Dojo!");
setTimeout(function(){
myModule.restoreText("greeting");
}, 3000);
});
</script>
</body>
</html>
This works, but I'm not entirely sure I understand why... In particular, at Location #1, the original had location.pathname.replace(/\/[^/]+$/, '') which evaluates to the empty string and makes the loader look for mymodule.js at the CDN location (I also tried to set location to "/", but that made it search at http://mymodule.js/).
At Location #2 it is a little mystical that the prefix should be djt2/...
If someone could explain it, or direct me to the documentation (I'm a bit overwhelmed with learning a new framework :-).
Add an extra djt2 directory in your structure
w:/djt2/js/djt2/mymodule.js
Set the baseUrl in the configuration.
var dojoConfig = {
async: true,
baseUrl: '/js'
packages: [{
name: "djt2",
location: 'djt2'
}]
};
Setting the baseUrl will tell dojo where to look for custom modules. The location that is part of the package is relative to the baseUrl.
I always think of modules/packages as namesapces. To extend your example with an additional package, it would look like the following:
w:/djt2/js/another/anotherModule.js
var dojoConfig = {
async: true,
baseUrl: '/js'
packages: [{
name: "djt2",
location: 'djt2'
}, {
name: "another",
location: 'another'
}]
};

Passing bootstrapped variables and JSON to require.js

What is the best practice for passing bootstrapped variables within the rendered page (i.e. JSON data or config variables) to require.js so they can be checked for an used by dependancies?
It looks like this could be done by checking the window object (i.e. window.bootstrapped_models but that does not seem very optimal.
app.html - example data within the HTML document
<script>
var config = {
"isAdmin": true,
"userId": 1
};
var bootstrapped_models = {
"groups": [
{
"id": 1,
"name": "Foo"
},
{
"id": 2,
"name": "Bar"
}
]
}
</script>
app.js - example app using require()
require(['jquery', 'GroupCollection'], function($, GroupCollection) {
// extend default config
if (config) {
$.extend(defaults, config);
}
// use bootstrapped JSON here
var collection = new GroupCollection;
if (bootstrapped_models.groups.length > 0) {
collection.add(bootstrapped_models.groups);
}
});
The answer from #timDunham was helpful, but it felt a little overly complicated to me. Playing around with require.js and Lithium (PHP MVC) I came up with the following. It's simple and has worked in each instance I've run into.
<script type="text/javascript">
define('bootstrapData', function () {
return <?php echo json_encode($bootstrapData) ?>;
});
</script>
Which is then available by doing the following:
define(['bootstrapData'], function(bootstrapData) {
console.log(bootstrapData); // Will output your bootstrapped object
});
Obviously the way I'm bringing the data in is language specific, but the rest should be useful regardless of your situation.
Not sure if my method is best practice but I do something a lot like what you are doing except instead of butting the bootstrapped models on the global object, I create a define for it in my HTML page:
<script type="text/javascript">
define("bootstrappedModelJson", function() {
return #Html.Action("Controller", "RenderModel");
});
require({
baseUrl: //etc.
}, ["app"],
function(){
});
</script>
then I have a js file called current.model that can be required by other modules and looks like this:
define(
[
'require',
'model'
],
function (require, Model)
{
var json= require("bootstrappedModelJson");
return new Model(json);
});
You can solve problems with optimize/build by disabling the bootstrapData in your build.js
Like this:
paths: {
bootstrapData: "empty:",

Categories

Resources