Folder copy including files in gulp - node.js

I'm trying to copy 2 folders onto a single build folder and for the second path I want to copy whole libs folder including libs folder itself to destination.
var paths = {
'standalone' : '../app-ui/assets/js',
'standalone_libs' : '../app-ui/libs',
'destination' : '../SomeFolder'
}
gulp.task('folder-copy', function() {
return gulp.src([paths.standalone_js + '/*', paths.standalone_libs + '/*']).pipe(gulp.dest(paths.destination));
});
Structure according to code
->SomeFolder
->app.js [ file from ../app-ui/assets/js ]
-> angular/angular.js [ file from ../app-ui/libs ]
-> lodash/lodash.js [ file from ../app-ui/libs ]
Actual Structure wanted
->SomeFolder
->app.js [ file from ../app-ui/assets/js ]
-> libs
-> angular/angular.js [ file from ../app-ui/libs ]
-> lodash/lodash.js [ file from ../app-ui/libs ]

You could specify the base in gulp.src :
return gulp.src(['some/path/app/*', 'libs/**/*'], {base: '.'})
.pipe(gulp.dest('build'));
This will copy all your files in libs, with the directory structure intact. But the directory structure will be preserved for app.js also...
I would just do two separate copy.
You can use merge-stream. There's a recipe in gulp repository. It would boil down to something like this :
var merge = require('merge-stream')
var libs= gulp.src('libs/**/*', {base: '.'})
.pipe(gulp.dest('build'));
var app = gulp.src('app.js')
.pipe(gulp.dest('build'));
return merge(libs, app);

