Scaffolding - Extend a js object - javascript

I'm working with scaffolt (https://www.npmjs.com/package/scaffolt) to generate some default templates.
I am using handlebars to handle the template.
This works as expected, but i would also like ot extend a JS object while scaffolding.
Basically, i have an object that looks like this:
module.export = {
name: {
"main": ["test"],
"plus": ["test", "test2"],
},
value: {
"test": [...],
"test2": [...]
}
};
and i would like to extend this when i run scaffold and append to both name and value the name of the template i'm scaffolding.
So for instance, if i run scaffolt -g generators template abc the js file will look like this:
module.export = {
name: {
"main": ["test"],
"plus": ["test", "test2"],
"abc" : []
},
value: {
"test": [...],
"test2": [...],
"abc": []
}
};
(where abc was added)
Is it possbile?
Thanks

At the end i managed to solve this but running as a "callback" a postscript.
Basically, in the package.json file i added the command i need to run and i callled it "scaffolt". Then, i've added a postscaffolt command to run a gulp task to inject the stuff i need in place.
The package.json file look something like this:
scripts: {
"scaffolt" "....",
"postscaffolt": "..."
}

Related

Dynamically set script tag through Grunt based on ENV

During my Grunt build process, I would like to set the script tag in my index.html which references the Google Maps API dynamically based on process.env.NODE_ENV.
Something like:
let googleMapsUrl;
if (process.env.NODE_ENV === 'development') {
googleMapsUrl = '//maps.googleaps.com/maps/api/js?v=3.exp&libraries=visualization';
} else {
googleMapsUrl = `//maps.googleaps.com/maps/api/js?key=${process.env.GOOGLE_MAPS_API_KEY}v=3.exp&libraries=visualization`;
}
My question is how do I then insert googleMapsUrl into a script tag in index.html like so: <script src=googleMapsUrl></script>
There are many options that you could use. From simple, like grunt-replace to more advanced ones like grunt-processhtml. I will describe the first one as it’s a good option for simple tasks and requires just a simple configuration.
Using grunt-replace
grunt-replace will search for simple variable definitions like ##foo in your source files, and replace those variables with your supplied value or the returning value from a callback.
First install the plugin using npm install grunt-replace --save-dev
Then configure the task as follows:
replace: {
dist: {
options: {
patterns: [
{
match: 'gmaps',
replacement: function() {
var googleMapsUrl;
if(process.env.NODE_ENV === 'development') {
googleMapsUrl = '//maps.googleaps.com/maps/api/js?v=3.exp&libraries=visualization';
} else {
googleMapsUrl = '//maps.googleaps.com/maps/api/js?key=' + process.env.GOOGLE_MAPS_API_KEY + 'v=3.exp&libraries=visualization';
}
return googleMapsUrl;
}
}
]
},
files: [
{
expand: true,
flatten: true,
src: ['path/to/your/source/file.html'], dest: 'destination/folder/'
}
]
}
}
Load the plugin using grunt.loadNpmTasks('grunt-replace') and then add it to your build process.
On your source files just add the defined variable as your script source:
<script src="##gmaps"></script>
The task will replace ##gmaps with the returning value from the defined callback.
Hope it helps.
More about plugin can be found here.

browserify module loading into function

i have an app.js which is the main file for my webapplication. It initialize the UI and loads different modules. At the moment it is one big file with all the code. I want to refactor this and split the functions into independant modules and then bundle them with browserify. App.js has a dependency to jquery and some modules too.
i have defined the browsersection in package.json
"browser": {
"jquery": "./node_modules/jquery/dist/jquery.js",
"jquery-ui": "./static/js/vendor/jquery-ui-1.12.1/jquery-ui.min.js",
"App": "./static/js/app.js",
"myModule": "./static/js/myModule.js"
}
Also i use browserify-shim to load some jquery plugins which can't be loaded without.
For browserify-shim i've defined a config section:
"browserify": {
"transform": [
"browserify-shim"
]
},
"browserify-shim": {
"jquery": "$",
"jquery-ui": {
"depends": [
"jquery:$"
]
},
"bootstrap": {
"depends": [
"jquery:$"
]
},
"dropdown": {
"depends": [
"jquery:$"
]
},
"App": {
"exports": "App",
"depends": [
"jquery:$"
]
},
}
My entry.js file
var $ = require("jquery");
window.$ = window.jQuery = jQuery;
var App = require('./app.js');
require('./some jquery plugins');
In my app.js
var App = function(){
some code...
var myModule = require('./myModule.js');
myModule();
some code...
return {
init: function() {
someFunctions();
someFunctions();
}
}
}();
$(function(){ App.init(); });
In my myModule.js
module.exports = function() {
some code with jquery...
};
It bundles correctly but if i load the page i'll get
app.js:14Uncaught Error: Cannot find module './myModule.js'
And if i look in the sources in my browser it tells me:
var myModule = __browserify_shim_require__('./myModule.js');
so it seems browserify can't load the module correctly in this scope.
What am i doing wrong? Does i forget something? I think i don't need to shim my own module because i can use commonjs format for browserify. Do i have to use another pattern in this context?
Thanks for help in advance!
Edit:
I don't have a solution yet. i refactored the whole thing and now i don't need browserify shim anymore. You can add most plugins without it.

