Skip to content

Commit

Permalink
feat(elements): web custom element generator (#96)
Browse files Browse the repository at this point in the history
  • Loading branch information
NathanWalker authored Mar 17, 2019
1 parent adec8fb commit d3c1661
Show file tree
Hide file tree
Showing 42 changed files with 771 additions and 84 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ The scope must be one of the following:
* ionic
* nativescript
* nest
* elements
* helpers

#### Subject
Expand Down
4 changes: 2 additions & 2 deletions src/app.electron/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import {
noop
} from '@angular-devkit/schematics';
import { Schema as ApplicationOptions } from './schema';
import { prerun, getPrefix, getNpmScope, stringUtils, addRootDeps, updateAngularProjects, updateNxProjects, formatFiles, getJsonFromFile, updatePackageScripts, addPostinstallers, applyAppNamingConvention, getGroupByName, getAppName, missingNameArgument } from '../utils';
import { prerun, getPrefix, getNpmScope, stringUtils, addRootDeps, updateAngularProjects, updateNxProjects, formatFiles, getJsonFromFile, updatePackageScripts, addPostinstallers, applyAppNamingConvention, getGroupByName, getAppName, missingArgument } from '../utils';

export default function (options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
missingNameArgument('Provide a name for your Electron app.', 'ng g app.electron sample')
missingArgument('name', 'Provide a name for your Electron app.', 'ng g app.electron sample')
);
}
if (!options.target) {
Expand Down
4 changes: 2 additions & 2 deletions src/app.ionic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import {
schematic,
noop,
} from '@angular-devkit/schematics';
import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, formatFiles, applyAppNamingConvention, getAppName, missingNameArgument } from '../utils';
import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, formatFiles, applyAppNamingConvention, getAppName, missingArgument } from '../utils';
import { Schema as ApplicationOptions } from './schema';

export default function (options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
missingNameArgument('Provide a name for your Ionic app.', 'ng g app.ionic sample')
missingArgument('name', 'Provide a name for your Ionic app.', 'ng g app.ionic sample')
);
}

Expand Down
4 changes: 2 additions & 2 deletions src/app.nativescript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ import {
schematic,
noop,
} from '@angular-devkit/schematics';
import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, applyAppNamingConvention, getGroupByName, getAppName, missingNameArgument } from '../utils';
import { stringUtils, prerun, getNpmScope, getPrefix, addRootDeps, updatePackageScripts, updateAngularProjects, updateNxProjects, applyAppNamingConvention, getGroupByName, getAppName, missingArgument } from '../utils';
import { Schema as ApplicationOptions } from './schema';

