Giter VIP home page Giter VIP logo

mem-fs-editor's Introduction

mem-fs-editor

Node.js CI NPM version Coverage Status

File edition helpers working on top of mem-fs

Usage

import { create as createMemFs } from 'mem-fs';
import { create as createEditor } from 'mem-fs-editor';

const store = createMemFs();
const fs = createEditor(store);

fs.write('somefile.js', 'var a = 1;');
await fs.commit()

#read(filepath, [options])

Read a file and return its contents as a string.

You can alternatively get the raw contents buffer if you pass options.raw = true.

By default, calling read() on a file path that does not exist throws error. You can, however, pass options.defaults = 'your default content' to get a default content you pass in, if you prefer to not deal with try/catch.

#readJSON(filepath, [defaults])

Read a file and parse its contents as JSON.

readJSON() internally calls read() but will not throw an error if the file path you pass in does not exist. If you pass in an optional defaults, the defaults content will be returned in case of the target file is missing, instead of undefined. (Error would still be thrown if JSON.parse failed to parse your target file.)

#write(filepath, contents)

Replace the content of a file (existing or new) with a string or a buffer.

#writeJSON(filepath, contents[, replacer [, space]])

Replace the content of a file (existing or new) with an object that is to be converted by calling JSON.stringify().

contents should usually be a JSON object, but it can technically be anything that is acceptable by JSON.stringify.

Optionally pass replacer and space as the last two arguments, as defined by JSON.stringify. spacer is used to format the output string (prettify).

Default value for space is 2, when not specified.

#append(filepath, contents, [options])

Append the new contents to the current file contents.

  • options.trimEnd (default true). Trim trailing whitespace of the current file contents.
  • options.separator (default os.EOL). Separator to insert between current and new contents.
  • options.create (default false). Create the file if doesn't exists.

#appendTpl(filepath, contents, context[, templateOptions[, [options]])

Append the new contents to the exsting filepath content and parse the new contents as an ejs template where context is the template context (the variable names available inside the template).

  • options.trimEnd (default true). Trim trailing whitespace of the current file contents.
  • options.separator (default os.EOL). Separator to insert between current and new contents.

#extendJSON(filepath, contents[, replacer [, space]])

Extend the content of an existing JSON file with the partial objects provided as argument.

Optionally take the same JSON formatting arguments than #writeJSON().

#delete(filepath, [options])

Delete a file or a directory.

filePath can also be a glob. If filePath is glob, you can optionally pass in an options.globOptions object to change its pattern matching behavior. The full list of options are being described here. The sync flag is forced to be true in globOptions.

#copy(from, to, [options], context[, templateOptions ])

Copy file(s) from the from path to the to path. When passing array, you should pass options.fromBasePath to be used to calculate the to relative path. The common directory will be detected and used as fromBasePath otherwise.

Optionally, pass an options.process function (process(contents)) returning a string or a buffer who'll become the new file content. The process function will take a single contents argument who is the copied file contents as a Buffer.

options.ignoreNoMatch can be used to silence the error thrown if no files match the from pattern. options.append can be used to append from contents to to instead of copying, when the file is already loaded in mem-fs (safe for regeneration).

from can be a glob pattern that'll be match against the file system. If that's the case, then to must be an output directory. For a globified from, you can optionally pass in an options.globOptions object to change its pattern matching behavior. The full list of options are being described here. The nodir flag is forced to be true in globOptions to ensure a vinyl object representing each matching directory is marked as deleted in the mem-fs store.

Optionally, when from is a glob pattern, pass an options.processDestinationPath function (processDestinationPath(destinationFile)) returning a string who'll become the new file name.

options.noGlob can be used to by bypass glob matching entirely. In that case, from will directly match file paths against the file system.

#copyAsync(from, to, [options], context[, templateOptions ])

Async version of copy.

copy loads from to memory and copy its contents to to. copyAsync copies directly from the disk to to, falling back to copy behavior if the file doesn't exists on disk.

Same parameters of copy (see copy() documentation for more details).

