alloc / nebu Goto Github PK
View Code? Open in Web Editor NEWFast, extensible, statically typed, and light Javascript transformer 🌿
License: MIT License
Fast, extensible, statically typed, and light Javascript transformer 🌿
License: MIT License
For example, a plugin may want to run only if a certain package is imported.
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.
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.
Nebu's internals won't need much work to support the ASTs of other languages.
I think SCSS would be a good start (we'll fork scss-parser).
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.
hasBinding(node, name)
returns true if a variable exists within the scope of the given node.
If all plugins only have Program
and/or ImportDeclaration
handlers, we can skip walking the entire AST.
Both of these are top-level node types.
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.
update
property?update
method to set
?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.
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
.
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")
}`)
https://github.com/vitalets/babel-plugin-runtyper
This is an intriguing plugin that should be implemented with nebu. :)
const utils = require('nebu/utils');
It's probably a good idea to include more utility functions for plugin developers.
Bublé has some functions that could be useful.
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.
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.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.