How to move/copy files during ember build - ember-cli

I wanted to moved some files between two folders in an ember app when build is run but I am having no success.
//ember-cli-build.js
module.exports = function (defaults) {
var app = new EmberApp(defaults, {
hinting: false,
minifyCSS: {
enabled: true
},
bless: {
enabled: true
}
});
var moveFile = new Funnel('./app/locales', {
srcDir: 'en',
files: ['test.js'],
destDir: 'en_US',
allowEmpty: true
});
return new MergeTrees([moveFile, app.toTree()]);
};
When I do the build, I get no errors but the file is also not getting moved.
UPDATE: I am trying to move the file before ember-cli puts compiles the files and puts it in the dist folder

You can use broccoli-static-compiler https://github.com/joliss/broccoli-static-compiler
In brocfile.js ( ember-cli-build.js )
// at top of file
var pickFiles = require('broccoli-static-compiler');
var mergeTrees = require('broccoli-merge-trees');
// inside exporting function
const bootstrapMap = pickFiles('bower_components/bootstrap/dist/css/',
{
srcDir: '/',
files: ['bootstrap.css.map'],
destDir: '/assets'
});
// and so on, as many times as you need
const zeroClipboard = pickFiles('bower_components/zeroclipboard/dist/',
{
srcDir: '/',
files: ['ZeroClipboard.swf'],
destDir: '/assets'
});
// at the end
return mergeTrees([
app.toTree(),
bootstrapMap,
zeroClipboard,
// ...
], { overwrite: true });