Try removing the /* because this means the whole content inside the folder is what you want.
So for the libs, I would not add the /* like follows
return gulp.src([paths.standalone_js + '/*', paths.standalone_libs ]).pipe(gulp.dest(paths.destination));

What about changing this:
var paths = {
'standalone' : '../app-ui/assets/js',
'standalone_libs' : '../app-ui/libs',
'destination' : '../SomeFolder'
}
to this:
var paths = {
'standalone' : '../app-ui/assets/js',
'standalone_libs' : '../app-ui/(libs)',
'destination' : '../SomeFolder'
}

Related

Codeigniter 4 View file invalid

I am using codeigniter 4 with modules.I am getting error invalid file :Admin/valid_faq.php
What is wrong in the view path?
My Module structure is like below
app
--modules
-- Faq
--controller
--Models
--Views
--Admin
--view_faq
echo view('layout/header', $data);
echo view('layout/sidebar');
echo view('Admin/view_faq', $data);
echo view('layout/footer');
I have gave the full path then also it doesn't work.
echo view('App/Modules/Faq/Views/Admin/view_faq');
echo view('Modules/Faq/Views/Admin/view_faq');
I have added to Autoload as well
public $psr4 = [
APP_NAMESPACE => APPPATH, // For custom app namespace
'Config' => APPPATH . 'Config',
'Modules' => APPPATH . 'Modules',
];
When I checked the view file
SYSTEMPATH\Common.php : 1121 — CodeIgniter\View\View->render ( arguments )
F:\xampp\htdocs\modularcms\app\Config/../Views/Modules/Faq/Views/Admin/view_faq.php
This is working
echo view('../Modules/Faq/Views/Admin/view_faq', $data);
my view directory in the paths
public $viewDirectory = __DIR__ . '/../Views';
Error function
public static function renderer(string $viewPath = null, $config = null, bool $getShared = true)
{
if ($getShared)
{
return static::getSharedInstance('renderer', $viewPath, $config);
}
if (is_null($config))
{
$config = new \Config\View();
}
if (is_null($viewPath))
{
$paths = config('Paths');
$viewPath = $paths->viewDirectory;
}
return new \CodeIgniter\View\View($config, $viewPath, static::locator(), CI_DEBUG, static::logger());
}
I'm not clear about your modules directory. Let’s say you want to keep a simple Faq module that you can re-use between applications. You might create folder with name, faq, to store all of your modules within. You will put it right alongside your app directory in the main project root:
/faq // modules directory
/app
/public
/system
/tests
/writable
Open app/Config/Autoload.php and add the Faq namespace to the psr4 array property:
$psr4 = [
'Config' => APPPATH . 'Config',
APP_NAMESPACE => APPPATH, // For custom namespace
'App' => APPPATH, // To ensure filters, etc still found,
'Faq' => ROOTPATH.'faq'
];
A common directory structure within a module will mimic the main application folder:
/faq
/modules
/Config
/Controllers
/Database
/Helpers
/Language
/Libraries
/Models
/Views
/Admin
/view_faq
View:
echo view('Faq\Modules\Views\view_faq', $data);
It's probably already too late, but maybe others - like me - are looking for it. The solution was there for me:
Write the folder in the Views folder in lower case and put a double backslash behind it. So in your example:
echo view('Modules\Faq\Views\admin\\view_faq');

Conditional settings for Gulp plugins dependent on source file

The plugin gulp-pug allows to pass global variables to pug files via data property.
What if we don't need full data set in each .pug file? To implement conditional data injection, we need to access to current vinyl file instance inside pipe(this.gulpPlugins.pug({}) or at least to know the source file absolute path. Possible?
const dataSetForTopPage = {
foo: "alpha",
bar: "bravo"
};
const dataSetForAboutPage = {
baz: "charlie",
hoge: "delta"
};
gulp.src(sourceFileGlobsOrAbsolutePath)
.pipe(gulpPlugins.pug({
data: /*
if path is 'top.pug' -> 'dataSetForTopPage',
else if path is 'about.pug' -> 'dataSetForAboutPage'
else -> empty object*/
}))
.pipe(Gulp.dest("output"));
I am using gulp-intercept plugin. But how to synchronize it with gulpPlugins.pug?
gulp.src(sourceFileGlobsOrAbsolutePath)
.pipe(this.gulpPlugins.intercept(vinylFile => {
// I can compute conditional data set here
// but how to execute gulpPlugins.pug() here?
}))
// ...
It was just one example, but we will deal with same problem when need to conditional plugins options for other gulp plugins, too. E. g:
.pipe(gulpPlugins.htmlPrettify({
indent_char: " ",
indent_size: // if source file in 'admin/**' -> 2, else if in 'auth/**' -> 3 else 4
}))
You'll need to modify the stream manually - through2 is probably the most used package for this purpose. Once in the through2 callback, you can pass the stream to your gulp plugins (as long as their transform functions are exposed) and conditionally pass them options. For example, here is a task:
pugtest = () => {
const dataSet = {
'top.pug': {
foo: "alpha",
bar: "bravo"
},
'about.pug': {
foo: "charlie",
bar: "delta"
}
};
return gulp.src('src/**/*.pug')
.pipe(through2.obj((file, enc, next) =>
gulpPlugins.pug({
// Grab the filename, and set pug data to the value found in dataSet by that name
data: dataSet[file.basename] || {}
})._transform(file, enc, next)
))
.pipe(through2.obj((file, enc, next) => {
const options = {
indent_char: ' ',
indent_size: 4
};
if(file.relative.match(/admin\//)) {
options.indent_size = 2;
} else if(file.relative.match(/auth\//)) {
options.indent_size = 3;
}
file.contents = new Buffer.from(html.prettyPrint(String(file.contents), options), enc);
next(null, file);
}))
.pipe(gulp.dest('output'));
}
For the pug step, we call through2.obj and create the pug plugin, passing it data grabbed from our object literal, indexed by filename in this example. So now the data passed into the compiler comes from that object literal.
For the html step you mention, gulp-html-prettify doesn't expose its transform function, so we can't reach into it and pass the transform back to the stream. But in this case that's OK, if you look at the source it's just a wrapper to prettyPrint in the html package. That's quite literally all it is doing. So we can just rig up our step using through2 to do the same thing, but changing our options based on the vinyl file's relative path.
That's it! For a working example see this repo: https://github.com/joshdavenport/stack-overflow-61314141-gulp-pug-conditional

Grunt variable as filename and file path

I'm trying to use Grunt option to define a file path and file name. This used to work but now I'm getting an unexpected token error.
var myTarget = grunt.option('target');
'build/assets/css/' + myTarget + '.css': 'source/scss/' + myTarget + '/styles.scss'
You should use the special placeholders for variables in file names and strings. First, you should load the option (using grunt.option()) or configuration (using grunt.congif()), as an option for the Grunt initConfig method. Then you should use the special placeholders <%= varname %> to use the loaded options or configurations.
grunt.initConfig({
target : grunt.option('target'),
...
files : {
'build/assets/css/<%= target %>.css' : 'source/scss/<%= target %>/styles.scss'
}
...
});
Configuration can also load an object, so the special placeholder can match object properties too:
grunt.config('definitions', (function() {
return {
target : 'my-target'
};
})());
Later on your config:
grunt.initConfig({
config : grunt.config('definitions'),
...
files : {
'build/assets/css/<%= config.target %>.css' : 'source/scss/<%= config.target %>/styles.scss'
}
...
});
Read more about Grunt option, config and templates in the Grunt official website.
Hope it helps.

Dom_munger issue with Node 7.7.3 - Path must be a string

I'm trying to update an application to support Node -v 7.7.3. But when I am running the grunt task dom_munger as per below:
dom_munger:{
read: {
options: {
read:[
{selector:'script[data-concat!="false"]',attribute:'src',writeto:'appjs', isPath: true},
{selector:'link[rel="stylesheet"][data-concat!="false"]',attribute:'href',writeto:'appcss'}
]
},
src: 'app/index.html'
}
}
I receive error:
Warning: Path must be a string. Received [ 'app/index.html' ] Use --force to continue.
I wonder if there is a way to rewrite above grunt task or if there might be a good alternative to dom_munger. Any help would be appreciated.
Per the grunt-dom-munger Github:
When isPath is true, the extracted values are assumed to be file
references and their path is made relative to the Gruntfile.js rather
than the file they're read from.
Try removing the isPath property, or altering it to match the path from your Gruntfile to the index.html file.
Remove isPath: true, and make sure that path in src attribute relative to the Gruntfile.js rather than the file they're read from.
If needs make a replace in path:
dom_munger: {
replacePath: {
options: {
callback: function($, file){
var scripts = $('script[data-concat!="false"]');
// NOTE: path is made relative to the Gruntfile.js rather than the file they're read from
for(var i=0, s, il=scripts.length; i<il; i++){
s = scripts[i];
if(s.attribs.src){
s.attribs.src = s.attribs.src.replace('../', '');
}
}
}
},
src: 'temp/index.html'
},
read: {
options: {
read: [
{selector:'script[data-concat!="false"]',attribute:'src',writeto:'appjs'},
{selector:'link[rel="stylesheet"][data-concat!="false"]',attribute:'href',writeto:'appcss'}
]
},
src: 'temp/index.html'
}
}
Thanks you! But this only seems to work if the Grunt and Index are in the same folder structure. My structure looks like this:
- /app
-index.html
- gruntfile.js
And without the attribute 'isPath' the dom_munger will look for js files in the same directory as where the Gruntfile is places.

How to scan an entire directory tree with node.js?

Often I would want to scan an entire directory tree (a directory, and everything inside it, including files, subdirs, and those subdir contents too, and their subdir contents too, etc etc).
How would one accomplish this with node? Requirements, is that it should be asynchronous to take advantage of super fast non-blocking IO - and not crash when processing too many files at once.
-- I've updated this answer in 2017 for the progress since 2012 --
Ended up creating these to accomplish it:
https://github.com/bevry/safefs - which now uses https://npmjs.org/package/graceful-fs (which didn't exist before)
https://github.com/bevry/scandirectory - there is also now a vast array of like projects like this
I also created this which is lightweight and super fast:
https://github.com/bevry/readdir-cluster
You can use the module npm dree if you want to achive that. It returns a json that describes the directory tree and it allows you to specify also a fileCallback and a dirCallback, so you can do this:
Here is the code:
const dree = require('dree');
const fileCb = function(file) {
// do what you want
}
const dirCb = function(directory) {
// do what you want
}
dree.scan('path-to-directory', { extensions: [ 'html', 'js' ] }, fileCb, dirCb);
If you want to stick with the 'fs' module, you can do some recursive functions to get them.
Heres a function I made recently to get the tree of a directory.
const fs = require("fs");
// dir is file, depth is how far into a directory it will read.
function treeFiles(dir, depth = 1000) {
if (depth < 1) return;
var sitesList = {};
fs.readdirSync(dir).forEach((file) => {
let base = dir + '/' + file;
// Add file to siteslist object.
sitesList[file] = {"stats": fs.statSync(base), "dir": false};
// Recursive to get directory and tree of files
if (fs.statSync(base).isDirectory()) {
sitesList[file]["dir"] = true;
sitesList[file]["ls"] = treeFiles(base, depth - 1);
}
});
return sitesList;
}
So if I have a file structure which looks like
nodejs_app >
- app.js
- config.js
- images >
- - logo.png
Then the final output of my function reading the nodejs_app directory will look like
{
"app.js": {"stats": {}, "dir": false},
"config.js": {"stats": {}, "dir": false},
"images": {"stats": {}, "dir": true, "ls": {
"logo.png": {"stats": {}, "dir": false}
}
}
Then just call the function with directory and depth into the directory if you want.
let dir = require("path").join(__dirname, "nodejs_app");
let tree = treeFiles(dir);
console.log(tree);
Of course change paths and names to fit your code. I included the depth as to reduce time it takes for it to finish reading a directory.

Resources