#copyTpl(from, to, context[, templateOptions [, copyOptions]])

Copy the from file and, if it is not a binary file, parse its content as an ejs template where context is the template context (the variable names available inside the template).

You can optionally pass a templateOptions object. mem-fs-editor automatically setup the filename option so you can easily use partials.

You can also optionally pass a copyOptions object (see copy() documentation for more details).

Templates syntax looks like this:

<%= value %>
<%- include('partial.ejs', { name: 'Simon' }) %>

Dir syntax looks like this:

/some/path/dir<%= value %>/...

Refer to the ejs documentation for more details.

#copyTplAsync(from, to, [options], context[, templateOptions ])

Async version of copyTpl that uses copyAsync instead of copy.

Can be used for best performance. Reduces overheads.

Same parameters of copyTpl (see copyTpl() documentation for more details).

#move(from, to, [options])

Move/rename a file from the from path to the to path.

#move internally uses #copy and #delete, so from can be a glob pattern, and you can provide options.globOptions with it.

#exists(filepath)

Returns true if a file exists. Returns false if the file is not found or deleted.

#commit([options,] [...transforms])

Pass stored files through a pipeline and persist every changes made to files in the mem-fs store to disk.

If provided, options is the pipeline options. By default only modified files are passed through the pipeline. Pass a custom filter options.filter to customize files passed through the pipeline. If provided, ...transforms is a vararg of TransformStream to be applied on a stream of vinyl files (like gulp plugins). commitTransform is appended to transforms and persists modified files to disk, non modified files are passed through.

returns promise that is resolved once the pipeline is finished.

#dump([cwd,] [filter])

Dump files to compare expected result. Provide a cwd for relative path. Allows to omit temporary path. Provide a filter function or a pattern to focus on specific files. dump returns only modified (committed or not) files when no filter or a pattern is provided.

mem-fs-editor's People

Contributors

2roy999 avatar alqh avatar blai avatar dependabot[bot] avatar greenkeeper[bot] avatar hirse avatar homyeeking avatar idpaterson avatar jakub300 avatar jasonbellamy avatar kevinschaul avatar manuth avatar mischah avatar mshima avatar nquinn721 avatar omaten avatar raineorshine avatar rodrigodmd avatar sboudrias avatar shannonmoeller avatar shladdergoo avatar sindresorhus avatar sinedied avatar sjoblomj avatar snyk-bot avatar stevemao avatar tarol avatar timlrx avatar zcei avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mem-fs-editor's Issues

#copy() should provide options 'override' to resolve conflicts between 'from' and 'to'

Currently, copying a file to a path that is associated with another existing file would override the existing file, without warning or options to override such behavior.

#copy(from, to, options) should provide an option options.override that allows more flexibility:

  • When options.override is set to true, the function should have exactly the same behavior as today.
  • When options.override is set to false, the function should throw exception if conflicting content is found between from and to
  • When options.override is a function, the function should be something like function (oldConent, newContent) { return desieredContent; }

There had different performance in debugging and formal environment.

yeoman-generator is dependent on this package.

When I written this code in debugging environment:

writing: function () {
    this.fs.copy(
      this.templatePath('*'),
      this.destinationPath('*')
    );
    this.fs.copy(
      this.templatePath('.babelrc'),
      this.destinationPath('.babelrc')
    );
   this.fs.copy(
      this.templatePath('.npmrc'),
      this.destinationPath('.npmrc')
    );
    this.fs.copy(
      this.templatePath('.gitignore'),
      this.destinationPath('.gitignore')
    );
    this.fs.copy(
      this.templatePath('src'),
      this.destinationPath('src')
    );
 },

I run

$ node --debug `which yo` webpack-babel

and it's OK.

I published, used in formal environment, then errored:

events.js:160
      throw er; // Unhandled 'error' event
      ^
