UNPKG

rocket-translator

Version:

Translate your HTML files to React.js and Vue.js

820 lines (638 loc) 18.9 kB
# Rocket Translator [![npm version](https://badge.fury.io/js/rocket-translator.svg)](https://badge.fury.io/js/rocket-translator) Translate HTML code to Vue, React or Angular. ## Instalation To install simply: Use npm ```sh npm i -g rocket-translator ``` or Yarn ```sh yarn global add rocket-translator ``` ## Getting Started ### Basic You can convert this: ```xml <div>Hello {name - state - "World"}!</div> ``` into this: ```jsx import React, {Component} from "react"; class MyComponent extends Component { constructor() { super(); this.state = { name:"World" }; } render(){ return( <div>Hello {this.state.name}!</div> ) } } export default MyComponent; ``` or this: ```xml <template> <div>Hello {{name}}!</div> </template> <script> export default { name:"MyComponent", data(){ return { name:"World" } } } </script> ``` Or this: ```ts import { Component } from '@angular/core'; @Component({ selector: 'test-root', template:`<div>Hello {{name}}!</div>` }) export class Test { name = "World"; } ``` ### How to Use To use, simpy create a HTML file, with the code to translate, and run: ```sh rocket [mode] path/to/file.html [output folder] ``` The **mode** may be `vue`, `react` or `angular`. The **output folder** is optional, if this is not defined will create a folder named **dist**. ## Guide * [States Simple](#states-simple) * [Props](#props) * [Computed](#computed) * [Methods](#methods) * [Components](#components) * [Watchers](#watchers) * [Inputs Handler](#inputs) * [Conditionals](#conditionals) * [List Render](#loops) * [Bind Attributes](#binds) * [JavaScript Management](#js-management) * [HTML Syntax](#syntax) * [CLI](#cli) ### States Simple <a name="states-simple"></a> A **State** in a Vue or React component, are a way to set data that affect the view, and when this changes, the component re-render the view. To get values from the HTML, we must declare into `{}`. And to the declare a state, we have 2 modes to set it: **Simple**, **With Value**. The **Simple** mode, is declared writing only the state name into the template and writing the type: **state**. Example: ```xml <div>{myState - state}</div> ``` In the **With Value** mode, is declared when, we write the state name, the type: **state** and the value for this state. Example: ```xml <div>{stateName - state - "Some Value"}</div> ``` The **value** may be `String`, `Number`, `Boolean`,`Array` and `Object`. And in the **simple** case, we obtain the next component state. In Vue: ```js data(){ return { myState:"" } } ``` In React we obtain: ```js this.state = { myState:"" } ``` And in Angular: ```ts export class Test { myState = ""; } ``` In the **With value** case we obtain. In Vue: ```js data() { return { stateName:"Some Value" } } ``` On React: ```js this.state = { stateName:"Some Value" } ``` And on Angular: ```ts export class Test { stateName = "Some Value"; } ``` Since version `2.0.0` you can add a prop in a bind attribute with the same format that in the bars expression `stateName - state`; Example: ```xml <div> <span :class="className - state">Hello World!!!</span> </div> <script> function setInitialState() { return { className: "foo" } } </script> ``` Or you can add the value next the `state` word. ```xml <div> <span :class="className - state - 'foo'">Hello World!!!</span> </div> ``` To know more about states and JavaScript Management. You can see [JavaScript Management](#js-management) section. ### Props <a name="props"></a> The **props** in a component, are data that a parent \(**container**\) component pass to a child component. And like the **state**, we may declare a prop with this format `{propName - prop}`. Example: ```xml <div>{parentData - prop}</div> ``` And declaring a prop, the final template will render, in Vue: ```js props:{ parentData:{ type:String, required:true, default:"Hello World" } } ``` And in React, auto declares the prop. ```js return( <div>{this.props.parentData}</div> ) ``` And on Angular, Import `Input` from `"@angular/core"` and declare as prop. ```ts import { Component, Input} from '@angular/core'; ... export class Test { @Input() parentData : string; } ``` Since version `2.0.0` you can add a prop in a bind attribute with the same format that in the bars expression `propName - prop`; Example: ```xml <span :class="externalState - prop">Hello World</span> ``` ### Computed <a name="computed"></a> A **Computed** propierty is a function that return a `String` or `Number` value, and this is render on the template. And to declare a computed propierty, simply we can set the computed propierty name and the type: **computed** and create the function to execute that match with the computed name. ```xml <div>{hello - computed}</div> ``` ```js function hello() { return "Hello World"; } ``` This will create a computed properties that returns a **Hello World**. Example: ```xml <div>Hi I Am {fullName - computed}!</div> <script> function fullName() { var name = "Foo"; var lastName = "Bar"; return name + " " + lastName; } </script> ``` Too know more about JavaScript Management go to [JavaScript Management](#js-management) section. ### Methods <a name="methods"></a> A **Method** is a function executed by an event on the final render or by the render. Is not necesary declare the method only set the event into the tag. ```xml <button onclick="hello()">Say Hello</button> <script> function hello() { alert("Hello World"); } </script> ``` Since Version 2.1.0 you can use `async` funtions. ```xml <div> <div>{data - state}</div> <button onclick="fetchData()">Fetch Data</button> </div> <script> function setInitialState() { return { data: "" } } async function fetchData() { try { const req = await fetch("http://someurl/data"); const fetched = await req.json(); data = fetched; } catch(err) { console.log(err); } } </script> ``` ### Components \(**Partial**\)<a name="components"></a> To import a **component** inside the main component. Only add the tag with the component syntax. ```xml <MyComponent /> ``` And to add a attr with a state value add `:` on the attr front. ```xml <MyComponent :my-bind-attr="stateName" /> ``` To write the component content, add a `component` tag with the **component content**. And add the attr `component-name` with the **component name**. And others attrs can be passed to the component. ```xml <component component-name="HelloWorldComponent" name="World"> <div> <h1>Hello {name - prop}!</h1> </div> </component> ``` ### State Watchers <a name="watchers"></a> To define a **State Watcher** you must create the function `setStateWatchers` this function must return all the states watchers. ```js function setStateWatchers() { return { state(e) { //Handle State }, anotherState: function(e) { //Handle Another State } } } ``` Also you can define as a `var`, `let` or `const`. ```js const setStateWatchers = () => { return { //Watchers } } ``` ### Inputs Handler <a name="inputs"></a> To **handle** a input, you must add the attr `name` on the input tag, and the value will be take to add a state with that name. ```xml <input type="text" name="username" /> ``` On **Vue** will render. ```xml <template> <input type="text" v-model="username" name="username"/> </template> <script> export default { name:"MyComponent", data() { return { username:"" } } } </script> ``` On React. ```jsx import React, {Component} from "react"; class MyComponent extends Component { constructor() { super(); this.state = { username:"" } } inputHandler({target}){ const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }) } } ``` Do not implement on Angular. We will add this features in futures versions. ### Conditionals <a name="conditionals"></a> To declare a **conditional**, add the `if` tag, with the `cond` attr, where `cond` is the condition to evaluate. Example: ```xml <if cond="auth"> <span>Congratulations! you are Sign in this platform</span> </if> ``` And you can set it with an `else` tag. ```xml <if cond="password.length < 6"> <span>Password must have more of 6 characters</span> </if> <else> <span>Password is very strong</span> </else> ``` Since version **2.0.0** we add the `else-if` tag. Like the `if` tag, this take the attr `cond` with the condition. ```xml <if cond="age < 18"> <span>Too Young</span> </if> <else-if cond="age > 30"> <span>Too Old</span> </else-if> ``` And now you can add the `tag` attribute to set conditional **tag name**. Example: ```xml <div> <if cond="auth === true" tag="span"> I must buy {item} </if> </div> ``` The `for` tag now will be a `li` tag. **Vue** ```xml <ul> <li v-for="item in buyList"> I must buy {{item}} </li> </ul> ``` **Angular** ```xml <ul> <li *ngFor="let item of buyList"> I must buy {{item}} </li> </ul> ``` On **React** put the content inside the **tag**. ```jsx var loop_0000 = this.state.buyList.map(item => (<li>{item}</li>) ); ``` The default tag on **Vue** is the `template` tag. On **React** don't have default tag. Put the content without tag. And on **Angular** the default tag is the `div` tag. ### List Render <a name="loops"></a> Like the conditionals, add a loop is't very easy, add a `for` tag, with the `val` attr. ```xml <for val="varName in stateName"> <span>{varName}</span> </for> ``` And since the version `2.0.0` you can add the `tag` attribute to define the tag to put the loop content. Example: ```xml <ul> <for val="item in buyList" tag="li"> I must buy {item} </for> </ul> ``` The `for` tag now will be a `li` tag. **Vue** ```xml <ul> <li v-for="item in buyList"> I must buy {{item}} </li> </ul> ``` **Angular** ```xml <ul> <li *ngFor="let item of buyList"> I must buy {{item}} </li> </ul> ``` On **React** put the content inside the **tag**. ```jsx var loop_0000 = this.state.buyList.map(item => (<li>{item}</li>) ); ``` The default tag on **Vue** is the `template` tag. On **React** don't have default tag. Put the content without tag. And on **Angular** the default tag is the `div` tag. ### Bind Attributes <a name="binds"></a> A **Bind Attribute** is a form to set a state value on a tag attribute. And the syntax is like on Vue. If you want add a default value you must add a `-` followed of the type. ```xml <button :class="classButton - state">Do Click</button> ``` The type can be `state` or `prop`. And with the type `state` you can add the `String` value next `state` word. ```xml <button :class="classButton - state - 'bar'">Do Click</button> ``` ### JavaScript Management <a name="js-management"></a> To the JavaScript Management, we add a few of keywords to help with the code imports. We must follow some rules to the correctly function of the translator. To include JavaScript on the template, add a `script` tag with the JavaScript code to translate. Or you can add the line `#js path/to/js.js` to import a external file. #### Lifecycles Since version `2.0.0` we add supports for framework **lifecycle**; and like methods and computed, all lifecycles will be filtered. We add 8 lifecycles to define the final component. * **setInitialState** * **setStateWatchers** * **beforeMount** * **mounted** * **beforeUpdate** * **updated** * **beforeUnmount** * **unmounted** ##### Set Initial States `setInitialState` have the same function that the `state` keyword in previous versions, this define **states** that will not be rendered on template. Example: ```xml <div> <span>Hi I Am: {fullName - computed}</span> </div> <script> function setInitialState() { return { name: "Foo", lastName: "Bar" } } function fullName() { return `${name} ${lastName}`; } </script> ``` ##### Set State Watchers `setStateWatchers` have the same function that the `watch` keyword in previous versions, this define all the states **watchers**. Example: ```xml <div> <span>You have do {clicks - state - 0} clicks</span> <button onclick="countClick()">Do Click</button> </div> <script> function setStateWatchers() { return { clicks(clicksNumber) { if (clicksNumber > 10) { alert("You do more than 10 clicks"); } } } } function countClick() { clicks++; } </script> ``` #### Functions The **Functions** are to change the method and computed properties execution. If the method or computed name match with the function name, this will be that method or computed. ```xml <div> <span>This is my {computedPropierty - computed} propierty</span> <button onclick="sayHello()">Say Hello</button> </div> <script> function computedPropierty() { return "Computed" } function sayHello() { alert("Hello World"); } </script> ``` #### Filter The **JavaScript Filter** is structured to filter the states and props. If into the code we have a function that contain a var with the state or prop name, this will be replaced automaticaly. Is not necesary declare like a state. ```js function setInitialState() { return { name: "Hello", lastName: "World" } } function sayHello() { alert(name + " " + lastName); /* will return on React: alert(this.state.name + " " + this.state.lastName); and on Vue: alert(this.name + " " + this.lastName); */ } ``` **Note**: You must evite use vars with state names, until we fix this. ### HTML Syntax <a name="syntax"></a> Like on JavaScript, on HTML we have a specific **syntax**, that we must follow to the correctly translator function. #### Bars Declaration The most used is the **bars declaration** `{}`, this is used to assign a state, prop, computed or the out framework syntax. Framework Declarative Syntax: `{ name }` State without value: `{stateName - state}` State With Value: `{stateName - state - value}` The `value` can be type: `String`, `Number`, `Boolean`, `Array`, `Object`, `null`, `undefined`, `NaN` or `Infinity`. Prop: `{propName - prop}` Computed Propierty: `{computedName - computed}` #### Import Tag To import a JavaScript external file, we use: `#js path/to/js.js`. **Note**: We want add **CSS** Support. #### Bind Attributes To execute JavaScript syntax or assign a state or prop value on an HTML attribute, we use `:attrName="Js or State"`. #### Conditionals And Loops Tags We add three HTML tags to assign **Conditionals** and **Loops**. `if`, `else-if`, `else` and `for`. ```xml <if cond="condToEvaluate"> <span>If Content</span> </if> <else-if cond="condToEvaluate"> <span>Else If Content</span> </else-if> <else> <span>Else Content</span> </else> <for val="varName in stateName"> <span>For Content</span> </for> ``` #### Component Tag We add this tag to declare a **custom** component inside the **Main Component** ```xml <component component-name="ComponentName"> <span>Component Content</span> </component> ``` ### CLI <a name="cli"></a> CLI use is simple: `rocket [mode] <input-file> <output-folder>` **mode** will be the target framework: _React_, _Vue_ or _Angular_. **input-file** will be the HTML component filepath. **output-folder** is optional. Will be the folder path. If is not defined, create a folder named `dist`. #### Options ##### --ignore-input-name Option `--ignore-input-name`, is used to evite that the filter, parse the name attribute on `input`, `select` or `textarea` tags. See a React Example Without `--ignore-input-name`: ```jsx render() { return ( <div> <input onChange={this.inputHandler} type="text" name="username"/> <input onChange={this.inputHandler} type="password" name="password"/> </div> ) } ``` With `--ignore-input-name`: ```jsx render() { return ( <div> <input type="text" name="username"/> <input type="password" name="password"/> </div> ) } ``` ##### --jsx Option `--jsx` is used to compile Vue and React as JSX, without this, Vue will be compiled as HTML and React with `React.createElement` ##### --allow-ssr Option `--allow-ssr` compile frameworks as Server Side Render-Frameworks, **Next** to React, **Nuxt** to Vue. With this `a` tags will be converted on `Link` or `nuxt-link` and can add, `getInitialProps` and `asyncData` methods. **Note**: Angular SSR are not currently supported ## To Do ### Features Support - [x] States - [x] Methods - [x] Computed - [x] Props - [x] States Watchers - [x] Components - [x] Bind States, Props, JS Expresions - [x] Input Handlers - [x] JavaScript Management \(**partial**\) - [x] Conditionals - [x] Nested Conditionals - [x] Loops - [x] Nested Loops - [ ] Inner HTML - [x] Lifecycles - [ ] React without JSX - [ ] React without ES6 - [ ] Vue Standalone - [x] Vue With JSX - [ ] Next Framework - [x] Angular 7 Support - [ ] Previous Angular Versions - [ ] Compiler Directives **Note:** If you see that some feature is missing, you can open a pull request or write an issue, and tell what feature is missing. ## Contributing To contribute you can open a **pull request** with the changes to improve in the code, or open a new **issue**.