export default function (options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
missingNameArgument('Provide a name for your NativeScript app.', 'ng g app.nativescript sample')
missingArgument('name', 'Provide a name for your NativeScript app.', 'ng g app.nativescript sample')
);
}
if (options.setupSandbox) {
Expand Down
6 changes: 3 additions & 3 deletions src/app.nest/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ import {
prerun,
applyAppNamingConvention,
getAppName,
missingNameArgument,
updateJsonInTree
updateJsonInTree,
missingArgument
} from "../utils";

export default function (options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
missingNameArgument('Provide a name for your Nest app.', 'ng g app.nest sample')
missingArgument('name', 'Provide a name for your Nest app.', 'ng g app.nest sample')
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
<div class="p-x-20">
<div style="text-align:center">
<h2>
Welcome to an Angular CLI app built with Nrwl Nx and xplat!
</h2>
<img width="100" src="assets/nx-logo.png">
<span style="position: relative;top: -28px;margin: 10px;">+</span>
<img width="120" src="assets/xplat.png">
</div>
<<%= prefix %>-header title="<%= name %>"></<%= prefix %>-header>

<h2>Nx</h2>

Expand Down
46 changes: 18 additions & 28 deletions src/app.web/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ import {
applyAppNamingConvention,
updateJsonFile,
formatFiles,
missingNameArgument
missingArgument
} from "../utils";
import { Schema as ApplicationOptions } from "./schema";

export default function(options: ApplicationOptions) {
if (!options.name) {
throw new SchematicsException(
missingNameArgument('Provide a name for your Web app.', 'ng g app my-app')
missingArgument('name', 'Provide a name for your Web app.', 'ng g app my-app')
);
}
// ensure sass is used
Expand Down Expand Up @@ -173,32 +173,22 @@ platformBrowserDynamic()

function appCmpHtml(name: string) {
return `<div class="p-x-20">
<div style="text-align:center">
<h1>
Welcome to ${name}!
</h1>
<h3>
An Angular CLI app built with Nrwl Nx and xplat.
</h3>
<img width="100" src="assets/nx-logo.png">
<span style="position: relative;top: -28px;margin: 10px;">+</span>
<img width="120" src="assets/xplat.png">
</div>
<h3>Nx</h3>
An open source toolkit for enterprise Angular applications. Nx is designed to help you create and build enterprise grade
Angular applications. It provides an opinionated approach to application project structure and patterns.
<h3>Quick Start & Documentation</h3>
<a href="https://nrwl.io/nx" target="_blank">Watch a 5-minute video on how to get started with Nx.</a>
<h2>{{'hello' | translate}}</h2>
<h3>Try things out</h3>
<a href="https://nstudio.io/xplat/generators/" target="_blank">Learn more about xplat generators.</a>
</div>`;
<${getPrefix()}-header title="${name}"></${getPrefix()}-header>
<h2>Nx</h2>
An open source toolkit for enterprise Angular applications. Nx is designed to help you create and build enterprise grade
Angular applications. It provides an opinionated approach to application project structure and patterns.
<h3>Quick Start & Documentation</h3>
<a href="https://nrwl.io/nx">Watch a 5-minute video on how to get started with Nx.</a>
<h1>{{'hello' | translate}}</h1>
<h3>Try things out</h3>
<a href="https://nstudio.io/xplat">Learn more about xplat.</a>
</div>`;
}

function appCmpContent() {
Expand Down
5 changes: 5 additions & 0 deletions src/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
"schema": "./app.web/schema.json",
"description": "Nx web app with xplat support."
},
"elements": {
"factory": "./elements",
"schema": "./elements/schema.json",
"description": "Create custom elements for the web."
},
"feature": {
"factory": "./feature",
"schema": "./feature/schema.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div><% if (onlyProject || ignoreBase) { %><%= utils.classify(name) %><% } else { %>{{text}}<% } %></div>
<div><% if (onlyProject || !createBase) { %><%= utils.classify(name) %><% } else { %>{{text}}<% } %></div>
4 changes: 2 additions & 2 deletions src/component/_ionic_files/__name__/__name__.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Component } from '@angular/core';

<% if (onlyProject || ignoreBase) { %>import { BaseComponent } from '@<%= npmScope %>/core';<%
<% if (onlyProject || !createBase) { %>import { BaseComponent } from '@<%= npmScope %>/core';<%
} else { %>import { <%= utils.classify(name) %>BaseComponent } from '@<%= npmScope %>/features';<% } %>

@Component({
selector: '<%= prefix %>-<%= name %>',
templateUrl: '<%= name %>.component.html'
})
export class <%= utils.classify(name) %>Component extends <%= onlyProject || ignoreBase ? '' : utils.classify(name) %>BaseComponent {
export class <%= utils.classify(name) %>Component extends <%= onlyProject || !createBase ? '' : utils.classify(name) %>BaseComponent {

constructor() {
super();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<StackLayout class="p-20">
<Label <% if (onlyProject || ignoreBase) { %>text="<%= utils.classify(name) %>"<% } else { %>[text]="text"<% } %> class="text-center"></Label>
<Label <% if (onlyProject || !createBase) { %>text="<%= utils.classify(name) %>"<% } else { %>[text]="text"<% } %> class="text-center"></Label>
</StackLayout>
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Component } from '@angular/core';

<% if (onlyProject || ignoreBase) { %>import { BaseComponent } from '@<%= npmScope %>/core';<%
<% if (onlyProject || !createBase) { %>import { BaseComponent } from '@<%= npmScope %>/core';<%
} else { %>import { <%= utils.classify(name) %>BaseComponent } from '@<%= npmScope %>/features';<% } %>

@Component({
moduleId: module.id,
selector: '<%= prefix %>-<%= name %>',
templateUrl: './<%= name %>.component.html'
})
export class <%= utils.classify(name) %>Component extends <%= onlyProject || ignoreBase ? '' : utils.classify(name) %>BaseComponent {
export class <%= utils.classify(name) %>Component extends <%= onlyProject || !createBase ? '' : utils.classify(name) %>BaseComponent {

constructor() {
super();
Expand Down
2 changes: 1 addition & 1 deletion src/component/_web_files/__name__/__name__.component.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div><% if (onlyProject || ignoreBase) { %><%= utils.classify(name) %><% } else { %>{{text}}<% } %></div>
<div><% if (onlyProject || !createBase) { %><%= utils.classify(name) %><% } else { %>{{text}}<% } %></div>
4 changes: 2 additions & 2 deletions src/component/_web_files/__name__/__name__.component.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Component } from '@angular/core';

<% if (onlyProject || ignoreBase) { %>import { BaseComponent } from '@<%= npmScope %>/core';<%
<% if (onlyProject || !createBase) { %>import { BaseComponent } from '@<%= npmScope %>/core';<%
} else { %>import { <%= utils.classify(name) %>BaseComponent } from '@<%= npmScope %>/features';<% } %>

@Component({
selector: '<%= prefix %>-<%= name %>',
templateUrl: '<%= name %>.component.html'
})
export class <%= utils.classify(name) %>Component extends <%= onlyProject || ignoreBase ? '' : utils.classify(name) %>BaseComponent {
export class <%= utils.classify(name) %>Component extends <%= onlyProject || !createBase ? '' : utils.classify(name) %>BaseComponent {

constructor() {
super();
Expand Down
6 changes: 3 additions & 3 deletions src/component/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,15 @@ export default function(options: featureOptions) {
prerun(),
// add component for base libs feature
(tree: Tree, context: SchematicContext) =>
!options.onlyProject && !options.ignoreBase
!options.onlyProject && options.createBase
? addToFeature("component", options, "libs", tree, "_base", true)(
tree,
context
)
: noop()(tree, context),
// adjust libs barrel for subFolder
(tree: Tree, context: SchematicContext) =>
options.subFolder && !options.onlyProject && !options.ignoreBase
options.subFolder && !options.onlyProject && options.createBase
? adjustBarrelIndex(
"component",
options,
Expand All @@ -239,7 +239,7 @@ export default function(options: featureOptions) {
: noop()(tree, context),
// adjust libs barrel
(tree: Tree, context: SchematicContext) =>
!options.onlyProject && !options.ignoreBase
!options.onlyProject && options.createBase
? adjustBarrelIndex(
"component",
options,
Expand Down
3 changes: 2 additions & 1 deletion src/component/index_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ describe('component schematic', () => {
const defaultOptions: GenerateOptions = {
name: 'signup',
feature: 'foo',
platforms: 'nativescript,web'
platforms: 'nativescript,web',
createBase: true
};

let appTree: Tree;
Expand Down
4 changes: 2 additions & 2 deletions src/component/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ export interface Schema {
*/
platforms?: string;
/**
* Ignore base component generation
* Create a base component for maximum cross platform sharing
*/
ignoreBase?: boolean;
createBase?: boolean;
/**
* Schematic processing helpers
*/
Expand Down
4 changes: 2 additions & 2 deletions src/component/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@
"type": "string",
"description": "Target platforms"
},
"ignoreBase": {
"createBase": {
"type": "boolean",
"description": "Ignore base component generation.",
"description": "Create a base component for maximum cross platform sharing.",
"default": false
},
"skipFormat": {
Expand Down
6 changes: 6 additions & 0 deletions src/elements/_builder_files/builder/elements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { <%= utils.classify(name) %>Module } from '../<%= name %>.module';

platformBrowserDynamic()
.bootstrapModule(<%= utils.classify(name) %>Module)
.catch(err => console.log(err));
13 changes: 13 additions & 0 deletions src/elements/_builder_files/builder/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Custom Elements</title>
<base href="/">

<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<%= htmlElements %>
</body>
</html>
81 changes: 81 additions & 0 deletions src/elements/_builder_files/builder/polyfills.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
*/

/***************************************************************************************************
* BROWSER POLYFILLS
*/

/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';


/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';


/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
**/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.

/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
*/

// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames

/*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*/
// (window as any).__Zone_enable_cross_context_check = true;

/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.



/***************************************************************************************************
* APPLICATION IMPORTS
*/
import '@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js';
Loading

0 comments on commit d3c1661

Please sign in to comment.