AssertionError: When copying multiple files, provide a directory as destination
    at EditionInterface.exports.copy (/usr/local/lib/node_modules/generator-webpack-babel/node_modules/mem-fs-editor/lib/actions/copy.js:34:5)
    at child.writing (/usr/local/lib/node_modules/generator-webpack-babel/app/index.js:31:13)
    at Object.<anonymous> (/usr/local/lib/node_modules/generator-webpack-babel/node_modules/yeoman-generator/lib/index.js:417:23)
    at /usr/local/lib/node_modules/generator-webpack-babel/node_modules/run-async/index.js:25:25
    at /usr/local/lib/node_modules/generator-webpack-babel/node_modules/run-async/index.js:24:19
    at /usr/local/lib/node_modules/generator-webpack-babel/node_modules/yeoman-generator/lib/index.js:418:9
    at runCallback (timers.js:637:20)
    at tryOnImmediate (timers.js:610:5)
    at processImmediate [as _immediateCallback] (timers.js:582:5)

When I modified code like this:

writing: function () {
    this.fs.copy(
      this.templatePath('*'),
      this.destinationRoot(),
      { globOptions: { dot: true } }
    );
    this.fs.copy(
      this.templatePath('src'),
      this.destinationPath('src')
    );
  },

It's just OK now.

Why it had different performance? Thanks.

Allow renaming on glob copy?

Appologies if this doesn't make sense or if the feature already exists.. I would like it if my template file names could have a replacable token in them... and when I copy, I want an opportunity to replace the token in the file name, or otherwise do whatever I want with the filename...

Thoughts? Is that possible already?

Make `fs` an option on `commit` such that a mock file system can be passed in

The mock-fs library allows the creation of a mock file system.

It has a mode to allow creating a mock fs object. See https://github.com/tschaub/mock-fs#mockfsconfig-options. This prevents problems with using it in the default way which interferes with require statements.

This small change to mem-fs-editor would allow the commit output to be tested in memory.

EDIT: Could also allow https://github.com/SBoudrias/mem-fs-editor/blob/master/test/commit.js tests to run faster.

Upgrade EJS to 2.3.4