With 'broccoli build', your app is build into a destination folder, so broccoli is the wrong tool to move files in an existing folder structure. Here I'm assuming it's run with something like 'broccoli build dist' on the command line which will create a new folder 'dist' with the results of the build, and error out if the directory already exists.
So let's say your project directory looks like this:
.
|--brocfile.js
|--app/
|--locales/ <----- funnel root
|--en/ <----- srcDir
|--test.js <----- file
When you funnel from ./app/locales, your srcDir and files` are relative to that as a root. The output tree is then put into the 'destDir' under the build output directory. What that will do is this:
.
|--brocfile.js
|--app/ <----- not changed
|--dist/ <----- build output directory
|--en_US <----- destDir
|--test.js <----- file
I think you want your destDir to be locales/en_US or app/locales/en_US.

Related

ESlint IDE not formatting in Sibling Directory

I feel like I must be missing something really simple here, but for all my searching and going over the docs, I just cannot find a solution to this problem.
I have an inherited file structure (which at the moment cannot change) that looks like this:
- Folder 1
-Web Files Folder
- Folder 2 (root)
- .eslintrc.js
Folder 1 and 2 are siblings of one another, my main set of js, jsx, ts and tsx are set up in the Web Files Folder, and my eslint and webpack configs, package.json and entry point files are all in Folder 2.
I cannot seem to get the IDE (in this case VS Code) to effectively lint the files within the Web Files Folder. I have tried a whole host of things, the latest of which was trying to use overrides in my .eslintrc.js file to point to the relevant directory:
module.exports = {
env: {
browser: true,
es6: true,
jest: true,
jquery: true,
node: true
},
extends: [
'eslint:recommended',
'eslint-config-prettier',
'plugin:#typescript-eslint/recommended',
'plugin:react/recommended',
'plugin:jsx-a11y/recommended',
'prettier',
'prettier/#typescript-eslint'
],
parser: '#typescript-eslint/parser',
parserOptions: {
jsx: true,
ecmaVersion: 2020
},
plugins: ['#typescript-eslint', 'react', 'prettier', 'jsx-a11y', 'jest'],
root: true,
rules: {
'array-callback-return': 0,
'consistent-return': 0,
...
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
}
},
react: {
version: 'detect'
}
}
overrides: [
{
files: ['../Folder 1/Web Files Folder/*.js', '../Folder 1/Web Files Folder/*.jsx', '../Folder 1/Web Files Folder/*.ts', '../Folder 1/Web Files Folder/*.tsx']
},
]
};
This results in the error in the Eslint console: Invalid override pattern (expected relative path not containing '..')
However nothing I have tried works. I am not worried about the linting in the build, only getting the errors to appear in the IDE and resolve on save (which works perfectly if I place the files within Folder 2)
I am looking for a solution which I can use in my eslintrc.js file rather than any changes to settings in the IDE if possible. Something like
project: ['./**/*', '../Folder 1/Web Files Folder/**/*']

How we can generate html report in cucumber latest version(3.2.0) with protractor-cucumber framework

Since cucumber 3 removed the registerHandler and registerListener , how we can generate html report in cucumber 3.2.0.I have used below code for generating json report in cucumber 2.
defineSupportCode(function({ registerListener }) {
var JsonFormatter = new Cucumber.JsonFormatter();
JsonFormatter.log = function(string) {
var outputDir = 'testreports/report';
var fileName = 'cucumber-report.json';
var targetJson = path.resolve(outputDir, fileName);
if (fse.existsSync(outputDir)) {
fse.moveSync(outputDir, outputDir + '_' + moment().format('YYYYMMDD_HHmmss'), {
overwrite: true
});
}
fse.outputFileSync(targetJson, string);
};
registerListener(JsonFormatter);
});
and used below code for html report
defineSupportCode(function({ registerHandler }) {
registerHandler('AfterFeatures', function(features, callback) {
var options = {
theme: 'bootstrap',
jsonFile: 'testreports/report/cucumber-report.json',
output: 'testreports/report/cucumber-report.html',
reportSuiteAsScenarios: true,
};
reporter.generate(options);
callback();
});
});
Thanks in advance.
You have to do following changes:
1) set cucumberOpts.format in protractor conf file
cucumberOpts: {
format: ["json:reports/report/cucumber/cucumber-report.json"],
here reports/report/cucumber/cucumber-report.json is the cucumber json file path, you must specify a path at here.
framework will generate it automatically with results' json data as file content when all scenarios execute complete.
2) create parent folder of cucumber json file path before test framework load if parent folder not exist
Option 1: put create parent folder code at head of protractor conf file.
Option 2: create a Protractor plugin implement interface: setup(), which will be executed before test framework load.
// plugin: create-report-folder.js
var moment = require("moment");
var fse = require("fs-extra");
module.exports = {
setup: function() {
var reportDir = this.config.options.reportDir;
if (fse.existsSync(reportDir)) {
fse.moveSync(
reportDir,
reportDir + "_" + moment().format("YYYYMMDD_HHmmss"),
{ overwrite: true}
);
}
fse.mkdirsSync(reportDir);
}
};
Note: both options need to use Sync api to create folder.
3) create Protractor plugin implement interface: postResults which will be executeed after all scenarios execute complete.
// plugin: cucumber-html-reporter.js
var reporter = require("cucumber-html-reporter");
module.exports = {
postResults: function() {
var options = {
theme: "bootstrap",
jsonFile: this.config.options.jsonFile,
output: this.config.options.htmlFile,
reportSuiteAsScenarios: true
};
reporter.generate(options);
}
};
Note: I tried generate cucumber html report in cucumber AfterAll hook, but failed, seems Cucumber JsonFormater generate cucumber json file is Async, when AfterAll hook start execute, cucumber json file have not create yet.
I'm keeping look into formatOption, should be a way to change JsonFormater generate cucumber json file to Sync, then we can use AfterAll hook.
4) set plugins in protractor conf file
// protractor conf file
exports.config = {
plugins: [
// plugin to create report parent folder
{
path: "supports/create-report-folder.js",
options: {
reportDir: "reports/report/cucumber"
}
}
// plugin to generate cucumber html report
{
path: "supports/cucumber-html-reporter.js",
options: {
jsonFile: "reports/report/cucumber/cucumber-report.json",
htmlFile: "reports/report/cucumber/cucumber-report.html"
}
}
]
A workable scaffold for Protractor + Cucumber4 + HTML Report at my github
The scaffold for Protractor + Cucumber3 + HTML Report on my local has some dependency campatible issue, I'm looking into that in case you must use Cucumber 3.
5) If you use multiCapabilities, you can use below package to generate report:
protractor-multiple-cucumber-html-reporter-plugin
If the location of protractor.conf.js is not at the same level as node_modules then the cucumberOpts.format path would be relative to its current file location and the protractor-multiple-cucumber-html-reporter-plugin looks for the json files relative to parent root folder and warns about json file is not found.
To solve this provide absolute path of the json file to cucumberOpts.format like below. This is applicable if you're using cucumber for e2e testing in Angular applications where the protractor.conf.js is normally present inside e2e folder.
cucumberOpts: {
require: [path.resolve(process.cwd(), 'e2e/steps/*.ts')],
format: 'json:'+ path.resolve(process.cwd() + '/reports/cucumber-ui-reports.json')
}

Ionic serve: how to rerun gulp task

I'm kinda new to ionic and gulp.
I was able to configure the ionic.project file in order to run the gulp tasks when I first run ionic serve.
But now when I change files I want that the gulp task will run again.. But this doesn't happen.. Is there a way to do that?
This is my ionic.project file:
{
"name": "test",
"app_id": "",
"gulpStartupTasks": [
"default"
],
"watchPatterns": [
"src/**/*",
"src/*",
"www/**/*",
"!www/lib/**/*"
]
}
I expected that when some file changes that match the wtachPatterns
it will invoke the gulp watch task, but this doesnt happen (I see that ionic see that the file has changed but nothing happen.)
this the the gulp watch task:
gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.script, ['script']);
});
Basically the task is minifying all the JS files and all the sass/scss files
and the index.html is looking on the minified files. so if the gulp task isn't invoked there are no changes in the minified file and I need to run ionic serve all over again.. Is there a proper way to do that?
UPDATE:
This is the complete gulpfile
var gulp = require('gulp');
var gutil = require('gulp-util');
var bower = require('bower');
require('require-dir')('./gulp/tasks');
var paths = {
sass: ['./scss/**/*.scss'],
style: ['./src/**/*.scss'],
script: ['./src/app.js'],
html:['./src/*.html']
};
gulp.task('default', ['sass', 'script','watch', 'html', 'style']);
gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']);
gulp.watch(paths.script, ['script']);
});
gulp.task('install', ['git-check'], function() {
return bower.commands.install()
.on('log', function(data) {
gutil.log('bower', gutil.colors.cyan(data.id), data.message);
});
});
gulp.task('git-check', function(done) {
if (!sh.which('git')) {
console.log(
' ' + gutil.colors.red('Git is not installed.'),
'\n Git, the version control system, is required to download Ionic.',
'\n Download git here:', gutil.colors.cyan('http://git- scm.com/downloads') + '.',
'\n Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
);
process.exit(1);
}
done();
});
And this is an example of one of the files who have the actual task:
var browserify = require('browserify');
var gulp = require('gulp');
var source = require('vinyl-source-stream');
var stringify = require('stringify');
var paths = ['./src/app.js'];
gulp.task('script', function() {
return browserify(paths, {debug: true})
.transform(stringify(['.html']))
.bundle()
.pipe(source('app.js'))
.pipe(gulp.dest('./www/js'));
});
Well So the problem was with paths I watched.
I removed the ./ and now its working
First thing first, you misunderstand the watchPatterns is for livereload, which means, the web will refresh if there is any file changed on watch. It's definitely not having any relation to gulp.
Read more at: http://ionicframework.com/docs/cli/test.html
To watch for file changes with watch, update your watch task, which is
gulp.task('watch', function() {
gulp.watch(paths.sass, ['sass']); <-- any file in paths.sass changed will trigger `gulp sass`
gulp.watch(paths.script, ['script']); <-- any file in paths.script changed will trigger `gulp script`
});
So if you want to watch more files to be processed by Gulp, just add tasks and watch them in gulp watch.
Oh hey, you are watching only files in ./scss/**/*.scss and ./src/app.js. Add more if you wish.

Ember-CLI: How to exclude a folder within /public from build

I have Ember-CLI-application with a few thousand static assets (~1GB) and my build time is now about 30sec.
I have tried in my Brocfile.js without success:
var app = new EmberApp({
fingerprint: {
enabled: false,
exclude: ['large_folder']
}
});
Build time with assets: TreeMerger | 29738ms
/ without: TreeMerger | 9182ms.
Any ideas how to speed up the build?
(Ember-CLI 0.1.7)
You have enabled:false, you can set it to true.
Also, on exclude, would be better to say the path for the folder, such as:
If you have a large folder inside images, then you can do it like this:
fingerprint: {
exclude: ['assets/images/large_folder/', 'assets/uploads/other_large_folder/]
}
My own solution is currently to use the postBuild-hook and a symbolic link to the assets folder.
lib/link-after-build/index.js:
var fs = require('fs');
var path = require('path');
module.exports = {
name: 'link-after-build',
// link additional assets after build
postBuild: function(result) {
if (process.env.EMBER_ENV === 'development') {
var buildDirPath = result.directory;
var srcpath = path.resolve("/opt/local/apache2/htdocs/large_folder");
var dstpath = path.resolve(buildDirPath + "/large_folder");
fs.symlinkSync(srcpath,dstpath);
}
}
};

How can I use grunt-regarde with grunt-contrib-coffee to only compile changed .coffee files?

My project has over 300 CoffeeScript files, so it takes several seconds to recompile everything. I'd like to only recompile the changed CoffeeScript files.
Here's the closest I've come so far, but the "frontend-src/coffeescript" folder structure is being copied from the src directory to the dest directory.
coffee: {
changed: {
expand: true,
cwd: './',
src: ['<%= grunt.regarde.changed %>'],
dest: 'public/js/',
ext: '.js'
}
},
regarde: {
coffee: {
files: 'frontend-src/coffeescript/**/*.coffee',
tasks: ['coffee:changed', 'livereload']
}
}
This is all with Grunt 0.4.0. Any help would be greatly appreciated!
I had this issue myself and I was able to come up with a solution for it inspired by the comments on this issue:
https://github.com/gruntjs/grunt-contrib-watch/issues/14
It is actually for the grunt-contrib-watch plugin, but it should also work for grunt-regarde, as it has similar events.
The idea is to bind a callback the watch event, in which you add a new task to the grunt configuration with the changed file's path, then run it.
From my Gruntfile.coffee:
coffee:
app:
expand: true
cwd: 'app/'
src: ['*.coffee',"**/*.coffee"]
dest: './public/temp'
ext: '.js'
watch:
coffee:
files: ['app/**/*.coffee']
tasks: ['livereload']
options:
nospawn: true
grunt.event.on 'watch', (action, filepath) ->
cwd = 'app/'
filepath = filepath.replace(cwd,'')
grunt.config.set('coffee',
changed:
expand: true
cwd: cwd
src: filepath
dest: './public/temp'
ext: '.js'
)
grunt.task.run('coffee:changed')
The nospawn is important for the watch task, so it runs the new task before the livereload task. I am pretty sure regarde does not spawn child processes by default.
I've had the same issue. I solved it using the regarde:file event.
First I listen for changed files by using the regarde:file event. This will feed the configuration for two tasks: clean:coffee if files in the source location has been deleted and coffee:refresh if files have been changed/added.
Then the regarde task will trigger its tasks, which will launch refresh:coffee (not to be mistaken from coffee:refresh). This task will check if there is configuration added for clean:coffee and/or for coffee:refresh and run these tasks if needed (via function grunt.task.run). If will also reset the flag, which will cause the next received regarde:file event to cleanup the configuration again.
In depth explanation:
First of all, regarde config:
// watch for changed coffeescript files
coffee: {
files: 'path/to/coffee/**/*.coffee',
tasks: ['refresh:coffee', 'livereload']
},
Then I listen for the regarde:file event, where I update the clean:coffee and coffee:refresh file lists in their config.
Feed the configuration based on the regarde:file event:
grunt.event.on('regarde:file', function (status, target, filepath) {
if (resetFlag) {
// clean file list from previous cycle, so clean clean:coffee and coffee:refresh
// file lists
...
resetFlag = false;
}
if (status === 'deleted') {
if (filepath) {
// calculate filepath's destination and
// add it to clean:coffee filelist
}
} else {
if (!grunt.file.isDir(filepath)) {
// add filepath to coffee:refresh filelist
}
}
}
It is easy to update configuration via grunt.config() function. Below the code snippets to feed coffee:refresh and clean:coffee.
Adding config to coffee:refresh:
var config = grunt.config('coffee') || {};
var value = config.refresh || {};
value.files = value.files || [];
...
var cwd = path.dirname(filepath),
src = path.basename(filepath),
dest = cwd.replace('path/to/source', 'path/to/dest');
value.files.push({
expand:true,
src:src,
dest:dest,
cwd:cwd,
ext:'.js'
});
grunt.config('coffee', config);
Adding config to clean:coffee:
var cwd = path.dirname(filepath),
src = path.basename(filepath),
dest = cwd.replace('path/to/source', 'path/to/dest');
value.src.push(path.join(dest, src.replace('coffee', 'js')));
// clean only what has been removed
config = grunt.config('clean') || {};
config.coffee = value;
grunt.config('clean', config);
Task refresh:coffee gets triggered:
grunt.registerMultiTask('refresh', 'refreshing the changed file(s)', function () {
this.requires('regarde');
var tasks = [];
var clean = grunt.config('clean');
// check if there is clean:refresh config available
if (clean && clean[this.target]) {
tasks.push('clean:' + this.target);
}
var config = grunt.config(this.target);
// check if there is coffee:refresh config available
if (config && config.refresh) {
tasks.push(this.target + ':refresh');
}
// run the tasks
grunt.task.run(tasks);
// set the resetFlag back to true
resetFlag = true;
});
grunt.regarde.changed is an array correct?
Should src: ['<%= grunt.regarde.changed %>']
be src: '<%= grunt.regarde.changed %>'
I looked through grunt-contrib-coffee's source for a second to see if it could be not correctly handling whatever you're giving it. Looked kind of likely that the stringified array you're giving it, doesn't get caught and dealt with.
I think what you're passing accidentally may be: src: [ '[path1, path2, path3, etc]' ]
If I'm way off base, leave a comment and I'll delete this answer.