Referencing custom library in SAPUI5 causes 404 when loading the library

We wrote a custom library that we now want to reference in our main application.
Thus we added the following two entries to the consumer's neo-app.json:
{
"path": "/webapp/resources/some/lib",
"target": {
"type": "application",
"name": "somedemolib"
},
"description": "..."
}, {
"path": "/resources/some/lib",
"target": {
"type": "application",
"name": "somedemolib"
},
"description": "..."
}
and the following to the manifest.json of the libs consumer:
"dependencies": {
"minUI5Version": "1.30.0",
"libs": {
...
"some.lib": {
"minVersion": "1.0.0"
}
}
},
However upon loading the web-app I can see a HTTP404 when trying to load the library under the following path:
Uncaught Error: failed to load 'some/lib/library.js' from ../../resources/some/lib/library.js: 404 - Not Found
You have to declare your custom scripts in the first lines of your components.js
First of all you have to declare the path of your custom lib folder:
https://sapui5.netweaver.ondemand.com/sdk/docs/api/symbols/jQuery.sap.html#.registerModulePath
jQuery.sap.registerResourcePath("libs/custom", "/scripts/customlibs");
After that call you are able to load your script from that path with this call:
jQuery.sap.require("libs.custom.nameofyourscript");
"libs.custom" points to that folder you have registered previously and then your are able to import the script by its name. So your components.js looks like this:
jQuery.sap.registerResourcePath("libs/custom", "/scripts/customlibs");
jQuery.sap.require("libs.custom.nameofyourscript");
// Now the declaration of the components starts
sap.ui.core.UIComponent.extend("yourappname.Component", {
// ...

Unable to get Jasmine working with basic library

I'm new to using Jasmine and Grunt (and StackOverflow). I'm trying to setup the most basic of projects. However, when I run my grunt task, I get an error that says:
Running "jasmine:testShared" (jasmine) task
Testing jasmine specs via PhantomJS
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\g.js:1
>> Error: notloaded: Module name "../" has not been loaded yet for context: _. Use require([])
>> http://requirejs.org/docs/errors.html#notloaded at
>> ..\..\C:\Tests\jasmine\_SpecRunner.html:21
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:12 v
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:26 h
>> ..\..\C:\Tests\jasmine\.grunt\grunt-contrib-jasmine\require.js:31
>> ..\..\C:\Tests\jasmine\node_modules\glob\examples\usr-local.js:1
>> ReferenceError: Can't find variable: module at
>> ..\..\C:\Tests\jasmine\node_modules\glob\glob.js:37
>> Error caught from PhantomJS. More info can be found by opening the Spec Runner in a browser.
Warning: SyntaxError: Parse error Use --force to continue.
Aborted due to warnings.
I can't figure out what I'm doing wrong. The code for this project can be found here. My file structure looks like this:
/jasmine
/node_modules
/shared
/modules
myModule.js
/tests
/unit
myModule.tests.js
/tasks
/options
jasmine.js
protractor.js
test_task.js
_SpecRunner.html
gruntfile.js
package.json
My package.json file looks like this:
{
"name": "MyApp",
"version": "1.0.0",
"dependencies": {
"async": "~0.9.0",
"glob":"~4.0.3",
"grunt":"~0.4.0",
"grunt-cli":"~0.1.13",
"grunt-contrib-connect":"0.7.1",
"grunt-contrib-jasmine":"~0.6.5",
"grunt-protractor-runner":"1.0.1",
"grunt-start-webdriver":"0.0.2",
"grunt-template-jasmine-requirejs":"0.2.0",
"jasmine-core":"2.0.0",
"jasmine-node":"2.0.0-beta3",
"load-grunt-tasks":"0.2.x",
"lodash":"~2.4.1",
"phantomjs": "1.9.7-14",
"selenium-webdriver":"2.42.1",
"time-grunt":"~0.3.2"
}
}
My gruntfile.js file looks like this:
'use strict';
module.exports = function (grunt) {
var config = {
name: 'MyApp',
pkg: grunt.file.readJSON('package.json'),
baseDir: '.'
};
// load all grunt task details
require('load-grunt-tasks')(grunt);
// show elapsed time at the end
require('time-grunt')(grunt);
// load task definitions
grunt.loadTasks('tasks');
// Utility function to load plugin settings into config
function loadConfig(config,path) {
require('glob').sync('*', {cwd: path}).forEach(function(option) {
var key = option.replace(/\.js$/,'');
// If key already exists, extend it. It is your responsibility to avoid naming collisions
config[key] = config[key] || {};
grunt.util._.extend(config[key], require(path + option)(config,grunt));
});
}
// Merge that object with what with whatever we have here
loadConfig(config,'./tasks/options/');
grunt.loadNpmTasks('grunt-start-webdriver');
grunt.loadNpmTasks('grunt-protractor-runner');
// pass the config to grunt
grunt.initConfig(config);
};
myModule.js looks like this:
'use strict';
var _ = require('lodash');
_.mixin({
'myFunction' : function(s) {
return 'Hello ' + s;
}
});
module.exports = _;
myModule.tests.js looks like this:
'use strict';
describe('myModule', function() {
it('should work', function() {
expect(true).toBe(true);
});
});
test_task.js looks like this:
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.registerTask('test-shared', [
'jasmine:testShared'
]);
};
jasmine.js looks like this:
module.exports = function(config) {
return {
testShared: {
src: "shared/modules/*.js",
options: {
specs: "shared/tests/unit/**.tests.js",
vendor: "node_modules/**/*.js",
template: require('grunt-template-jasmine-requirejs')
}
}
};
};
protractor.js looks like this:
module.exports = function(config) {
return {
testShared: {
options: {
configFile: "shared/tests/unit/config.js"
}
}
};
};
I've spent two days on this. I have no idea what I'm doing wrong. I feel like I've followed the examples online. I feel like there is something stupid I'm overlooking. Can someone please show me what I'm doing wrong?
It's very hard to diagnose without a running example but that error is caused by RequireJS. It happens when you do require('something') without having loaded it. Loading is asynchronous so you either need to do require['lodash'], function(_) { do stuff }. Or the preferred define syntax:
define([
'lodash'
], function(_) {
'use strict';
_.mixin({
myFunction: function(s) {
return 'Hello ' + s;
}
});
return _;
});
With a test you would typically use the same structure and pull in the module you are testing in the define. You would set it up so the path to required files is the same as in the app.
To help more we need a running example.
My colleague made a good boilerplate using grunt/jasmine/requirejs maybe you can get some good practices from there: https://github.com/mderrick/backbone-boilerplate
Your directory structure is quite confusing have you considered simplifying it?
- Use a single Gruntfile.js - don't fragment unless your project is very big
index.html
Gruntfile.js
app/
test/
That is all you really need to get going. In app it could look something like:
app/app.js <-- entry point
app/modules/...

RequireJS: how to dynamically define/add packages

I've got a config for requirejs that is shared with multiple applications. When the app is loaded, the app receives an object with the layout of the app (and various other params). I want to use that object to define modules/packages for the app.
siteMap = { modules: { "foo": { … }, "bar": { … }, … }, other: "stuff" }
/shared/
libs/
bootstrap.js
jquery.js
…
app.js
/$appName/
foo/
index.html
edit.html
main.js
bar/
index.html
stuff.html
main.js
…
I imagine there must be a way to add packages that goes something like this:
// /shared/app.js
require.config({
paths: {
"bootstrap": ["//hosted.bootstrap.js","/shared/libs/bootstrap.js"],
"jquery": ["//hosted.jquery.js","/shared/libs/jquery.js"],
"siteMap": "//appName.example.com/api/siteMap"
},
…
});
require(['jquery','siteMap','bootstrap'], function($,siteMap) {
for ( var module in siteMap.modules )
{
require.config.packages[module] = siteMap.modules[module];
// OR
require.addPackage(siteMap.modules[module]);
}
});
You could nest another require() call to load the additional modules after siteMap tells you what should be loaded. Something like this:
require(['jquery','siteMap','bootstrap'], function($,siteMap) {
// .map assumes modern browser or use of something like es5-shim
var modulesToLoad = siteMap.modules.map(function(m) { return m + '/main'; } );
require(modulesToLoad, function() {
// kick off the rest of app logic
});
});

Categories