Aurora
Ibyar Aurora, is a web framework, that can create and define a Web Component standards ('custom elements', 'Shadow DOM' and 'HTML Templates'), that compatible with other frameworks, using Typescript.
This framework build with-in a embedded JavaScript Engine @ibyar/expressions to execute Template syntax and attributes binding.
- Demo: https://muhammad-salem.github.io/aurora-demo
- API Doc: https://muhammad-salem.github.io/aurora-docs
- Ibyar Expression & Elements parser: https://muhammad-salem.github.io/astexplorer
- select: JavaScript: @ibyar/expressions
- select: HTML: @ibyar/elements
- Custom Elements Everywhere for Aurora Test & Results: https://muhammad-salem.github.io/custom-elements-everywhere/libraries/aurora/results/results.html
CLI Install
npm i -g @ibyar/cliyarn global add @ibyar/cliInstall
npm i --save @ibyar/aurorayarn add @ibyar/auroraDependencies
| README | Description | NPM, PKG, SRC |
|---|---|---|
| @ibyar/cli | ibyar cli package | |
| @ibyar/aurora | a central package to manage dependance only | |
| @ibyar/core | create components, render elements bind attributes and handling events |
|
| @ibyar/expressions | a JavaScript engine, parser and evaluator build by the guid of V8 JavaScript engine. Introduce a reactive scope concept to detect changes for scope variables, subscriptions based on a wave effect like concept,(simple what is subscribed will only be reevaluated again). Follow ESTree structural to generate an ast object. |
|
| @ibyar/elements | parse HTML Template,has tag names, properties for each tag |
|
| @ibyar/pipes | implement all supported pipes | |
| @ibyar/directives | implement all supported directives | |
| @ibyar/platform | utility package for and plural stuff, json patch | |
| @ibyar/router | has the built-in directives for router and navigation | |
| @ibyar/forms | contain form group, form builder and native ui form group | |
| @ibyar/decorators | ibyar decorators package | |
| typescript | Runtime library for TypeScript helpers. | |
| tslib | Runtime library for TypeScript helpers. |
'HTML Template' Features
| Support | HTML Template |
|---|---|
| Parsing Attributes | ✓ |
| One Way Data Binding | ✓ |
| Two Way Data Binding | ✓ |
| Event Binding | ✓ |
| Template Parser | ✓ |
| Template Syntax | ✓ |
| Control Flow Syntax | ✓ |
| Variables in templates | ✓ |
| Template Reference Variables | ✓ |
| Template HTML File | fetch or embedded |
| Fragment | ✓ |
| camelCase Property Naming | ✓ |
| lowercase for root element Property Naming | ✓ |
Library Features
- <input checked="" disabled="" type="checkbox"> ES Module
- <input checked="" disabled="" type="checkbox"> Dependency Injection
- <input checked="" disabled="" type="checkbox"> Component
- <input checked="" disabled="" type="checkbox"> Directives (Attribute and Structural Directives)
- <input checked="" disabled="" type="checkbox"> Pipes
- <input checked="" disabled="" type="checkbox"> Modules
- <input checked="" disabled="" type="checkbox"> Lifecycle
- <input checked="" disabled="" type="checkbox"> Signals
- <input checked="" disabled="" type="checkbox"> input signal
- <input checked="" disabled="" type="checkbox"> output signal
- <input checked="" disabled="" type="checkbox"> view signal
- <input checked="" disabled="" type="checkbox"> viewChild signal
- <input checked="" disabled="" type="checkbox"> @HostListener [Supported by Component and Attribute directive].
- <input checked="" disabled="" type="checkbox"> @HostBinding [Supported by Component and Attribute directive].
- <input disabled="" type="checkbox"> XSS (cross-site-scripting)
Lifecycle
- OnChanges
- OnInit
- DoCheck
- AfterContentInit
- AfterContentChecked
- AfterViewInit
- AfterViewChecked
- OnViewMove
- OnViewAdopted
- OnDestroy
Built-in Directive
Structure Directives
- <input checked="" disabled="" type="checkbox"> *if
- <input checked="" disabled="" type="checkbox"> *for is same as ( *forOf )
- <input checked="" disabled="" type="checkbox"> *forIn
- <input checked="" disabled="" type="checkbox"> *forAwait
- <input checked="" disabled="" type="checkbox"> switch and (case, *default)
-- support control flow syntax
-- see directive syntax structural-directive-syntax-reference
Attributes Directives
- <input checked="" disabled="" type="checkbox"> class [support
Single class binding,Multi-class binding]. - <input checked="" disabled="" type="checkbox"> style [support
Single style binding,Multi-style binding]. theSingle style binding with unitsnot yet supported.
Built-in Pipes ( Pipeline operator '|>' )
- <input checked="" disabled="" type="checkbox"> async
- <input checked="" disabled="" type="checkbox"> json
- <input checked="" disabled="" type="checkbox"> lowercase
- <input checked="" disabled="" type="checkbox"> uppercase
- <input checked="" disabled="" type="checkbox"> titlecase
- <input checked="" disabled="" type="checkbox"> keyvalue
- <input checked="" disabled="" type="checkbox"> slice
- <input disabled="" type="checkbox"> date
- <input disabled="" type="checkbox"> currency
- <input disabled="" type="checkbox"> number
- <input disabled="" type="checkbox"> percent
- <input disabled="" type="checkbox"> i18nPlural
- <input disabled="" type="checkbox"> i18nSelect
Web Component standards
- <input checked="" disabled="" type="checkbox"> Custom Elements
- <input checked="" disabled="" type="checkbox"> Shadow DOM
- <input checked="" disabled="" type="checkbox"> HTML Templates Element
- <input checked="" disabled="" type="checkbox"> HTML Templates Element with Shadow DOM
Custom Elements standards
- <input checked="" disabled="" type="checkbox"> Reflecting Properties to Attributes
- <input checked="" disabled="" type="checkbox"> Observing Changes to Attributes
- <input checked="" disabled="" type="checkbox"> Element Upgrades
- <input checked="" disabled="" type="checkbox"> Styling a Custom Element
- <input checked="" disabled="" type="checkbox"> Extending native HTML elements
- <input disabled="" type="checkbox"> Extending a Custom Element
- <input checked="" disabled="" type="checkbox"> Two Component On Same Model Class
- <input disabled="" type="checkbox"> Two Component Share Same Model Instance
Shadow DOM standards
- <input checked="" disabled="" type="checkbox"> Open Mode
- <input checked="" disabled="" type="checkbox"> Closed Mode
- <input checked="" disabled="" type="checkbox"> delegatesFocus
- <input checked="" disabled="" type="checkbox"> Shadow DOM event model
HTML Templates Element standards
- <input checked="" disabled="" type="checkbox"> Load template by ID from document
- <input checked="" disabled="" type="checkbox"> As Normal Custom Element
- <input checked="" disabled="" type="checkbox"> As Shadow DOM Element
how to bundle your package before publish
# always run ibyar cli to pre-build (AOT) your template and view types.
ibyar --build
#or
ibyar --build --watchHow to use:
HTML -- template parser example
in a polyfills.ts file
- use
aurorazone for detect changes
import 'zone.js';
import { bootstrapZone } from '@ibyar/aurora';
bootstrapZone('aurora');- or use
manualZone, if you don't like to useZone.jsall the events likerxjsobservables, setTimeout and fetch, etc.. can't be detected, use signals to connect to variables changes, provide better debugging experience.
import { bootstrapZone } from '@ibyar/aurora';
bootstrapZone('manual');- or use
proxyZone, if you don't like to useZone.jsbut still like to have full change detection for your application. it my be hard in debugging your application.
import { bootstrapZone } from '@ibyar/aurora';
bootstrapZone('proxy');you still can control the zone peer component while define your component by add
zonet one of the zone types 'aurora', 'manual' and 'proxy'. ifaurorais selected, you need to import theZone.jspackage.the
zoneproperty in the@Component({zone: 'manual'})is optional and will get the default value frombootstrapZone()
import { Component, HostListener, isModel, OnDestroy, OnInit } from '@ibyar/aurora';
import { interval, Subscription } from 'rxjs';
@Component({
selector: 'pipe-app',
zone: 'AURORA',
template: `
<style>.bs-color{color: var({{currentColor}});}</style>
@for(let color of colors; let i = index, isOdd = odd) {
isOdd :{{ isOdd? 'odd': 'even'}}
color: {{color}}
}
<!-- Local template variables -->
@let name = user.name;
@let name = user.name, age = user.age; <!-- comma separated variable declaration -->
@let greeting = 'Hello, ' + name;
@let data = data$ | async;
@let pi = 3.1459;
@let coordinates = {x: 50, y: 100};
@let longExpression = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit ' +
'sed do eiusmod tempor incididunt ut labore et dolore magna ' +
'Ut enim ad minim veniam...';
<div *for="const color of colors">
color: {{color}} <span *if="color === currentColor" class="bs-color"> Current Color ='{{currentColor}}'</span>
</div>
<table class="table">
<thead>
<tr>
<th class="bs-color" scope="col">pipe</th>
<th class="bs-color" scope="col">expression</th>
<th class="bs-color" scope="col">view</th>
</tr>
</thead>
<tbody>
<tr>
<td>async</td>
<td>observable |> async</td>
<td>{{observable |> async}}</td>
</tr>
<tr>
<td>*</td>
<td>text</td>
<td>{{text}}</td>
</tr>
<tr>
<td>lowercase</td>
<td>text |> lowercase</td>
<td>{{text |> lowercase}}</td>
</tr>
<tr>
<td>titlecase</td>
<td>text |> titlecase</td>
<td>{{text |> titlecase}}</td>
</tr>
<tr>
<td>uppercase</td>
<td>text |> uppercase</td>
<td>{{text |> uppercase}}</td>
</tr>
<tr>
<td>json</td>
<td>obj |> json</td>
<td>{{obj |> json}}</td>
</tr>
<tr>
<td>json <small>pre element</small></td>
<td>obj |> json:undefined:2</td>
<td>
<pre>{{obj |> json:undefined:2}}</pre>
</td>
</tr>
<tr>
<td>keyvalue</td>
<td>keyValueObject |> keyvalue</td>
<td>{{keyValueObject |> keyvalue |> json}}</td>
</tr>
<tr>
<td>keyvalue</td>
<td>keyValueObject |> keyvalue</td>
<td>{{keyValueObject |> keyvalue |> json}}</td>
</tr>
<tr>
<td>keyvalue</td>
<td>keyValueMap |> keyvalue</td>
<td>{{keyValueMap |> keyvalue |> json}}</td>
</tr>
<tr>
<td>slice</td>
<td>array |> slice:1:3</td>
<td>{{array |> slice:1:3}}</td>
</tr>
<tr>
<td>slice</td>
<td>slice(array, 1, 3)</td>
<td>{{slice(array, 1, 3)}}</td>
</tr>
<tr>
<td>call windows method directly</td>
<td>3345.54645 |> Math.trunc</td>
<td>{{3345.54645 |> Math.trunc}}</td>
</tr>
</tbody>
</table>
`
})
export class PipeAppComponent implements OnInit, OnDestroy {
text = 'Lorem ipsum is placeholder text commonly used in the graphic, print, and publishing industries for previewing layouts and visual mockups';
obj = {
a: [1, 2, 3],
b: 'property b',
c: {
d: [],
e: 4,
f: [{ 5: 'g' }]
}
};
keyValueObject = {
1: 100,
a: 'A00'
};
keyValueArray = [200, 300];
keyValueMap = new Map<number, number | string>([[1, 400], [2, 500], [3, 'B200']]);
observable = interval(1000);
array = ['a', 'b', 'c', 'd'];
readonly name = input('name');
readonly age = input.required();
readonly inputWithAlias = input('init-value', { alias: 'alias-name-1' });
readonly requiredInputWithAlias = input.required({ alias: 'alias-name-2' });
readonly event = output<string>();
colors = [
'--bs-blue',
'--bs-indigo',
'--bs-purple',
'--bs-pink',
'--bs-red',
'--bs-orange',
'--bs-yellow',
'--bs-green',
'--bs-teal',
'--bs-cyan',
'--bs-white',
'--bs-gray',
'--bs-gray-dark'
];
currentColor = this.colors[0];
subscription: Subscription;
onInit() {
let index = 0;
this.subscription = this.observable.subscribe(() => {
if (index === this.colors.length) {
index = 0;
}
this.currentColor = this.colors[index++];
if (isModel(this)) {
this.emitChangeModel('currentColor');
}
console.log(this.currentColor);
});
}
@HostListener('currentColor')
onCurrentColorChange() {
console.log(this.currentColor);
}
onDestroy() {
this.subscription.unsubscribe();
}
}
in index.html add:
<body>
<pipe-app></pipe-app>
<script type="module" src="path-to-main-file/index.js"></script>
</body>how to build
git clone https://github.com/ibyar/aurora.git
cd aurora
yarn install
yarn buildFor NPM 7(workshop support):
git clone https://github.com/ibyar/aurora.git
cd aurora
npm install
npm run buildsee test app for full example
Integration with Webpack
add @ibyar/cli as loader
module.exports = {
entry: './src/index.ts',
module: {
exprContextCritical: false,
rules: [
{
test: /\.tsx?$/,
use: ['@ibyar/cli',],
exclude: /node_modules/,
}
]
}
};use ts-loader
// 1. import default from the plugin module
import {
beforeCompileDirectiveOptions, beforeCompileComponentOptions,
afterDeclarationsCompileComponentOptions,
afterDeclarationsCompileDirectiveOptions,
scanDirectivesOnceAsTransformer,
} from '@ibyar/cli';
// 3. add getCustomTransformer method to the loader config
var config = {
...
module: {
rules: [
{
test: /\.tsx?$/,
loader: 'ts-loader',
options: {
... // other loader's options
getCustomTransformers: () => ({
before: [
scanDirectivesOnceAsTransformer(),
beforeCompileDirectiveOptions,
beforeCompileComponentOptions,
],
after: [],
afterDeclarations: [
afterDeclarationsCompileComponentOptions,
afterDeclarationsCompileDirectiveOptions,
],
})
}
}
]
}
...
};Integration with Rollup
import typescript from '@rollup/plugin-typescript';
import {
beforeCompileDirectiveOptions, beforeCompileComponentOptions,
afterDeclarationsCompileComponentOptions,
afterDeclarationsCompileDirectiveOptions,
scanDirectivesOnceAsTransformer,
} from '@ibyar/cli';
export default = {
...,
plugins: [
typescript({
transformers: {
before: [
{ type: 'program', factory: scanDirectivesOnceAsTransformer() },
{ type: 'program', factory: beforeCompileDirectiveOptions },
{ type: 'program', factory: beforeCompileComponentOptions },
],
after: [],
afterDeclarations: [
{ type: 'program', factory: afterDeclarationsCompileComponentOptions },
{ type: 'program', factory: afterDeclarationsCompileDirectiveOptions },
],
}
}),
],
...
};
see test app for full webpack
see test app for full rollup