Giter Club home page Giter Club logo

rx-aster's Introduction

rx-aster

NPM version Build Status

aster - AST-based code builder

What's that

aster is reactive builder specialized for code processing and transformations. It's built with debugging in mind and makes building JavaScript code more reliable and faster.

Why one more

Source maps are a great invention that is meant to simplify life by allowing developers to debug the original code (the one that they actually write, whatever language it is) on production.

However, using them is pretty hard in any of existing build systems whenever you have at least one plugin in your build pipeline - and you most likely do - that doesn't support emitting them or even consuming from previous step; some plugins even treat code as simple strings discarding all it's inner logic and structure.

Your code isn't just a string. It has a soul and rich inner world and aster is built to treat it like that. As result, it provides complex yet easy and fast transformations that are transparent for browser debugger out of the box.

You can think of aster for JS as of rework for CSS.

But I like X builder! Should I throw it out?

Definitely no! aster doesn't try to fight your favorite build system. It has only one specific area that it's exceptionally good at - code processing. Everything else (CSS, images, publishing to CDN, etc.) is left for generic builders, and you can use them together.

Currently there are following bindings:

If you wish, you can define aster pipeline as custom task in any existing build system on your own since aster uses RxJS under the hood, which is interoperable with events, streams, promises, callbacks and any other asynchronous primitives and patterns out of the box.

API

aster is completely modular and main package is just a centralized API wrapper for core parts published as separate modules (check out their documentations for details):

  • src - Single-pass source files reader.
  • watch - Continuous source files reader.
  • dest - File writer.
  • runner - Build pipeline runner with built-in logger.
  • equery - Example query and modify, via grasp-equery
  • squery - Standard (CSS like) query and modify, via grasp-squery
  • traverse - AST traverser
  • parse - Parser
  • parse-js - JS Parser
  • parse-esnext - ES.next Parser

Usage

First, install rx-aster as a development dependency:

npm i --save rx-aster

or via yarn

yarn add rx-aster

Check the tests in /tests folder and run them. The tests demonstrate how to:

  • select and remove/rename class, function and method by id
  • find a node and add a class, function or method after it

Read the docs

Test AST parsing of your code

Notice how the tests use selectors described in javascript syntax

Example (from squery)

Putting a couple things we have learned together, here is the selector for an immediately-invoked function expression.

These can take for form of:

(function(){ ... })();
(function(){ ... }).call(...);
(function(){ ... }).apply(...);

The selector we use to match these is:

call[callee=(func-exp, member[obj=func-exp][prop=(#call, #apply)])]

At the top level, in all cases we are matching a call. The callee (the function being called) of the call is either a function expression in the first case, or a member expression in the second and third cases. In those cases, the object that is being accessed is a function expression, and the property is either the identifier call in the second case, or apply in the third case.

As this is a common pattern, you can simply use iife to match it instead.

See the javascript syntax for an overview of available selectors such as func-dec and class-dec.

Creating a refactor pipeline

Create build script and use it.

const rxa = require('rx-aster')
const { aster } = rxa

aster.watch([ // watch these files for changes
  'src/**/*.js',
  'src/**/*.coffee',
  'src/**/*.jsx'
])
.throttle(500) // every 500ms
.map(changed(function (src) {
  return src.map(equery({
    'if ($cond) return $expr1; else return $expr2;':
      'return <%= cond %> ? <%= expr1 %> : <%= expr2 %>'
  }));
}))
.map(concat('built.js'))
.map(umd({exports: 'superLib'}))
.map(aster.dest('dist', {sourceMap: true}))
.subscribe(aster.runner);

Using custom sources:

const sources = ['var a = 1', 'var b = a + 2']

const srcObserver = Rx.Observable.of(sources);
const srcObserver2 = Rx.Observable.just(sources[0]);

aster.src({
  srcObserver
})
.map(equery({
  'if ($cond) return $expr1; else return $expr2;': 'return <%= cond %> ? <%= expr1 %> : <%= expr2 %>'
  // , ...
}))
.map(aster.dest((options) => {
  // return a function that when run returns an Observable
  return function(sinks) {
    // do something with the sinks...
    // ie. use incoming event streams from previous step (ie. .map(equery(...)), write to a destination
    return sinks
  }
}))
.subscribe(aster.runner({
  onNext: (item) => {
    console.log('>> %s'.yellow, item)
  }
}));

Code Operator

Currently the operator includes the following:

  • ClassOperator
  • MethodOperator
  • FunctionOperator

ClassOperator example

const { operator } = require('rx-aster')
const { ClassOperator } = operator

const codeWithClass = `class Hello {
  cool(x) {
    console.log(x)
  }
}`

const op = new ClassOperator({ code })

// rename one class and add another
let code = op
  .rename({name: 'Hello', to: 'Goodbye'})
  .add({name: 'Winner'})
  .code

console.log('Modified code', code)

Creating plugins

Check out aster's Yeoman generator.

It automizes the process of creating basic skeleton and Github repo for your plugin in few easy steps. When created, you just need to modify index.js and test.js files to reflect your intended plugin's functionality (detailed hints included right in code).

License

MIT License

rx-aster's People

Contributors

mandricore avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

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.