Using mem-fs in a Yeoman generator (using fs.copyTpl) may lead to horrible output, because of the restricted white space handling of EJS (see mde/ejs#105). Since EJS 2.3.4 introduced <%_ and _%> which should help with these kinds of problems, I'd like to ask you for an EJS upgrade.

Renaming a newly created directory throws "Trying to copy from a source that does not exist" error

I'm trying to rename a directory as part of a Yeoman generator. I have the following Yeoman directory structure:

root/
├── generators
│   └── app
│       ├── templates
│       │   └── app
│       │       └── widget
│       │           ├── widget.controller.ts
│       │           ├── widget.service.ts
│       │           └── widget.module.ts
│       └── index.js
└── .yo-rc.json

My Yeoman generator copies everything from the templates directory to the new app's destination directory. As part of this process, I'd like to rename the widget folder to a name that the user enters earlier in the Yeoman process. This is the relevant code from the Yeoman generator (this.fs is an instance of mem-fs-editor):

this.fs.copyTpl(this.templatePath('**/*'), this.destinationPath('.'), this.props);

this.fs.move(
    this.destinationPath('app/widget'),
    this.destinationPath('app/' + this.props.widgetName)
);

The call to copyTpl is correctly scaffolding and templating the app from the templatePath to the destinationPath. However, when the fs.move operation is called, I get the following error message:

PS C:\Users\username\code\generator-dashboard-widget-test> yo dashboard-widget
? Your widget's name: (generator-dashboard-widget-test)
? Your widget's name: generator-dashboard-widget-test

events.js:154
      throw er; // Unhandled 'error' event
      ^
 AssertionError: Trying to copy from a source that does not exist: C:\Users\username\code\generator-dashboard-widget-test\app\widget
    at EditionInterface.exports._copySingle (C:\Users\username\code\generator-dashboard-widget\node_modules\mem-fs-editor\lib\actions\copy.js:45:3)
    at EditionInterface.exports.copy (C:\Users\username\code\generator-dashboard-widget\node_modules\mem-fs-editor\lib\actions\copy.js:23:17)
    at EditionInterface.module.exports [as move] (C:\Users\username\code\generator-dashboard-widget\node_modules\mem-fs-editor\lib\actions\move.js:4:8)
    at module.exports.generators.Base.extend.copyAppTemplate (C:\Users\username\code\generator-dashboard-widget\generators\app\index.js:54:17)
    at Object.<anonymous> (C:\Users\username\code\generator-dashboard-widget\node_modules\yeoman-generator\lib\base.js:431:23)
    at C:\Users\username\code\generator-dashboard-widget\node_modules\run-async\index.js:26:25
    at C:\Users\username\code\generator-dashboard-widget\node_modules\run-async\index.js:25:19
    at C:\Users\username\code\generator-dashboard-widget\node_modules\yeoman-generator\lib\base.js:432:9
    at processImmediate [as _immediateCallback] (timers.js:383:17)

If I leave out the rename step, this process works without any issues, and I can verify that the app/widget folder does indeed exist.

Here's a bug I filed on the yo repository for the same issue: yeoman/yo#455

Option to allow return null from read if file does not exist

This would save having to write this.fs.exists() && this.fs.read().

Can't think of a good name. Something like {nullIfNotExists} or {throws: false}.

The current design with the defaults option assumes that when you read a file you want to create it.

But say you want to read a file, get its contents, run some logic to decide which location to write it to, then it becomes more verbose.

I am writing idempotent generators for yeoman and this is a common practice for me.

E.g.

docs/LICENSE.md
LICENSE.md

Try to read each file, merge contents/decide which contents to use, then write file depending on option.

copyTpl should support glob options

the copyTpl function should support an optional options property in the same way that copy does. More spicificly there should be some way to pass in globing options to paths that support globs.

Creating an empty directory

I believe a method for creating an empty directory is required, and should be relatively easy.
Sometimes you just want to give a logical tree structure without having to actually put any files in them.

Delete folders inside folder

Environment: I have the folder "public / wp-content / themes /" and inside it several other folders and a file named "index.php"

Objective: Delete the existing folders within the folder and keep the themes folder and the index.php file

Situation:
- Delete the entire themes folder

fs.delete(this.destinationPath('public/wp-content/themes/**'));
fs.delete(this.destinationPath('public/wp-content/themes/**/*'));
fs.delete(this.destinationPath('public/wp-content/themes/**/*!(index.php)'));

- Leave the internal folders and delete only the index.php

fs.delete('public/wp-content/themes/**!(index.php)');
fs.delete('public/wp-content/themes/*');

How to solve this situation? Does anyone know what I'm doing wrong?

write to placeholder

Is it possible to write the new content to where a placeholder is and leave that placeholder there for future writes?

copyTpl should take process options like copy

I can imagine some scenarios where we'd want to pass our own process function to copyTpl() to do some string replacement or other editing logic on a copied template file either before or after it's passed to ejs.render().

In one of these scenarios, in yeoman, we generate a template file with template() where we populate an array based on various options selected by the user, say for angular module dependencies, and because we need to allow for multiple options being selected, as well as other injection later by other sub-generators we write the template like this:

angular.module('<%= moduleName %>', [<% if (module1) { %>'module1',<% } %><% if (module2) { %>'module2',<% } %><% if (module3) { %>'module3',<% } %>
     // inject:modules start
     // inject:modules end
])

The annoying thing is that after only running this one generator, if we run our tests we automatically fail the linter because we necessarily have included a dangling comma in the above array. I guess we could write more templating logic to handle the commas alone, but given ejs's syntax, that would quickly grow unwieldy. It would be great if we were able to resolve this with options passed to template()/copyTpl().

I see two possible solutions to this problem if either pre- or post-process functions could be passed in the options:

  • If we have a postProcess function, we could to inspect the array after templating and remove the dangling comma, perhaps using existing linters

  • if we have a preProcess function we could write logic to determine what modules were selected by the user and and then add commas as necessary. e.g. we could write our template like this:

    angular.module('<%= moduleName %>', [ #=====modules hook=====#
          // inject:modules start
          // inject:modules end
    ])

    and then our preProcess function like this:

    preProcess: function (content) {
        var moduleDeps = []
            .concat(module1 ? '\'module1\'' : [], module2 ? '\'module2\'' : [], module3 ? '\'module3\'' : []);
        return content.toString().replace(/#=====modules hook=====#/, moduleDeps.join(', ');
    }

Of course we could just use copy() and write the process logic for all of the replacements, but then we miss out on being able to use ejs for the simple value replacements.

Let me know what you think, I'm happy to work on a PR if people agree with me.

Copy not copying files to app root

I have the following code and for the life of me I can't figure out what's wrong. I first get a prompt for conflict resolution with no filename on ['app.js', 'run.js', 'gulfpfile.js']. if i type 'y' to overwrite, I get error "Illegal operation on a directory". If I comment out objects for 'app.js', 'run.js' and 'gulfpfile.js', everything works fine. All these files are under templates/ btw

const dest = this.destinationPath();
    const resources = [
      { uri: 'app.js', dest: '.' },
      { uri: 'run.js', dest: '.' },
      { uri: 'gulpfile.js', dest: '.' },
      { uri: 'app/**/*', dest: 'app' },
      { uri: 'public/**/*', dest: 'public' },
      { uri: 'spec/**/*', dest: 'spec' },
      { uri: 'views/**/*', dest: 'views' },
    ];
    _.forEach(resources, resource => {
      if (resource.dest) mkdirp.sync(resource.dest);
      this.fs.copy(
        this.templatePath(`${resource.uri}`),
        this.destinationPath(resource.dest)
      );
    });

defaults option is ignored if falsy (e.g. empty string)

Commit 7adfb3a makes it impossible to default to a falsy value such as an empty string when the file being read does not exist. Prior to version 1.2.2 it was possible to set an empty string with { defaults: '' }. This was a convenience as it allows a simple falsy evaluation of the file contents if (contents) { ... } without worrying about the exception.

The defaults option handling is in actions/read.js line 10

I can submit a pull request with tests but I'm not sure which approach you would prefer to use to test whether defaults is provided. In a general case I would use something like 'defaults' in options or options.defaults !== undefined but since the Buffer is intended to be created with a string it may be better to use typeof options.defaults === 'string' to both ensure that the option is defined and that it is a string.

.dot files copying

Hello guys, thanks a lot for awesome work!
I have the following code (from own yeoman generator):

    glob('**', {
      cwd: this.sourceRoot(),
      dot: true
    }, function (err, files) {
      files.forEach(function (file) {
        this.fs.copyTpl(
          file,
          this.destinationRoot(this.appname),
          this
        );
      }.bind(this));

      cb();
    }.bind(this));

which throw AssertionError:
AssertionError: Trying to copy from a source that does not exist: .babelrc

Could you explain, how I can copy .dot files with copyTpl method?

#commit() to write files to disk

New method that will take the mem-fs store and write it to disk.

Features

  • Must allow write filters. (Probably taking a list of filters as parameters - filters being transform streams, just like gulp-plugins)
  • Must triggers events. (We need an event interface where we can listen for write, delete and modified events)
  • Must take a callback when the processing is completed.

Allow to disable glob matching?

I'm using yeoman which uses your lib for file operations.

The problem I'm having is when I try to copy a file containing blob-matching characters, like [merge].package.json.

This file resolves as a blob and fails to copy properly. When I tried to escape the [ ] character with \[merge\].package.json, there is an issue in copy.js with this statement:

  if (Array.isArray(from) || !this.exists(from) || glob.hasMagic(from)) {

glob.hasMagic() properly returns false, but !this.exists() matches because the test does not account for the escaped glob characters.

The simplest way to resolve this would be an option to copy/copyTpl to disable glob matching entirely, what do you think?

New feature: Append

I'm going to use read -> write as a workaround for now, but I was wondering whether you'd be open to merging a PR with this feature.

Add a fuction exists

Currently in yeoman you may want to check if a file exists before attempting to create it.

If you use the built in fs module from Node is not the right approach if using mem-fs-editor.

I attempted to "check existence" by using read it throws an error but I feel it's a bit inelegant to catch it.

Listing files.

Code that moves files individually is unfortunate. I would prefer to avoid hardcoding filenames into my generator.

One thing that would help is if I could programmatically get a list of the filenames within the destinationRoot() directory. Then I can have conventions around how files get renamed and do it in a loop based on whatever files were actually copied over. E.g. all filenames with a given prefix have that prefix removed.

In the generator, it would look something like this:

const cruft = '_';
const filenames = this.fs.list(this.destinationRoot());
filenames.forEach((name) => {
    if (name.startsWith(cruft)) {
        this.fs.move(
            this.destinationPath(name),
            this.destinationPath(name.substring(cruft.length))
        );
    }
});

_.slugify() no longer supported in templating

The recent bump in version number dependencies has caused an issue in my generator where a I am using the slugify function from undersocre.string.

This was introduced in my generator once the version of lodash exceeded 2.4.1. Was this behavior expected?

Bug: Copy-tpl does not handle an array of files correctly

I am a collaborator at EJS. Someone just opened mde/ejs#166 stating that they were receiving an error due to recent updates in EJS's error handling. We traced the issue back to the fact that mem-fs-editor sometimes calls ejs.compile() passing the filename option as an array. As I stated there:

The official API docs explicitly specify that filename should be a string. http://ryanzim.github.io/ejs-api/global.html#Options

There should be some handling in copy-tpl.js to check if filename is an array.

This is a critical bug; this behavior affects yeoman-generator's use of this module. 🆘

If you want a quick patch in the meantime, you can fix the EJS dependency to v2.4.1.

How to use copy() with options.process?

I am trying to copy a file and save an altered version to destination.

I couldn't find any information on options.process usage. But when I try the snippet below, it doesn't work. Is this usage wrong?

this.fs.copy(
  this.destinationPath('vendor/_bootstrap.scss'),
  this.destinationPath('sass/_bootstrap.scss'),
  {
    options: {
      process: function (contents) {
        var c = contents.replace('@import "bootstrap/variables";', '');

        return c;
      }
    }
  }
);

this.fs.delete shows "create" when deleting files

Assume my folder structure is :

dir
src
test
HelloWorld.txt

For instance, if I do this.fs.delete("dir/src/test"); in my Yeoman generator:

I get prompted about a conflict (why?). But anyways,

conflict dir/src/test
? Overwrite dir/src/test? overwrite
force dir/src/test
create dir/src/test/HelloWorld.txt

I assume the force statements refers to deletion of the outer test folder.

But, why, when deleting dir/src/test/HelloWorld.txt, does it say "create"?

This "create" behavior as well as the "overwrite" prompt happens for this.fs.move as well.

For reference, I am on:

yo --version
1.4.7

An in-range update of deep-extend is breaking the build 🚨

Version 0.4.2 of deep-extend just got published.

Branch Build failing 🚨
Dependency deep-extend
Current Version 0.4.1
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

deep-extend is a direct dependency of this project this is very likely breaking your project right now. If other packages depend on you it’s very likely also breaking them.
I recommend you give this issue a very high priority. I’m sure you can resolve this 💪

Status Details
  • continuous-integration/travis-ci/push The Travis CI build failed Details,- ✅ coverage/coveralls First build on greenkeeper/deep-extend-0.4.2 at 85.938% Details

Commits

The new version differs by 6 commits0.

false

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

file mode handling

We should add a property mode to vinyl files so we can track the chmod to apply certain files.

fs.copyTpl throws error with recursive globs (**/*)

Originally posted here: yeoman/generator#735
@blai suggested I post this here, as it may be a mem-fs-editor bug.

Ran into this here: https://github.com/timkelty/generator-craft-plugin

      this.fs.copyTpl(
        this.templatePath('pluginhandle/**/*'),
        this.destinationPath(pluginDest),
        this
      );

This was working rather recently, but with a freshly re-installed yo, I get this:

events.js:72
        throw er; // Unhandled 'error' event
              ^
TypeError: Cannot call method 'toString' of null
    at copy.process (/Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy-tpl.js:11:34)
    at applyProcessingFunc (/Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:12:16)
    at EditionInterface.exports._copySingle (/Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:52:24)
    at EditionInterface.<anonymous> (/Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:37:10)
    at Array.forEach (native)
    at EditionInterface.exports.copy (/Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:34:9)
    at EditionInterface.module.exports [as copyTpl] (/Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy-tpl.js:9:8)
    at module.exports.yeoman.generators.Base.extend.writing.pluginFiles (/Users/timkelty/Repos/generator-craft-plugin/app/index.js:125:15)
    at /Users/timkelty/Repos/generator-craft-plugin/node_modules/yeoman-generator/lib/base.js:406:16
    at processImmediate [as _immediateCallback] (timers.js:345:15)

Throws when using `copyTpl` and image types

My scenario & examples occur within the context of yeoman-generator, but mem-fs-editor is mounted directly as this.fs

When copying files from templatePath to destinationPath, I need to explicitly ignore all .jpg files (and presumably gif & png too):

this.fs.copyTpl([
    `${this.templatePath()}/**`,
    '!**/test.js',
    '!**/*.jpg'
], this.destinationPath(), {...});

If I don't, the following stack is thrown:

Error: Could not find matching close tag for "<%".
    node_modules/ejs/lib/ejs.js:560:19
    Object.Template.generateSource (node_modules/ejs/lib/ejs.js:545:15)
    Object.Template.compile (node_modules/ejs/lib/ejs.js:450:12)
    Object.compile (node_modules/ejs/lib/ejs.js:306:16)
    handleCache (node_modules/ejs/lib/ejs.js:169:18)
    Object.exports.render (node_modules/ejs/lib/ejs.js:332:10)
    copy.extend.process (node_modules/mem-fs-editor/lib/actions/copy-tpl.js:12:18)
    applyProcessingFunc (node_modules/mem-fs-editor/lib/actions/copy.js:13:16)
    EditionInterface.exports._copySingle (node_modules/mem-fs-editor/lib/actions/copy.js:51:16)
    EditionInterface.exports.copy (node_modules/mem-fs-editor/lib/actions/copy.js:23:17)
    EditionInterface.module.exports [as copyTpl] (node_modules/mem-fs-editor/lib/actions/copy-tpl.js:10:8)
    cp (app/index.js:81:13)
    app/index.js:92:4

I know I can successfully copy images to my destination using copy(), but it can only be done one file at a time && makes the copy-templates phase clunkier.

this.fs.copy(this.templatePath('assets/foo.jpg'), this.destinationPath('assets/foo.jpg'));
this.fs.copy(this.templatePath('assets/bar.jpg'), this.destinationPath('assets/bar.jpg'));
this.fs.copy(this.templatePath('assets/baz.jpg'), this.destinationPath('assets/baz.jpg'));

TL;DR;

Can we filter & ignore extensions within copyTpl() so that images can be cloned along with everything else in one fell swoop?

Would be nice if copy supported copying in-memory folders

I have the following in memory but not on disk:

/path/to/file1.txt
/path/to/file2.txt

I would like to perform:

this.copy('/path/to', '/new/path/to');

So that I end up with:

/path/to/file1.txt
/path/to/file2.txt
/new/path/to/file1.txt
/new/path/to/file2.txt

Currently this fail with:

Trying to copy from a source that does not exist: /path/to

Interestingly if /path/to exists in the physical filesystem, I think this works (has been a couple days so this needs double checking.) @SBoudrias suggested the following workaround, which does work perfectly even when the files are only in memory:

this.copy('/path/to/**', '/new/path/to');

Can not write or copy files

Hi, I'm using node v4.1.1, not sure if it's causing the problem.
I was testing using the example in the introduction:

var memFs = require('mem-fs');
var editor = require('mem-fs-editor');

var store = memFs.create();
var fs = editor.create(store);
console.log(fs.read('test.js'));
fs.write('test.js', 'var a = 1;');

output is
aaaaa which was correct in the test.js
But the new string didn't get written into the file. (I've granted write permission on the file.)

I didn't get any error messages either, is there a way I can debug? Thank you

New method: extendJSON

I wonder if we could add a new method #extendJSON() to provide a JSON structure to overwrite the keys in an existing JSON file.

This seem like a pretty common pattern inside yeoman generators (like progressively building a package.json). And having syntax sugar on top of it might be useful.

[Feature request] move / rename function

A move function would be helpful, and as far as I can see, also pretty easy to write.

I'm not so sure about a rename function—possibly a function which behaves pretty much the same as the move function, but doesn't change the directory?

fs.move('dir/file.js', 'dir/different-name.js'); // dir/different-name.js

fs.rename('dir/file.js', 'different-name.js'); // dir/different-name.js

Could be confusing though. Might be best just to stick to one function.

Expose a way to list files in memory

That's just a suggestion coming from a recent need. I wanted to apply modifications on a collection of files already modified and in memory. But my context is too generic to allow me to now exactly the name of the files I want.

In some way, what I need at that point is an API like a .list('src/**.*.js'). .exists already exists but it doesn't allow to discover which files are in memory.

Finally, as a workaroud, I committed changes and used globby to list my files. It works but it's not really the best.

I looked quickly to the source code, it seems really simple to do as list files with glob patterns is already everywhere, it would only be exposing the feature. I can make a PR if the idea is ok.

this.fs.delete does not ... delete a file that was just added ...

In yeoman I copy a template folder structure and then based on some prompts I want to remove some of the files that the template copied. Yes I realize I could filter these files out during the copy or split the template copy into two parts. While either of these would be more efficient it makes the code more complicated.

I added the following step to my generator as a test:

testDeletion: function() {
  this.fs.write("foo", "foo");
  this.fs.delete("foo");
},

When the generator completes it creates foo. Now if I run the generator again, I get a diff message if I accept the change foo is deleted.

I expect that the first time through foo is not saved to the filesystem. And hence the second time through I should not see a diff prompt.

I'm not clear what issue #32 is about, I suspect these are different issues, but I could be wrong. Forgive me if I am :)

Delete and exists issue

In the delete since it sets contents to new Buffer(''); the contents are never considered null so the exists method throws a false positive.

move file in memory

From move code:

this.copy(from, to, options);
this.delete(from, options);

If file was moved in memory it will be stored as modified and deleted file in mem-fs, even if it was never stored on fs. For example, if we copy _package.json and then move it to package.json yeoman will get two events from mem-fs:

   create package.json
   create _package.json

Should it instead remove from from this.store and just add to?

Cont. sindresorhus/generator-nm#18

<%% in copyTpl

In ejs, <%% Outputs a literal '<%', but it doesn't work for me in copyTpl, while making a yeoman generator.

I wrote this in my html file:

<div id="nodata">
    <i class="iconfont icon-nodata"></i>
    <div><%%=(errCode!=0) ? errMsg : 'No data.' %></div>
</div>

It should be rendered as:

<div id="nodata">
    <i class="iconfont icon-nodata"></i>
    <div><%=(errCode!=0) ? errMsg : 'No data.' %></div>
</div>

However, I get:

SyntaxError: Unexpected token %
    at Function (native)
    at /Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/lodash/index.js:10809:16
    at /Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/lodash/index.js:11082:21
    at /Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/lodash/index.js:8152:31
    at Function.template (/Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/lodash/index.js:10808:20)
    at copy.process (/Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy-tpl.js:11:16)
    at applyProcessingFunc (/Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:12:16)
    at EditionInterface.exports._copySingle (/Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:55:24)
    at EditionInterface.exports.copy (/Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy.js:22:17)
    at EditionInterface.module.exports [as copyTpl] (/Users/kelly/codespace/works/generator-k-midway/node_modules/yeoman-generator/node_modules/mem-fs-editor/actions/copy-tpl.js:9:8)

It seems that it can't recognize <%%

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.