Giter Club home page Giter Club logo

nebu's People

Contributors

aleclarson avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar

Forkers

halloalex

nebu's Issues

Conditional plugins

For example, a plugin may want to run only if a certain package is imported.

Command line interface

nebu command for the terminal.

Options:
    -o    output directory/filename
    -m    sourcemap option
    -x    ignored file patterns

When -o is unspecified, the result is printed to the console (if compiling a directory, we exit early).

The -m option can be inline, both, or no value (which saves sourcemaps to .map files alongside the compiled sources). When unspecified, sourcemaps are discarded.

Support input sourcemaps

When an input sourcemap is given, the result's sourcemap will be merged with it, so it points back to the input sourcemap's sources (aka the original source).

Bonus: If //# sourceMappingURL exists and the filename option is defined, load the source map and treat it as an input sourcemap automatically.

[RFC] Node.prototype.wrap

node.wrap('try {\n', '\n}')
// identical to:
node.before('try {\n')
node.after('\n}')

You can wrap the node with anything, but the main use cases are blocks and call expressions.

Do we have a separate method for "block wrapping" that indents the wrapped node and implicitly adds the newline characters seen above? Or maybe passing true as the third argument can do that?

node.wrap('try {', '}', true)
// or
node.bwrap('try {', '}')

Not a big fan of the name bwrap though.

bug: ForStatement has an update property

You can't reach the update method on a ForStatement node, because it already has an update property for the i++ in for (let i = 0; i < len; i++) {}.

I'm undecided on what to do for this.

  • rename the update property?
  • rename the update method to set?

Blank line preservation

When moving a block of code, you can use toString on each node and "paste" the result by using the appropriate method. There needs to be a way to preserve blank lines between nodes, so we can preserve the author's style.

The first idea that comes to mind is a method that returns a string containing only newlines (and maybe indentation?) corresponding to the number of blank lines before or after the node (so two variants). This string can then be "pasted" just like the toString result.

As an example:

foo()

// comment 1
bar()

// comment 2
foo()

Assume the bar() expression is represented by node:

node.spaceBefore() // => "\n\n// comment 1\n"
node.toString()    // => "bar()"
node.spaceAfter()  // => "\n\n\n// comment 2\n"

In the above example, the \n that begins bar()'s line is included in the spaceBefore result. And the \n that begins the line after that is included in the spaceAfter result. I'm not certain, but I think that's the expected behavior.

I'm also undecided if indentation should be included or not. I'm leaning towards no, because toString currently strips indentation and we should match that behavior.

Another thing: maybe toString(true) can include the result of spaceAfter (and even the result of spaceBefore if we're the first sibling of a BlockStatement) to make things easier?

These decisions could easily be a source of many bugs if we aren't careful.

Support nebu.config.js

When opts.filename is defined, search up the chain of parent directories for a nebu.config.js module. If the module exports an array, use it for opts.plugins. Otherwise, an object should be exported, which is merged into opts.

The opts properties passed to nebu.process take precedence over any defined in nebu.config.js. But the plugins arrays are concatenated if opts.plugins is defined and nebu.config.js exports an array of plugins (or an object with a plugins property). During concatenation, we should take care to remove any duplicate plugins.

You can disable this feature with opts.dotconfig = false.

Let set() replace null with a node

Sometimes, a block is optional (eg: the finally block in a try statement). Currently, the set method doesn't know how to handle each case appropriately.

// This *should* work, but it doesn't.
node.set('finalizer', 'console.log("test")')

// In this case, there's a workaround.
node.after(`finally {
  console.log("test")
}`)

Updating arbitrary properties

While the set method currently only works with properties that typically contain a Node object or an array of Node objects, it should work with any property that makes sense to update.

Supporting this will require a new module that exports an object like so:

exports.VariableDeclaration = {
  setKind(value, output) {
    output.overwrite(this.start, this.start + this.kind.length, value);
  }
};

Then, node.set('kind', 'var') would turn let a = 1 into var a = 1.

The exports would be restructured (on startup) into something like:

exports.set = {
  VariableDeclaration: {
    kind(value, output) { /* ... */ }
  }
};

The push, unshift, and splice methods might have their own edge cases, too. These would be handled similarly with insertProperty-style functions.

Same for the remove method with removeProperty-style functions.

[RFC] Node.prototype.process

The process method would apply a new set of plugins to the node and its descendants.

This may require changes to magic-string to work properly. We'll want a "slice" of the MagicString object that applies changes based on a character offset (where our node starts). The original MagicString object would inherit any changes we make to the "slice".

// A plugin that applies its own plugins.
const plugin = {
  ClassBody(node) {
    node.process(plugins, state)
  }
}

The plugins argument must be an array with at least one element.

The state argument is an optional object, which defaults to the "parent" state.

This is very efficient when you want a subset of plugins to be used only if within a certain context.

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.