├── app └── templates │ ├── empty │ ├── src │ │ ├── module.js │ │ └── templates │ │ │ └── template.html │ ├── schema.json │ └── form.json │ ├── base │ ├── README.md │ ├── sources.json │ ├── _gitignore │ ├── demo │ │ ├── main.css │ │ └── index.html │ ├── package.json │ ├── bower.json │ └── gulpfile.js │ └── input │ ├── form.json │ ├── schema.json │ └── src │ ├── directives │ └── update-on-blur.js │ ├── module.js │ └── templates │ └── template.html ├── .jshintrc ├── .npmignore ├── .gitignore ├── .jscsrc ├── README.md ├── package.json ├── LICENSE └── index.js /app/templates/empty/src/module.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/templates/empty/schema.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "esnext": true 3 | } 4 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | index.js 2 | node_modules 3 | -------------------------------------------------------------------------------- /app/templates/empty/form.json: -------------------------------------------------------------------------------- 1 | ["*"] 2 | -------------------------------------------------------------------------------- /app/templates/base/README.md: -------------------------------------------------------------------------------- 1 | <%= name %> 2 | -------------------------------------------------------------------------------- /app/templates/empty/src/templates/template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/templates/base/sources.json: -------------------------------------------------------------------------------- 1 | <%- sources -%> 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | app/index.js 3 | app/index.js.map 4 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "airbnb", 3 | "esnext": true 4 | } 5 | -------------------------------------------------------------------------------- /app/templates/base/_gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_components 3 | -------------------------------------------------------------------------------- /app/templates/input/form.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "type": "", 4 | "key": "name", 5 | "myOwnFormOption": "Hello world!" 6 | } 7 | ] 8 | -------------------------------------------------------------------------------- /app/templates/base/demo/main.css: -------------------------------------------------------------------------------- 1 | .debug .wrapper { 2 | border: 1px solid #d6d6d6; 3 | border-radius: 5px; 4 | margin: 10px 0; 5 | } 6 | 7 | .debug .wrapper > div > div { 8 | padding: 0 25px; 9 | } 10 | -------------------------------------------------------------------------------- /app/templates/base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= paramName %>", 3 | "version": "1.0.0", 4 | "description": "<%= name %> add-on for Angular Schema Form.", 5 | "author": "<%= username %>", 6 | "license": "MIT", 7 | "devDependencies": {} 8 | } 9 | -------------------------------------------------------------------------------- /app/templates/input/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "properties": { 4 | "name": { 5 | "type": "string", 6 | "title": "Name", 7 | "description": "Name or alias", 8 | "maxLength": 10, 9 | "minLength": 2, 10 | "required": true 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/templates/base/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= paramName %>", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "author": "<%= username %>", 6 | "main": [ 7 | "dist/<%= paramName %>.min.js" 8 | ], 9 | "keywords": [ 10 | "angular-schema-form", 11 | "schema-form", 12 | "form", 13 | "json", 14 | "json-schema", 15 | "schema" 16 | ], 17 | "ignore": [ 18 | "**/.*", 19 | "node_modules", 20 | "bower_components", 21 | "test", 22 | "tests" 23 | ], 24 | "devDependencies": {} 25 | } 26 | -------------------------------------------------------------------------------- /app/templates/input/src/directives/update-on-blur.js: -------------------------------------------------------------------------------- 1 | angular.module('<%= module %>').directive('updateOnBlur', function () { 2 | return { 3 | restrict: 'E', 4 | require: 'ngModel', 5 | scope: {}, 6 | template: '', 7 | link: function (scope, element, attrs, ngModel) { 8 | scope.modelValue = ngModel.$viewValue; 9 | 10 | scope.updateModel = function (modelValue) { 11 | ngModel.$setViewValue(modelValue); 12 | }; 13 | }, 14 | }; 15 | }); 16 | -------------------------------------------------------------------------------- /app/templates/input/src/module.js: -------------------------------------------------------------------------------- 1 | angular.module('<%= module %>', [ 2 | 'schemaForm', 3 | 'templates' 4 | ]).config(function(schemaFormDecoratorsProvider, sfBuilderProvider) { 5 | 6 | schemaFormDecoratorsProvider.defineAddOn( 7 | 'bootstrapDecorator', // Name of the decorator you want to add to. 8 | '<%= formType %>', // Form type that should render this add-on 9 | 'src/templates/<%= paramName %>.html', // Template name in $templateCache 10 | sfBuilderProvider.stdBuilders // List of builder functions to apply. 11 | ); 12 | 13 | }); 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Angular Schema Form Add-on Generator 2 | ==================================== 3 | 4 | A Yeoman generator to scaffold a [Angular Schema Form](http://schemaform.io/) Add-on. 5 | 6 | Install 7 | --------------- 8 | `npm install -g yo gulp bower generator-angular-schema-form-add-on` 9 | 10 | Usage 11 | --------------- 12 | First create a directory 13 | 14 | `mkdir your-add-on && cd your-add-on` 15 | 16 | Run `yo` and select **Angular Schema Form Add On** 17 | 18 | OR 19 | 20 | Run `yo angular-schema-form-add-on` 21 | 22 | When yeoman is done, gulp default will minify and start a livereload server for you to test the add-on. 23 | 24 | Under development 25 | ----------------- 26 | Right now we have support for one starting form type **input**.. You can also choose **empty** which doesnt give you any example, just all the dependencies you need 27 | -------------------------------------------------------------------------------- /app/templates/input/src/templates/template.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

{{form.myOwnFormOption}}

5 | 6 | 7 | 8 | <% if (directive) { %> 9 | 10 | Blur this field to update the model. 11 | <% } else { %> 12 | 13 | <% } %> 14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "generator-angular-schema-form-add-on", 3 | "version": "0.1.3", 4 | "description": "A Yeoman generator for Angular Schema Form Add-Ons.", 5 | "main": "app/index.js", 6 | "files": [ 7 | "app" 8 | ], 9 | "keywords": [ 10 | "yeoman-generator" 11 | ], 12 | "scripts": { 13 | "compile": "babel index.js --out-file app/index.js --source-maps", 14 | "watch": "babel index.js --watch --out-file app/index.js --source-maps", 15 | "prepublish": "npm run compile" 16 | }, 17 | "babel": { 18 | "presets": [ 19 | "es2015" 20 | ] 21 | }, 22 | "repository": "json-schema-form/generator-angular-schema-form-add-on", 23 | "dependencies": { 24 | "babel-polyfill": "^6.5.0", 25 | "babel-preset-es2015": "^6.5.0", 26 | "camelcase": "^1.2.1", 27 | "chalk": "^1.1.1", 28 | "fs-promise": "^0.3.1", 29 | "fs-readdir-recursive": "^0.1.2", 30 | "q": "^1.4.1", 31 | "yeoman-generator": "^0.20.3", 32 | "yosay": "^1.1.0" 33 | }, 34 | "license": "MIT", 35 | "devDependencies": { 36 | "babel-cli": "^6.5.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Simon Korn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/templates/base/gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var connect = require('gulp-connect'); 3 | var uglify = require('gulp-uglify'); 4 | var concat = require('gulp-concat'); 5 | var rename = require('gulp-rename'); 6 | var templateCache = require('gulp-angular-templatecache'); 7 | var streamqueue = require('streamqueue'); 8 | var fs = require('fs'); 9 | 10 | gulp.task('default', ['minify', 'connect', 'watch']); 11 | 12 | gulp.task('connect', function () { 13 | connect.server({ 14 | root: ['demo', './'], 15 | livereload: true, 16 | }); 17 | }); 18 | 19 | gulp.task('reload', ['minify'], function () { 20 | gulp.src('./dist/**/*.*').pipe(connect.reload()); 21 | }); 22 | 23 | gulp.task('watch', function () { 24 | gulp.watch(['./src/**', './demo/**'], ['reload']); 25 | }); 26 | 27 | gulp.task('minify', function () { 28 | var files = JSON.parse(fs.readFileSync('sources.json', 'utf-8')); 29 | var stream = streamqueue({ objectMode: true }, 30 | gulp.src(['src/templates/**/*.html']).pipe(templateCache({ 31 | standalone: true, 32 | root: 'src/templates/', 33 | })), 34 | gulp.src(files) 35 | ) 36 | .pipe(concat('<%= paramName %>.js')) 37 | .pipe(gulp.dest('./dist')) 38 | .pipe(uglify()) 39 | .pipe(rename('<%= paramName %>.min.js')) 40 | .pipe(gulp.dest('./dist')); 41 | 42 | return stream; 43 | }); 44 | -------------------------------------------------------------------------------- /app/templates/base/demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 29 | Testing <%= name %> ASF addon 30 | 31 | 32 | 33 |
34 | 35 |
36 |
37 |
38 | 39 |
40 |
41 |
42 |
43 |

Model

44 |
{{model | json}}
45 |
46 |
47 |
48 |
49 |

Form

50 |
{{debug.form | json}}
51 |
52 |
53 |
54 |
55 |

Schema

56 |
{{debug.schema | json}}
57 |
58 |
59 |
60 |
61 |
62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import { Base } from 'yeoman-generator'; 3 | import yosay from 'yosay'; 4 | import camelcase from 'camelcase'; 5 | import chalk from 'chalk'; 6 | import read from 'fs-readdir-recursive'; 7 | 8 | class asfAddOnGenerator extends Base { 9 | 10 | constructor(...args) { 11 | super(...args); 12 | 13 | /* Setting up our config object 14 | */ 15 | this.addon = {}; 16 | } 17 | 18 | prompting() { 19 | /* Welcome the user!! 20 | */ 21 | this.log(yosay(`Hello and welcome to the Angular Schema Form Add-on Generator!`)); 22 | 23 | /* We tell yeoman we don't want to continue until we run our done(). 24 | */ 25 | const done = this.async(); 26 | 27 | this.prompt([ 28 | { 29 | type: 'input', 30 | name: 'name', 31 | message: 'Your add-on name', 32 | default: this.appname, 33 | }, 34 | { 35 | type: 'list', 36 | name: 'type', 37 | message: 'What kind of form type do you want?', 38 | choices: ['input', 'empty'], /*, 'Radio', 'Checkbox', 'Array'*/ 39 | default: 'input', 40 | }, 41 | { 42 | type: 'confirm', 43 | name: 'useDirective', 44 | message: 'Do you want a directive added to your addon?', 45 | default: true, 46 | }, 47 | { 48 | type: 'input', 49 | name: 'username', 50 | message: 'What\'s your Github username?', 51 | store: true, 52 | }, 53 | ], (answers) => { 54 | 55 | /* Nice, we now have all the answers. 56 | */ 57 | Object.assign(this.addon, answers); 58 | 59 | /* Changing cases 60 | */ 61 | this.addon.module = camelcase(this.addon.name); // ex. add on > addOn 62 | this.addon.formType = this.addon.name.replace(/ /g, ''); // ex. add on > addon 63 | this.addon.paramName = this.addon.name.replace(/ /g, '-'); // ex. add on > add-on 64 | 65 | /* We are done here... Let's continue 66 | */ 67 | done(); 68 | }); 69 | } 70 | 71 | configure() { 72 | 73 | /* Let's get a list of our base files and type specific files. 74 | */ 75 | this.addon.files = {}; 76 | 77 | /* I do not like this, it looks ugly too me. but hell, it works for now. 78 | */ 79 | this.addon.files.base = read(`${this.templatePath()}/base`); 80 | this.addon.files[this.addon.type] = read(`${this.templatePath()}/${this.addon.type}/src`); 81 | 82 | if (!this.addon.useDirective) { 83 | this.addon.files[this.addon.type] = this.addon.files[this.addon.type].filter(dir => !dir.includes('directives')) 84 | } 85 | 86 | } 87 | 88 | writing() { 89 | const done = this.async(); 90 | const schema = this.fs.read(this.templatePath(`${this.addon.type}/schema.json`)); 91 | let form = this.fs.read(this.templatePath(`${this.addon.type}/form.json`)); 92 | 93 | /* TODO: Just a fast and easy fix for now.. 94 | */ 95 | form = JSON.parse(form); 96 | if (form[0].hasOwnProperty('type')) { 97 | form[0].type = this.addon.formType; 98 | } 99 | 100 | const sources = []; 101 | const testModule = ['schemaForm']; 102 | 103 | if (this.addon.type !== 'empty') { 104 | testModule.push(this.addon.module); 105 | sources.push('src/module.js', 'src/**/*.js'); 106 | } 107 | 108 | this.addon.files.base.forEach((file) => { 109 | /* What to inject in the test controller 110 | */ 111 | const dest = file.replace('_', '.'); 112 | 113 | /* Base files */ 114 | this.fs.copyTpl( 115 | this.templatePath(this.templatePath('base/') + file), 116 | this.destinationPath('./') + dest, 117 | { 118 | name: this.addon.name, 119 | module: this.addon.module, 120 | testModuleInj: JSON.stringify(testModule), 121 | formType: this.addon.formType, 122 | paramName: this.addon.paramName, 123 | schema: schema, 124 | form: JSON.stringify(form), 125 | username: this.addon.username, 126 | sources: JSON.stringify(sources), 127 | } 128 | ); 129 | }); 130 | 131 | /* Type files */ 132 | this.addon.files[this.addon.type].forEach((file) => { 133 | const dest = file.replace('_', '.') 134 | .replace('template.html', `${this.addon.paramName}.html`) 135 | .replace('template.js', `${this.addon.paramName}.js`); 136 | 137 | this.fs.copyTpl( 138 | this.templatePath(this.templatePath(`${this.addon.type}/src/`) + file), 139 | this.destinationPath('./src/') + dest, 140 | { 141 | name: this.addon.name, 142 | module: this.addon.module, 143 | formType: this.addon.formType, 144 | paramName: this.addon.paramName, 145 | directive: this.addon.useDirective, 146 | } 147 | ); 148 | }); 149 | 150 | done(); 151 | } 152 | 153 | install() { 154 | const npmDevDeps = [ 155 | 'gulp', 156 | 'gulp-angular-templatecache', 157 | 'gulp-concat', 158 | 'gulp-connect', 159 | 'gulp-livereload', 160 | 'gulp-rename', 161 | 'gulp-server-livereload', 162 | 'gulp-uglify', 163 | 'streamqueue', 164 | ]; 165 | 166 | const bowerDevDeps = [ 167 | 'angular-schema-form', 168 | 'angular-schema-form-bootstrap', 169 | 'bootstrap', 170 | ]; 171 | 172 | this.log(chalk.white(`\nAlmost done! Just running ${chalk.green.bold('npm install')} and ${chalk.green.bold('bower install')} for you!\n`)); 173 | 174 | this.npmInstall(npmDevDeps, { saveDev: true }); 175 | this.bowerInstall(bowerDevDeps, { saveDev: true }); 176 | } 177 | 178 | end() { 179 | this.log(chalk.green(`\nEverything is done! \nJust run ${chalk.bold.green('gulp')} to start a livereload server to test your addon.`)); 180 | } 181 | 182 | } 183 | 184 | module.exports = asfAddOnGenerator; 185 | --------------------------------------------------------------------------------