├── .babelrc
├── test
├── data.zip
├── setup
│ ├── .globals.json
│ ├── browser.js
│ ├── node.js
│ └── setup.js
├── .eslintrc
├── data
│ ├── types.json
│ ├── simple.json
│ ├── conditional-required.json
│ ├── generator-definition.json
│ ├── grid.json
│ ├── complex-keys.json
│ ├── tabarray.json
│ ├── array.json
│ ├── titlemaps.json
│ └── sink.json
├── unit
│ └── json-schema-form-generator.js
└── runner.html
├── CHANGELOG.md
├── .eslintrc
├── .travis.yml
├── .editorconfig
├── src
├── model-to-jsf.js
├── json-schema-form-generator.js
├── jsf-to-model.js
├── generator-form.js
├── form-definitions-generator.js
└── generator-schema.js
├── .gitignore
├── LICENSE
├── package.json
├── README.md
├── gulpfile.js
└── dist
└── json-schema-form-generator.min.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
4 |
--------------------------------------------------------------------------------
/test/data.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/json-schema-form/json-schema-form-generator-es6/master/test/data.zip
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ### [0.0.1](https://github.com/json-schema-form/json-schema-form-generator/releases/tag/v0.0.1)
2 |
3 | - The first release
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parserOptions": {
3 | "ecmaVersion": 6,
4 | "sourceType": "module"
5 | },
6 | "rules": {},
7 | "env": {
8 | "browser": true,
9 | "node": true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4"
4 | - "5"
5 | - "stable"
6 | sudo: false
7 | script: "gulp coverage"
8 | after_success:
9 | - npm install -g codeclimate-test-reporter
10 | - codeclimate-test-reporter < coverage/lcov.info
11 |
--------------------------------------------------------------------------------
/test/setup/.globals.json:
--------------------------------------------------------------------------------
1 | {
2 | "globals": {
3 | "expect": true,
4 | "mock": true,
5 | "sandbox": true,
6 | "spy": true,
7 | "stub": true,
8 | "useFakeServer": true,
9 | "useFakeTimers": true,
10 | "useFakeXMLHttpRequest": true
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/test/setup/browser.js:
--------------------------------------------------------------------------------
1 | var mochaGlobals = require('./.globals.json').globals;
2 |
3 | window.mocha.setup('bdd');
4 | window.onload = function() {
5 | window.mocha.checkLeaks();
6 | window.mocha.globals(Object.keys(mochaGlobals));
7 | window.mocha.run();
8 | require('./setup')(window);
9 | };
10 |
--------------------------------------------------------------------------------
/test/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./setup/.globals.json",
3 | "parserOptions": {
4 | "ecmaVersion": 6,
5 | "sourceType": "module"
6 | },
7 | "rules": {
8 | "strict": 0,
9 | "quotes": [2, "single"],
10 | "no-unused-expressions": 0
11 | },
12 | "env": {
13 | "browser": true,
14 | "node": true,
15 | "mocha": true
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | root = true;
4 |
5 | [*]
6 | # Ensure there's no lingering whitespace
7 | trim_trailing_whitespace = true
8 | # Ensure a newline at the end of each file
9 | insert_final_newline = true
10 |
11 | [*.js]
12 | # Unix-style newlines
13 | end_of_line = lf
14 | charset = utf-8
15 | indent_style = space
16 | indent_size = 2
17 |
--------------------------------------------------------------------------------
/test/data/types.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "title": "Types",
5 | "properties": {
6 | "string": {
7 | "type": "string",
8 | "minLength": 3
9 | },
10 | "integer": {
11 | "type": "integer"
12 | },
13 | "number": {
14 | "type": "number"
15 | },
16 | "boolean": {
17 | "type": "boolean"
18 | }
19 | },
20 | "required": ["number"]
21 | },
22 | "form": [
23 | "*",
24 | {"type": "submit", "title": "OK"}
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/test/unit/json-schema-form-generator.js:
--------------------------------------------------------------------------------
1 | import jsonSchemaFormGenerator from '../../src/json-schema-form-generator';
2 |
3 | describe('jsonSchemaFormGenerator', () => {
4 | describe('Greet function', () => {
5 | beforeEach(() => {
6 | spy(jsonSchemaFormGenerator, 'greet');
7 | jsonSchemaFormGenerator.greet();
8 | });
9 |
10 | it('should have been run once', () => {
11 | expect(jsonSchemaFormGenerator.greet).to.have.been.calledOnce;
12 | });
13 |
14 | it('should have always returned hello', () => {
15 | expect(jsonSchemaFormGenerator.greet).to.have.always.returned('hello');
16 | });
17 | });
18 | });
19 |
--------------------------------------------------------------------------------
/src/model-to-jsf.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash'),
2 | formGenerator = require('./form-definitions-generator').default,
3 | definitions;
4 |
5 | const modelToJSF = {
6 | getFormDefinitions(model){
7 | "use strict";
8 | definitions = {schema: {type: 'object', properties: {}}, form: []};
9 | if (_.isArray(model.fields)) {
10 | _.forEach(model.fields, (field) => {
11 | if (field.type) {
12 | definitions = formGenerator.generateField(field, definitions);
13 | }
14 | }
15 | );
16 | }
17 | return definitions;
18 | },
19 | addField(field){
20 |
21 | }
22 | };
23 |
24 | export default modelToJSF;
25 |
--------------------------------------------------------------------------------
/src/json-schema-form-generator.js:
--------------------------------------------------------------------------------
1 | const _ = require('lodash'),
2 | jsfToModel = require('./jsf-to-model.js').default,
3 | modelToJsf = require('./model-to-jsf.js').default;
4 | const jsonSchemaFormGenerator = {
5 | getFormBuilder(schema, form) {
6 | let _schema, _form, _model;
7 | _schema = jsfToModel.getSchema();
8 | _form = jsfToModel.getForm();
9 | _model = jsfToModel.getModel(schema, form);
10 | return {
11 | schema: _schema,
12 | form: _form,
13 | model: _model
14 | }
15 | },
16 | getDefinitions(model){
17 | "use strict";
18 | return modelToJsf.getFormDefinitions(model);
19 | },
20 |
21 | };
22 |
23 | export default jsonSchemaFormGenerator;
24 |
--------------------------------------------------------------------------------
/test/setup/node.js:
--------------------------------------------------------------------------------
1 | global.chai = require('chai');
2 | global.sinon = require('sinon');
3 | global.chai.use(require('sinon-chai'));
4 |
5 | require('babel-core/register');
6 | require('./setup')();
7 |
8 | /*
9 | Uncomment the following if your library uses features of the DOM,
10 | for example if writing a jQuery extension, and
11 | add 'simple-jsdom' to the `devDependencies` of your package.json
12 |
13 | Note that JSDom doesn't implement the entire DOM API. If you're using
14 | more advanced or experimental features, you may need to switch to
15 | PhantomJS. Setting that up is currently outside of the scope of this
16 | boilerplate.
17 | */
18 | // import simpleJSDom from 'simple-jsdom';
19 | // simpleJSDom.install();
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Commenting this out is preferred by some people, see
24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
25 | node_modules
26 | bower_components
27 | coverage
28 | tmp
29 |
30 | # Users Environment Variables
31 | .lock-wscript
32 | .idea
--------------------------------------------------------------------------------
/test/setup/setup.js:
--------------------------------------------------------------------------------
1 | module.exports = function(root) {
2 | root = root ? root : global;
3 | root.expect = root.chai.expect;
4 |
5 | beforeEach(function() {
6 | // Using these globally-available Sinon features is preferrable, as they're
7 | // automatically restored for you in the subsequent `afterEach`
8 | root.sandbox = root.sinon.sandbox.create();
9 | root.stub = root.sandbox.stub.bind(root.sandbox);
10 | root.spy = root.sandbox.spy.bind(root.sandbox);
11 | root.mock = root.sandbox.mock.bind(root.sandbox);
12 | root.useFakeTimers = root.sandbox.useFakeTimers.bind(root.sandbox);
13 | root.useFakeXMLHttpRequest = root.sandbox.useFakeXMLHttpRequest.bind(root.sandbox);
14 | root.useFakeServer = root.sandbox.useFakeServer.bind(root.sandbox);
15 | });
16 |
17 | afterEach(function() {
18 | delete root.stub;
19 | delete root.spy;
20 | root.sandbox.restore();
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/test/data/simple.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "title": "Comment",
5 | "properties": {
6 | "name": {
7 | "title": "Name",
8 | "type": "string"
9 | },
10 | "email": {
11 | "title": "Email",
12 | "type": "string",
13 | "pattern": "^\\S+@\\S+$",
14 | "description": "Email will be used for evil."
15 | },
16 | "comment": {
17 | "title": "Comment",
18 | "type": "string",
19 | "maxLength": 20,
20 | "validationMessage": "Don't be greedy!"
21 | }
22 | },
23 | "required": ["name","email","comment"]
24 | },
25 | "form": [
26 | "name",
27 | "email",
28 | {
29 | "key": "comment",
30 | "type": "textarea",
31 | "placeholder": "Make a comment"
32 | },
33 | {
34 | "type": "submit",
35 | "style": "btn-info",
36 | "title": "OK"
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/test/data/conditional-required.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "properties": {
5 | "switch": {
6 | "title": "Spam me, please",
7 | "type": "boolean"
8 | },
9 | "email": {
10 | "title": "Email",
11 | "type": "string",
12 | "pattern": "^\\S+@\\S+$",
13 | "description": "Email will be used for evil."
14 | }
15 | },
16 | "required": ["switch"]
17 | },
18 | "form": [
19 | {
20 | "type": "help",
21 | "helpvalue": "
Schema Form does not support oneOf (yet), but you can do a workaround and simulate certain scenarios with 'condition' and 'required' (and/or 'readonly') in the form.
"
22 | },
23 | "switch",
24 | {
25 | "key": "email",
26 | "condition": "model.switch",
27 | "required": true
28 | },
29 | {
30 | "key": "email",
31 | "condition": "!model.switch"
32 | },
33 | {
34 | "type": "submit",
35 | "style": "btn-info",
36 | "title": "OK"
37 | }
38 | ]
39 | }
40 |
--------------------------------------------------------------------------------
/test/runner.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Tests
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Raphael Owino
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 |
--------------------------------------------------------------------------------
/test/data/generator-definition.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Sample Form",
3 | "type": "schema-form",
4 | "fields": [
5 | {
6 | "type": "text",
7 | "key": "first_name",
8 | "title": "First name",
9 | "open": false
10 | },
11 | {
12 | "type": "text",
13 | "key": "last_name",
14 | "title": "Last name",
15 | "open": false
16 | },
17 | {
18 | "type": "email",
19 | "key": "email",
20 | "title": "Email",
21 | "open": false,
22 | "showAdvance": true,
23 | "fieldAddonRight": " "
24 | },
25 | {
26 | "type": "date",
27 | "key": "dob",
28 | "title": "Date of Birth",
29 | "open": false
30 | },
31 | {
32 | "type": "dropdown",
33 | "key": "marital-status",
34 | "title": "Marital Status",
35 | "open": false
36 | },
37 | {
38 | "type": "date-time",
39 | "key": "check-in",
40 | "title": "Check In",
41 | "open": false
42 | },
43 | {
44 | "type": "date-time",
45 | "key": "check-out",
46 | "title": "Check Out",
47 | "open": false
48 | },
49 | {
50 | "type": "textarea",
51 | "key": "bio",
52 | "title": "Biography",
53 | "open": false
54 | }
55 | ]
56 | }
57 |
--------------------------------------------------------------------------------
/src/jsf-to-model.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 | const JSFToModel = {
3 | getModel(schema, form){
4 | let model = {};
5 |
6 | let index = _.indexOf(form, '*');
7 | if (index > -1) {
8 | form.splice(index, 1);
9 | _.each(schema.properties, (item, slug)=> {
10 | form.splice(index, 0, {key: slug});
11 | index++;
12 | });
13 | }
14 |
15 |
16 | form = _.map(form, (field)=> {
17 | "use strict";
18 | if (_.isString(field)) {
19 | field = {key: field};
20 | }
21 |
22 | field.schema = _.get(schema.properties, field.key, {});
23 |
24 | field = _.defaultsDeep(_.get(field.schema, 'x-schema-form', {}), field, field.schema);
25 |
26 | if(field.type == 'string')
27 | {
28 | field.type = 'text'
29 | if(field.enum)
30 | {
31 | field.type = 'select'
32 | }
33 | }
34 |
35 | return field;
36 | });
37 | model.fields = form;
38 | return model;
39 |
40 | },
41 |
42 | getSchema(){
43 | let definition = require('./generator-schema.js');
44 | console.log(definition.schema);
45 | return definition.schema;
46 | },
47 | getForm(){
48 | let definition = require('./generator-form.js');
49 | return definition.form;
50 | }
51 |
52 | };
53 |
54 | export default JSFToModel;
55 |
--------------------------------------------------------------------------------
/test/data/grid.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "title": "Comment",
5 | "properties": {
6 | "name": {
7 | "title": "Name",
8 | "type": "string"
9 | },
10 | "email": {
11 | "title": "Email",
12 | "type": "string",
13 | "pattern": "^\\S+@\\S+$",
14 | "description": "Email will be used for evil."
15 | },
16 | "comment": {
17 | "title": "Comment",
18 | "type": "string",
19 | "maxLength": 20,
20 | "validationMessage": "Don't be greedy!"
21 | }
22 | },
23 | "required": ["name","email","comment"]
24 | },
25 | "form": [
26 | {
27 | "type": "help",
28 | "helpvalue": "Grid it up with bootstrap
"
29 | },
30 | {
31 | "type": "section",
32 | "htmlClass": "row",
33 | "items": [
34 | {
35 | "type": "section",
36 | "htmlClass": "col-xs-6",
37 | "items": ["name"]
38 | },
39 | {
40 | "type": "section",
41 | "htmlClass": "col-xs-6",
42 | "items": ["email"]
43 | }
44 | ]
45 | },
46 | {
47 | "key": "comment",
48 | "type": "textarea",
49 | "placeholder": "Make a comment"
50 | },
51 | {
52 | "type": "submit",
53 | "style": "btn-info",
54 | "title": "OK"
55 | }
56 | ]
57 | }
58 |
--------------------------------------------------------------------------------
/test/data/complex-keys.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "title": "Complex Key Support",
5 | "properties": {
6 | "a[\"b\"].c": {
7 | "type": "string"
8 | },
9 | "simple": {
10 | "type": "object",
11 | "properties": {
12 | "prøp": {
13 | "title": "UTF8 in both dot and bracket notation",
14 | "type": "string"
15 | }
16 | }
17 | },
18 | "array-key": {
19 | "type": "array",
20 | "items": {
21 | "type": "object",
22 | "properties": {
23 | "a'rr[\"l": {
24 | "title": "Control Characters",
25 | "type": "string"
26 | },
27 | "˙∆∂∞˚¬": {
28 | "type": "string"
29 | }
30 | },
31 | "required": [
32 | "a'rr[\"l",
33 | "˙∆∂∞˚¬"
34 | ]
35 | }
36 | }
37 | }
38 | },
39 | "form": [
40 | {
41 | "type": "help",
42 | "helpvalue": "Complex keys are only supported with AngularJS version 1.3.x, see known limitations in the docs."
43 | },
44 | "['a[\"b\"].c']",
45 | {
46 | "key": "array-key",
47 | "items": [
48 | "['array-key'][]['a'rr[\"l']",
49 | {
50 | "key": "['array-key'][]['˙∆∂∞˚¬']",
51 | "title": "Unicode Characters"
52 | }
53 | ]
54 | },
55 | {
56 | "key": "simple",
57 | "items": [
58 | "simple.prøp"
59 | ]
60 | }
61 | ]
62 | }
63 |
--------------------------------------------------------------------------------
/test/data/tabarray.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "title": "Comment",
5 | "properties": {
6 | "comments": {
7 | "type": "array",
8 | "items": {
9 | "type": "object",
10 | "properties": {
11 | "name": {
12 | "title": "Name",
13 | "type": "string"
14 | },
15 | "email": {
16 | "title": "Email",
17 | "type": "string",
18 | "pattern": "^\\S+@\\S+$",
19 | "description": "Email will be used for evil."
20 | },
21 | "comment": {
22 | "title": "Comment",
23 | "type": "string",
24 | "maxLength": 20,
25 | "validationMessage": "Don't be greedy!"
26 | }
27 | },
28 | "required": ["name","email","comment"]
29 | }
30 | }
31 | }
32 | },
33 | "form": [
34 | {
35 | "type": "help",
36 | "helpvalue": "Tabbed Array Example Tab arrays can have tabs to the left, top or right.
"
37 | },
38 | {
39 | "key": "comments",
40 | "type": "tabarray",
41 | "add": "New",
42 | "remove": "Delete",
43 | "style": {
44 | "remove": "btn-danger"
45 | },
46 | "title": "{{ value.name || 'Tab '+$index }}",
47 | "items": [
48 | "comments[].name",
49 | "comments[].email",
50 | {
51 | "key": "comments[].comment",
52 | "type": "textarea"
53 | }
54 | ]
55 | },
56 | {
57 | "type": "submit",
58 | "style": "btn-default",
59 | "title": "OK"
60 | }
61 | ]
62 | }
63 |
--------------------------------------------------------------------------------
/test/data/array.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "title": "Comment",
5 | "required": ["comments"],
6 | "properties": {
7 | "comments": {
8 | "type": "array",
9 | "maxItems": 2,
10 | "items": {
11 | "type": "object",
12 | "properties": {
13 | "name": {
14 | "title": "Name",
15 | "type": "string"
16 | },
17 | "email": {
18 | "title": "Email",
19 | "type": "string",
20 | "pattern": "^\\S+@\\S+$",
21 | "description": "Email will be used for evil."
22 | },
23 | "spam": {
24 | "title": "Spam",
25 | "type": "boolean",
26 | "default": true
27 | },
28 | "comment": {
29 | "title": "Comment",
30 | "type": "string",
31 | "maxLength": 20,
32 | "validationMessage": "Don't be greedy!"
33 | }
34 | },
35 | "required": ["name","comment"]
36 | }
37 | }
38 | }
39 | },
40 | "form": [
41 | {
42 | "type": "help",
43 | "helpvalue": "Array Example Try adding a couple of forms, reorder by drag'n'drop.
"
44 | },
45 | {
46 | "key": "comments",
47 | "add": "New",
48 | "style": {
49 | "add": "btn-success"
50 | },
51 | "items": [
52 | "comments[].name",
53 | "comments[].email",
54 | {
55 | "key": "comments[].spam",
56 | "type": "checkbox",
57 | "title": "Yes I want spam.",
58 | "condition": "model.comments[arrayIndex].email"
59 | },
60 | {
61 | "key": "comments[].comment",
62 | "type": "textarea"
63 | }
64 | ]
65 | },
66 | {
67 | "type": "submit",
68 | "style": "btn-info",
69 | "title": "OK"
70 | }
71 | ]
72 | }
73 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "json-schema-form-generator",
3 | "version": "0.0.1",
4 | "description": "A tool to generate json schema forms",
5 | "main": "dist/json-schema-form-generator.js",
6 | "scripts": {
7 | "test": "gulp",
8 | "lint": "gulp lint",
9 | "test-browser": "gulp test-browser",
10 | "watch": "gulp watch",
11 | "build": "gulp build",
12 | "coverage": "gulp coverage"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "https://github.com/json-schema-form/json-schema-form-generator-es6.git"
17 | },
18 | "keywords": [],
19 | "author": "Raphael Owino ",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/json-schema-form/json-schema-form-generator-es6/issues"
23 | },
24 | "homepage": "https://github.com/json-schema-form/json-schema-form-generator-es6",
25 | "devDependencies": {
26 | "babel-core": "^6.3.26",
27 | "babel-loader": "^6.2.0",
28 | "babel-polyfill": "^6.3.14",
29 | "babel-preset-es2015": "^6.3.13",
30 | "babel-register": "^6.3.13",
31 | "chai": "^3.4.1",
32 | "del": "^2.2.0",
33 | "glob": "^7.0.3",
34 | "gulp": "^3.9.0",
35 | "gulp-eslint": "^2.0.0",
36 | "gulp-filter": "^4.0.0",
37 | "gulp-istanbul": "^0.10.3",
38 | "gulp-livereload": "^3.8.1",
39 | "gulp-load-plugins": "^1.1.0",
40 | "gulp-mocha": "^2.2.0",
41 | "gulp-plumber": "^1.0.1",
42 | "gulp-rename": "^1.2.2",
43 | "gulp-sourcemaps": "^1.6.0",
44 | "gulp-uglify": "^1.5.1",
45 | "isparta": "^4.0.0",
46 | "json-loader": "^0.5.3",
47 | "mocha": "^2.3.4",
48 | "sinon": "^1.17.2",
49 | "sinon-chai": "^2.8.0",
50 | "vinyl-source-stream": "^1.1.0",
51 | "webpack": "^1.12.9",
52 | "webpack-stream": "^3.1.0"
53 | },
54 | "babelBoilerplateOptions": {
55 | "entryFileName": "json-schema-form-generator.js",
56 | "mainVarName": "jsonSchemaFormGenerator"
57 | },
58 | "dependencies": {
59 | "lodash": "^4.13.1"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/test/data/titlemaps.json:
--------------------------------------------------------------------------------
1 | {
2 | "model": {
3 | "select": "a",
4 | "array": ["b"]
5 | },
6 | "schema": {
7 | "type": "object",
8 | "properties": {
9 | "select": {
10 | "title": "Select without titleMap",
11 | "type": "string",
12 | "enum": ["a","b","c"]
13 | },
14 | "select2": {
15 | "title": "Select with titleMap (old style)",
16 | "type": "string",
17 | "enum": ["a","b","c"]
18 | },
19 | "noenum": { "type": "string", "title": "No enum, but forms says it's a select" },
20 | "array": {
21 | "title": "Array with enum defaults to 'checkboxes'",
22 | "type": "array",
23 | "items": {
24 | "type": "string",
25 | "enum": ["a","b","c"]
26 | }
27 | },
28 | "array2": {
29 | "title": "Array with titleMap",
30 | "type": "array",
31 | "default": ["b","c"],
32 | "items": {
33 | "type": "string",
34 | "enum": ["a","b","c"]
35 | }
36 | },
37 | "radios": {
38 | "title": "Basic radio button example",
39 | "type": "string",
40 | "enum": ["a","b","c"]
41 | },
42 | "radiobuttons": {
43 | "title": "Radio buttons used to switch a boolean",
44 | "type": "boolean",
45 | "default": false
46 | }
47 | }
48 | },
49 | "form": [
50 | "select",
51 | {
52 | "key": "select2",
53 | "type": "select",
54 | "titleMap": {
55 | "a": "A",
56 | "b": "B",
57 | "c": "C"
58 | }
59 | },
60 | {
61 | "key": "noenum",
62 | "type": "select",
63 | "titleMap": [
64 | { "value":"a", "name": "A" },
65 | { "value":"b", "name":"B" },
66 | { "value":"c", "name":"C" }
67 | ]
68 | },
69 | "array",
70 | {
71 | "key": "array2",
72 | "type": "checkboxes",
73 | "titleMap": [
74 | { "value":"a", "name": "A" },
75 | { "value":"b", "name":"B" },
76 | { "value":"c", "name":"C" }
77 | ]
78 | },
79 | {
80 | "key": "radios",
81 | "type": "radios",
82 | "titleMap": [
83 | { "value":"c", "name": "C" },
84 | { "value":"b", "name":"B" },
85 | { "value":"a", "name":"A" }
86 | ]
87 | },
88 | {
89 | "key":"radiobuttons",
90 | "type": "radiobuttons",
91 | "titleMap": [
92 | {"value": false, "name": "No way"},
93 | {"value": true, "name": "OK"}
94 | ]
95 | }
96 | ]
97 | }
98 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # json-schema-form-generator
2 |
3 | A tool to generate json schema forms
4 |
5 | [](https://travis-ci.org/json-schema-form/json-schema-form-generator-es6)
6 | [](https://codeclimate.com/github/json-schema-form/json-schema-form-generator-es6)
7 | [](https://codeclimate.com/github/json-schema-form/json-schema-form-generator-es6)
8 | [](https://david-dm.org/json-schema-form/json-schema-form-generator-es6)
9 | [](https://david-dm.org/json-schema-form/json-schema-form-generator-es6#info=devDependencies)
10 |
11 | ## Objective
12 |
13 | The goal for this libary is to provide a generator that will allow users of json-schema-form to generate form definitions through various means. This is the base package and will provide translations of simple data into json-schema-form syntax. It will also import json-schema-form definitions and return it in a format that can be used with the GUI.
14 |
15 | ## Installation
16 |
17 | npm install json-schema-generator
18 |
19 | ## Usage
20 |
21 | The generator accepts standard json schema form schema and form as input and will output json schema form schema, form and model that use jsf to edit the form definition.
22 |
23 |
24 | var jsonSchemaFormGenerator = require('json-schema-generator').default;
25 | generator = jsonSchemaFormGenerator.getFormBuilder(schema, form);
26 |
27 | In html:
28 |
29 |
30 |
31 | To get the form definitions, simply call ```getDefinitions``` with the model as parameter
32 |
33 | var output = jsonSchemaFormGenerator.getDefinitions(generator.model);
34 |
35 |
36 | In html, you can then show the form like any standard json schema form:
37 |
38 |
39 |
40 |
41 | NB: The examples use the angular-builder, however the generator is framework agnostic and uses plain javascript. Adapters for different frameworks are required for drop-in usage.
42 |
43 |
44 | ## Todo
45 |
46 | - Support the full json schema form definition
47 | - Enum and Titlemaps
48 | - Fields without keys
49 | - All Json Schema Draft 4 keywords
50 | - Fields with items
51 | - Unit tests
52 | - Framework adapters
53 | - Angular Directive
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/generator-form.js:
--------------------------------------------------------------------------------
1 | module.exports.form = [
2 | {
3 | key: 'fields',
4 | type: 'array',
5 | title: 'Form Fields',
6 | add: 'Add a new Field',
7 | remove: 'Remove Field',
8 | startEmpty: true,
9 | items: [
10 | {
11 | key: 'fields[].title',
12 | htmlClass: 'hide-label',
13 | placeholder: 'Title'
14 | },
15 | {
16 | type: 'section',
17 | htmlClass: 'row',
18 | items: [
19 | {
20 | key: 'fields[].type',
21 | placeholder: 'Type',
22 | notitle: true,
23 | htmlClass: 'col-sm-6 hide-label',
24 | },
25 | {
26 | key: 'fields[].key',
27 | //type: 'section',
28 | placeholder: 'Key (Unique Identifier)',
29 | notitle: true,
30 | htmlClass: 'col-sm-6 hide-label',
31 | }
32 | ]
33 | },
34 | {
35 | key: 'fields[].open',
36 | notitle: true,
37 | type: 'hidden'
38 | },
39 | {
40 | key: 'fields[].description',
41 | type: 'textarea',
42 | placeholder: 'Description',
43 | notitle: true,
44 | },
45 | {
46 | type: 'section',
47 | htmlClass: 'row',
48 | items: [
49 | {
50 | key: 'fields[].notitle',
51 | htmlClass: 'col-sm-6'
52 | },
53 | {
54 | key: 'fields[].showAdvanced',
55 | htmlClass: 'col-sm-6'
56 | },
57 | ]
58 | },
59 | {
60 | condition: 'model.fields[arrayIndex].showAdvanced',
61 | type: 'help',
62 | helpvalue: ' '
63 | },
64 | {
65 | type: 'section',
66 | htmlClass: 'row',
67 | items: [
68 | {
69 | type: 'section',
70 | htmlClass: 'col-md-4',
71 | items: [
72 | {
73 | condition: 'model.fields[arrayIndex].showAdvanced',
74 | key: 'fields[].disableSuccessState'
75 | }
76 | ]
77 | },
78 | {
79 | type: 'section',
80 | htmlClass: 'col-md-4',
81 | items: [
82 | {
83 | condition: 'model.fields[arrayIndex].showAdvanced',
84 | key: 'fields[].disableErrorState'
85 | }
86 | ]
87 | },
88 | {
89 | type: 'section',
90 | htmlClass: 'col-md-4',
91 | items: [
92 | {
93 | condition: 'model.fields[arrayIndex].showAdvanced',
94 | key: 'fields[].readonly'
95 | },
96 | ]
97 | }
98 | ]
99 | },
100 | {
101 | condition: 'model.fields[arrayIndex].showAdvanced',
102 | type: 'help',
103 | helpvalue: ' '
104 | },
105 | {
106 | condition: 'model.fields[arrayIndex].showAdvanced',
107 | key: 'fields[].validationMessage',
108 | type: 'textarea'
109 | },
110 | {
111 | condition: 'model.fields[arrayIndex].showAdvanced',
112 | key: 'fields[].onChange',
113 | type: 'textarea'
114 | },
115 | {
116 | condition: 'model.fields[arrayIndex].showAdvanced',
117 | key: 'fields[].feedback'
118 | },
119 | {
120 | condition: 'model.fields[arrayIndex].showAdvanced',
121 | key: 'fields[].placeholder'
122 | },
123 | {
124 | condition: 'model.fields[arrayIndex].showAdvanced',
125 | key: 'fields[].ngModelOptions',
126 | type: 'textarea'
127 | },
128 | {
129 | condition: 'model.fields[arrayIndex].showAdvanced',
130 | key: 'fields[].htmlClass'
131 | },
132 | {
133 | condition: 'model.fields[arrayIndex].showAdvanced',
134 | key: 'fields[].destroyStrategy'
135 | },
136 | {
137 | condition: 'model.fields[arrayIndex].showAdvanced',
138 | key: 'fields[].copyValueTo'
139 | },
140 | {
141 | condition: 'model.fields[arrayIndex].showAdvanced',
142 | key: 'fields[].fieldHtmlClass'
143 | },
144 | {
145 | condition: 'model.fields[arrayIndex].showAdvanced',
146 | key: 'fields[].labelHtmlClass'
147 | },
148 | {
149 | condition: 'model.fields[arrayIndex].showAdvanced',
150 | key: 'fields[].condition'
151 | },
152 | {
153 | condition: 'model.fields[arrayIndex].showAdvanced',
154 | 'key': 'fields[].fieldAddonLeft'
155 | },
156 | {
157 | condition: 'model.fields[arrayIndex].showAdvanced',
158 | key: 'fields[].fieldAddonRight'
159 | }
160 |
161 | ]
162 | }
163 | ];
164 |
--------------------------------------------------------------------------------
/src/form-definitions-generator.js:
--------------------------------------------------------------------------------
1 | var _ = require('lodash');
2 |
3 | const formDefinitionsGenerator = {
4 | generateField(field, definitions){
5 | "use strict";
6 | let morpher = _.camelCase('_generate_' + field.type.replace('-', '_') + '_field');
7 |
8 | definitions = this.generateStandardFormAttributes(field, definitions);
9 | definitions = this.generateStandardSchemaAttributes(field, definitions);
10 |
11 | if (_.isFunction(this[morpher])) {
12 | definitions = this[morpher](field, definitions);
13 | }
14 |
15 | return definitions;
16 | },
17 | generateStandardFormAttributes(field, definitions) {
18 |
19 | let form, formIndex, formProps = [
20 | 'key',
21 | 'condition',
22 | 'onChange',
23 | 'notitle',
24 | 'showAdvanced',
25 | 'validationMessage',
26 | 'onChange',
27 | 'ngModelOptions',
28 | 'condition',
29 | 'fieldAddonLeft',
30 | 'fieldAddonRight',
31 | 'showAdvanced',
32 | 'validationMessage',
33 | 'onChange',
34 | 'feedback',
35 | 'disableSuccessState',
36 | 'disableErrorState',
37 | 'placeholder',
38 | 'ngModelOptions',
39 | 'readonly',
40 | 'htmlClass',
41 | 'destroyStrategy',
42 | 'copyValueTo',
43 | 'fieldHtmlClass',
44 | 'labelHtmlClass',
45 | 'items'
46 | ];
47 | form = _.pick(field, formProps);
48 | formIndex = _.findIndex(definitions, {key: field.key});
49 | if (!form.key) {
50 | form.type = field.type;
51 | form.title = field.title;
52 | formIndex = _.findIndex(definitions, {key: undefined, type: field.type, title: field.title});
53 | }
54 | if (formIndex > -1) {
55 | definitions.form[formIndex] = form;
56 | } else {
57 | definitions.form.push(form);
58 | }
59 | return definitions;
60 | },
61 | generateStandardSchemaAttributes(field, definitions) {
62 |
63 | let schemaProps = [
64 | 'type',
65 | 'format',
66 | 'description',
67 | 'title',
68 | 'minLength',
69 | 'maxLength'
70 | ];
71 | if (field.key) {
72 | definitions.schema.properties[field.key] = _.pick(field, schemaProps);
73 | }
74 | return definitions;
75 | },
76 | updateForm(definitions, key, attr, value) {
77 | let index = _.findKey(definitions.form, 'key', key);
78 | definitions.form[index][attr] = value;
79 | return definitions;
80 | },
81 | generateTextField(field, definitions){
82 | definitions.schema.properties[field.key]['type'] = 'string';
83 | return definitions;
84 | },
85 | generateTextareaField(field, definitions){
86 | definitions.schema.properties[field.key]['type'] = 'string';
87 | definitions = this.updateForm(definitions, field.key, 'type', 'textarea');
88 | return definitions;
89 | },
90 | generateEmailField(field, definitions){
91 | definitions.schema.properties[field.key]['type'] = 'string';
92 | definitions.schema.properties[field.key]['format'] = 'email';
93 | return definitions;
94 | },
95 | generateSelectField(field, definitions){
96 | definitions.schema.properties[field.key]['type'] = 'string';
97 | definitions.schema.properties[field.key]['enum'] = field.enum;
98 | return definitions;
99 | },
100 | generateCheckboxField(field, definitions){
101 | definitions.schema.properties[field.key]['type'] = 'string';
102 | definitions.schema.properties[field.key]['enum'] = field.enum;
103 | return definitions;
104 | },
105 | generateDateField(field, definitions){
106 | definitions.schema.properties[field.key]['type'] = 'string';
107 | definitions.schema.properties[field.key]['format'] = 'date';
108 | return definitions;
109 | },
110 | generateTimeField(field, definitions){
111 | definitions.schema.properties[field.key]['type'] = 'string';
112 | definitions.schema.properties[field.key]['format'] = 'time';
113 | return definitions;
114 | },
115 | generateDateTimeField(field, definitions){
116 | definitions.schema.properties[field.key]['type'] = 'string';
117 | definitions.schema.properties[field.key]['format'] = 'date-time';
118 | return definitions;
119 | },
120 | generateFieldsetField(field, definitions){
121 | if (field.key) {
122 | delete definitions.schema.properties[field.key]
123 | }
124 | return definitions;
125 | },
126 | generateSectionField(field, definitions){
127 | return definitions;
128 | },
129 | generateActionsField(field, definitions){
130 | return definitions;
131 | },
132 | generateNumberField(field, definitions){
133 | return definitions;
134 | },
135 | generatePasswordField(field, definitions){
136 | return definitions;
137 | },
138 | generateCheckboxField(field, definitions){
139 | return definitions;
140 | },
141 | generateCheckboxesField(field, definitions){
142 | return definitions;
143 | },
144 | generateSubmitField(field, definitions){
145 | return definitions;
146 | },
147 | generateButtonField(field, definitions){
148 | return definitions;
149 | },
150 | generateRadiosField(field, definitions){
151 | return definitions;
152 | },
153 | generateRadiosInlineField(field, definitions){
154 | return definitions;
155 | },
156 | generateRadioButtonsField(field, definitions){
157 | return definitions;
158 | },
159 | generateHelpField(field, definitions){
160 | return definitions;
161 | },
162 | generateTemplateField(field, definitions){
163 | return definitions;
164 | },
165 | generateTabField(field, definitions){
166 | return definitions;
167 | },
168 | generateArrayField(field, definitions){
169 | return definitions;
170 | },
171 | generateTabArrayField(field, definitions){
172 | return definitions;
173 | },
174 | }
175 |
176 | export default formDefinitionsGenerator;
--------------------------------------------------------------------------------
/src/generator-schema.js:
--------------------------------------------------------------------------------
1 | module.exports.schema = {
2 | type: 'object',
3 | title: 'Comment',
4 | properties: {
5 | name: {
6 | type: 'string'
7 | },
8 | fields: {
9 | type: 'array',
10 | title: 'Fields',
11 | items: {
12 | type: 'object',
13 | properties: {
14 | open: {
15 | type: 'boolean',
16 | default: true
17 | },
18 | type: {
19 | title: 'Type',
20 | type: 'string',
21 | enum: [
22 | 'actions',
23 | 'array',
24 | 'boolean',
25 | 'button',
26 | 'checkbox',
27 | 'checkboxes',
28 | 'date',
29 | 'date-time',
30 | 'email',
31 | 'fieldset',
32 | 'help',
33 | 'number',
34 | 'password',
35 | 'radiobuttons',
36 | 'radios',
37 | 'radios-inline',
38 | 'reset',
39 | 'section',
40 | 'select',
41 | 'submit',
42 | 'submit',
43 | 'tab',
44 | 'tabarray',
45 | 'template',
46 | 'text',
47 | 'textarea',
48 | 'time'
49 | ]
50 | },
51 | key: {
52 | title: 'Key',
53 | type: 'string',
54 | description: 'Unique identifier'
55 | },
56 | title: {
57 | condition: 'model.notitle',
58 | title: 'Title',
59 | type: 'string'
60 | },
61 | notitle: {
62 | type: 'boolean',
63 | title: 'Don\'t show title'
64 | },
65 | description: {
66 | title: 'Description',
67 | type: 'string'
68 | },
69 | validationMessage: {
70 | title: 'Validation Message',
71 | description: 'A custom validation error message. It can be a string, an object with error codes as key and messages as values or a custom message function',
72 | type: 'string'
73 | },
74 | onChange: {
75 | title: 'onChange',
76 | description: 'onChange event handler, expression or function. For expression, modelValue and form are both available. For a function, they will be passed as parameters in that order',
77 | type: 'string'
78 | },
79 | feedback: {
80 | title: 'Feedback Icon',
81 | description: 'Inline feedback icons. To turn off just set feedback to false. If set to a string that string is evaluated by a ngClass in the decorators scope. If not set att all the default value is { "glyphicon": true, "glyphicon-ok": hasSuccess(), "glyphicon-remove": hasError() }',
82 | type: 'string'
83 | },
84 | disableSuccessState: {
85 | type: 'boolean',
86 | title: 'Disable Success State',
87 | default: false
88 | },
89 | disableErrorState: {
90 | type: 'boolean',
91 | title: 'Disable Error State',
92 | default: false
93 | },
94 | placeholder: {
95 | title: 'Placeholder',
96 | description: 'Placeholder on inputs and textarea',
97 | type: 'string'
98 | },
99 | ngModelOptions: {
100 | title: 'ng-Model Options',
101 | description: 'Passed along to ng-model-options',
102 | type: 'string'
103 | },
104 | readonly: {
105 | type: 'boolean',
106 | title: 'Readonly',
107 | default: false
108 | },
109 | htmlClass: {
110 | title: 'Class',
111 | description: 'CSS Class(es) to be added to the container div e.g. : \'street foobar\'',
112 | type: 'string'
113 | },
114 | destroyStrategy: {
115 | title: 'Destroy Strategy',
116 | description: 'One of null, empty , remove, or retain. Changes model on $destroy event. default is remove.',
117 | type: 'string'
118 | },
119 | copyValueTo: {
120 | title: 'Copy Value To',
121 | description: 'Copy values to these schema keys e.g [\'address.street\']. The receiving fields can be shown, but the intent for them is to be hidden.',
122 | type: 'string'
123 | },
124 | fieldHtmlClass: {
125 | title: 'Field Class',
126 | description: 'CSS Class(es) to be added to field input (or similar)',
127 | type: 'string'
128 | },
129 | labelHtmlClass: {
130 | title: 'Label Class',
131 | description: 'CSS Class(es) to be added to the label of the field (or similar)',
132 | type: 'string'
133 | },
134 | condition: {
135 | title: 'Condition',
136 | description: 'Show or hide field depending on an angular expression e.g \'model.age < 18\'. The expression has access to model, modelValue, arrayIndex. The condition need not reference a model value it could be anything on scope.',
137 | type: 'string'
138 | },
139 | fieldAddonLeft: {
140 | title: 'Field Addon - Left',
141 | description: 'Add html code to left of input field. For reference check bootstrap input groups .',
142 | type: 'string'
143 | },
144 | fieldAddonRight: {
145 | title: 'Field Addon - Right',
146 | description: 'Add html code to right of input field. For reference check bootstrap input groups .',
147 | type: 'string'
148 | },
149 | onClick: {
150 | title: 'onClick',
151 | description: 'Function to call when a button/submit is clicked',
152 | type: 'string'
153 | },
154 | showAdvanced: {
155 | title: 'Show advance options',
156 | type: 'boolean'
157 | }
158 | },
159 | required: [
160 | 'key'
161 | ]
162 | }
163 | }
164 | },
165 | required: ['name']
166 | };
167 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp');
2 | const loadPlugins = require('gulp-load-plugins');
3 | const del = require('del');
4 | const glob = require('glob');
5 | const path = require('path');
6 | const isparta = require('isparta');
7 | const webpack = require('webpack');
8 | const webpackStream = require('webpack-stream');
9 | const source = require('vinyl-source-stream');
10 |
11 | const Instrumenter = isparta.Instrumenter;
12 | const mochaGlobals = require('./test/setup/.globals');
13 | const manifest = require('./package.json');
14 |
15 | // Load all of our Gulp plugins
16 | const $ = loadPlugins();
17 |
18 | // Gather the library data from `package.json`
19 | const config = manifest.babelBoilerplateOptions;
20 | const mainFile = manifest.main;
21 | const destinationFolder = path.dirname(mainFile);
22 | const exportFileName = path.basename(mainFile, path.extname(mainFile));
23 |
24 | function cleanDist(done) {
25 | del([destinationFolder]).then(() => done());
26 | }
27 |
28 | function cleanTmp(done) {
29 | del(['tmp']).then(() => done());
30 | }
31 |
32 | // Lint a set of files
33 | function lint(files) {
34 | return gulp.src(files)
35 | .pipe($.eslint())
36 | .pipe($.eslint.format())
37 | .pipe($.eslint.failAfterError());
38 | }
39 |
40 | function lintSrc() {
41 | return lint('src/**/*.js');
42 | }
43 |
44 | function lintTest() {
45 | return lint('test/**/*.js');
46 | }
47 |
48 | function lintGulpfile() {
49 | return lint('gulpfile.js');
50 | }
51 |
52 | function build() {
53 | return gulp.src(path.join('src', config.entryFileName))
54 | .pipe(webpackStream({
55 | output: {
56 | filename: exportFileName + '.js',
57 | libraryTarget: 'umd',
58 | library: config.mainVarName
59 | },
60 | // Add your own externals here. For instance,
61 | // {
62 | // jquery: true
63 | // }
64 | // would externalize the `jquery` module.
65 | externals: {},
66 | module: {
67 | loaders: [
68 | { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' }
69 | ]
70 | },
71 | devtool: 'source-map'
72 | }))
73 | .pipe(gulp.dest(destinationFolder))
74 | .pipe($.filter(['**', '!**/*.js.map']))
75 | .pipe($.rename(exportFileName + '.min.js'))
76 | .pipe($.sourcemaps.init({ loadMaps: true }))
77 | .pipe($.uglify())
78 | .pipe($.sourcemaps.write('./'))
79 | .pipe(gulp.dest(destinationFolder));
80 | }
81 |
82 | function _mocha() {
83 | return gulp.src(['test/setup/node.js', 'test/unit/**/*.js'], {read: false})
84 | .pipe($.mocha({
85 | reporter: 'dot',
86 | globals: Object.keys(mochaGlobals.globals),
87 | ignoreLeaks: false
88 | }));
89 | }
90 |
91 | function _registerBabel() {
92 | require('babel-register');
93 | }
94 |
95 | function test() {
96 | _registerBabel();
97 | return _mocha();
98 | }
99 |
100 | function coverage(done) {
101 | _registerBabel();
102 | gulp.src(['src/**/*.js'])
103 | .pipe($.istanbul({ instrumenter: Instrumenter }))
104 | .pipe($.istanbul.hookRequire())
105 | .on('finish', () => {
106 | return test()
107 | .pipe($.istanbul.writeReports())
108 | .on('end', done);
109 | });
110 | }
111 |
112 | const watchFiles = ['src/**/*', 'test/**/*', 'package.json', '**/.eslintrc', '.jscsrc'];
113 |
114 | // Run the headless unit tests as you make changes.
115 | function watch() {
116 | gulp.watch(watchFiles, ['test']);
117 | }
118 | // Run the headless unit tests as you make changes.
119 | function watchAndBuild() {
120 | gulp.watch(watchFiles, ['build']);
121 | }
122 |
123 | function testBrowser() {
124 | // Our testing bundle is made up of our unit tests, which
125 | // should individually load up pieces of our application.
126 | // We also include the browser setup file.
127 | const testFiles = glob.sync('./test/unit/**/*.js');
128 | const allFiles = ['./test/setup/browser.js'].concat(testFiles);
129 |
130 | // Lets us differentiate between the first build and subsequent builds
131 | var firstBuild = true;
132 |
133 | // This empty stream might seem like a hack, but we need to specify all of our files through
134 | // the `entry` option of webpack. Otherwise, it ignores whatever file(s) are placed in here.
135 | return gulp.src('')
136 | .pipe($.plumber())
137 | .pipe(webpackStream({
138 | watch: true,
139 | entry: allFiles,
140 | output: {
141 | filename: '__spec-build.js'
142 | },
143 | // Externals isn't necessary here since these are for tests.
144 | module: {
145 | loaders: [
146 | // This is what allows us to author in future JavaScript
147 | { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' },
148 | // This allows the test setup scripts to load `package.json`
149 | { test: /\.json$/, exclude: /node_modules/, loader: 'json-loader' }
150 | ]
151 | },
152 | plugins: [
153 | // By default, webpack does `n=>n` compilation with entry files. This concatenates
154 | // them into a single chunk.
155 | new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })
156 | ],
157 | devtool: 'inline-source-map'
158 | }, null, function() {
159 | if (firstBuild) {
160 | $.livereload.listen({port: 35729, host: 'localhost', start: true});
161 | var watcher = gulp.watch(watchFiles, ['lint']);
162 | } else {
163 | $.livereload.reload('./tmp/__spec-build.js');
164 | }
165 | firstBuild = false;
166 | }))
167 | .pipe(gulp.dest('./tmp'));
168 | }
169 |
170 | // Remove the built files
171 | gulp.task('clean', cleanDist);
172 |
173 | // Remove our temporary files
174 | gulp.task('clean-tmp', cleanTmp);
175 |
176 | // Lint our source code
177 | gulp.task('lint-src', lintSrc);
178 |
179 | // Lint our test code
180 | gulp.task('lint-test', lintTest);
181 |
182 | // Lint this file
183 | gulp.task('lint-gulpfile', lintGulpfile);
184 |
185 | // Lint everything
186 | gulp.task('lint', ['lint-src', 'lint-test', 'lint-gulpfile']);
187 |
188 | // Build two versions of the library
189 | gulp.task('build', ['lint', 'clean'], build);
190 |
191 | // Lint and run our tests
192 | gulp.task('test', ['lint'], test);
193 |
194 | // Set up coverage and run tests
195 | gulp.task('coverage', ['lint'], coverage);
196 |
197 | // Set up a livereload environment for our spec runner `test/runner.html`
198 | gulp.task('test-browser', ['lint', 'clean-tmp'], testBrowser);
199 |
200 | // Run the headless unit tests as you make changes.
201 | gulp.task('watch', watch);
202 |
203 | // Build new dist as you make changes.
204 | gulp.task('watch-build', watchAndBuild);
205 |
206 | // An alias of test
207 | gulp.task('default', ['test']);
208 |
--------------------------------------------------------------------------------
/test/data/sink.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema": {
3 | "type": "object",
4 | "required": [
5 | "name",
6 | "shoesizeLeft"
7 | ],
8 | "properties": {
9 | "name": {
10 | "title": "Name",
11 | "description": "Gimme yea name lad",
12 | "type": "string",
13 | "pattern": "^[^/]*$",
14 | "minLength": 2
15 | },
16 | "invitation": {
17 | "type": "string",
18 | "format": "html",
19 | "title": "Invitation Design",
20 | "description": "Design the invitation in full technicolor HTML"
21 | },
22 | "favorite": {
23 | "title": "Favorite",
24 | "type": "string",
25 | "enum": [
26 | "undefined",
27 | "null",
28 | "NaN"
29 | ]
30 | },
31 | "shoesizeLeft": {
32 | "title": "Shoe size (left)",
33 | "default": 42,
34 | "type": "number"
35 | },
36 | "shoesizeRight": {
37 | "title": "Shoe size (right)",
38 | "default": 42,
39 | "type": "number"
40 | },
41 | "attributes": {
42 | "type": "object",
43 | "title": "Attributes",
44 | "required": [
45 | "eyecolor"
46 | ],
47 | "properties": {
48 | "eyecolor": {
49 | "type": "string",
50 | "format": "color",
51 | "title": "Eye color",
52 | "default": "pink"
53 | },
54 | "haircolor": {
55 | "type": "string",
56 | "title": "Hair color"
57 | },
58 | "shoulders": {
59 | "type": "object",
60 | "title": "Shoulders",
61 | "properties": {
62 | "left": {
63 | "type": "string",
64 | "title": "Left"
65 | },
66 | "right": {
67 | "type": "string",
68 | "title": "Right"
69 | }
70 | }
71 | }
72 | }
73 | },
74 | "things": {
75 | "type": "array",
76 | "title": "I like...",
77 | "items": {
78 | "type": "string",
79 | "enum": [
80 | "clowns",
81 | "compiling",
82 | "sleeping"
83 | ]
84 | }
85 | },
86 | "dislike": {
87 | "type": "array",
88 | "title": "I dislike...",
89 | "items": {
90 | "type": "string",
91 | "title": "I hate"
92 | }
93 | },
94 | "soul": {
95 | "title": "Terms Of Service",
96 | "description": "I agree to sell my undying soul ",
97 | "type": "boolean",
98 | "default": true
99 | },
100 | "soulserial": {
101 | "title": "Soul Serial No",
102 | "type": "string"
103 | },
104 | "date": {
105 | "title": "Date of party",
106 | "type": "string",
107 | "format": "date"
108 | },
109 | "radio": {
110 | "title": "Radio type",
111 | "type": "string",
112 | "enum": [
113 | "Transistor",
114 | "Tube"
115 | ]
116 | },
117 | "radio2": {
118 | "title": "My Second Radio",
119 | "type": "string",
120 | "enum": [
121 | "Transistor",
122 | "Tube"
123 | ]
124 | },
125 | "radiobuttons": {
126 | "type": "string",
127 | "enum": [
128 | "Select me!",
129 | "No me!"
130 | ]
131 | }
132 | }
133 | },
134 | "form": [
135 | {
136 | "type": "fieldset",
137 | "title": "Stuff",
138 | "items": [
139 | {
140 | "type": "tabs",
141 | "tabs": [
142 | {
143 | "title": "Simple stuff",
144 | "items": [
145 | {
146 | "key": "name",
147 | "placeholder": "Check the console",
148 | "onChange": "log(modelValue)",
149 | "feedback": "{'glyphicon': true, 'glyphicon-ok': hasSuccess(), 'glyphicon-star': !hasSuccess() }"
150 | },
151 | {
152 | "key": "favorite",
153 | "feedback": false
154 | }
155 | ]
156 | },
157 | {
158 | "title": "More stuff",
159 | "items": [
160 | "attributes.eyecolor",
161 | "attributes.haircolor",
162 | {
163 | "key": "attributes.shoulders.left",
164 | "title": "Left shoulder",
165 | "description": "This value is copied to attributes.shoulders.right in the model",
166 | "copyValueTo": ["attributes.shoulders.right"]
167 | },
168 | {
169 | "key": "shoesizeLeft",
170 | "feedback": false,
171 | "copyValueTo":["shoesizeRight"]
172 | },
173 | {
174 | "key": "shoesizeRight"
175 | },
176 | {
177 | "key": "invitation",
178 | "tinymceOptions": {
179 | "toolbar": [
180 | "undo redo| styleselect | bold italic | link image",
181 | "alignleft aligncenter alignright"
182 | ]
183 | }
184 | },
185 | "things",
186 | "dislike"
187 | ]
188 | }
189 | ]
190 | }
191 | ]
192 | },
193 | {
194 | "type": "help",
195 | "helpvalue": " "
196 | },
197 | "soul",
198 | {
199 | "type": "conditional",
200 | "condition": "modelData.soul",
201 | "items": [
202 | {
203 | "key": "soulserial",
204 | "placeholder": "ex. 666"
205 | }
206 | ]
207 | },
208 | {
209 | "key": "date",
210 | "minDate": "2014-06-20"
211 | },
212 | {
213 | "key": "radio",
214 | "type": "radios",
215 | "titleMap": [
216 | {
217 | "value": "Transistor",
218 | "name": "Transistor Not the tube kind."
219 | },
220 | {
221 | "value": "Tube",
222 | "name": "Tube The tube kind."
223 | }
224 | ]
225 | },
226 | {
227 | "key": "radio2",
228 | "type": "radios-inline",
229 | "titleMap": [
230 | {
231 | "value": "Transistor",
232 | "name": "Transistor Not the tube kind."
233 | },
234 | {
235 | "value": "Tube",
236 | "name": "Tube The tube kind."
237 | }
238 | ]
239 | },
240 | {
241 | "key": "radiobuttons",
242 | "style": {
243 | "selected": "btn-success",
244 | "unselected": "btn-default"
245 | },
246 | "type": "radiobuttons",
247 | "notitle": true
248 | },
249 | {
250 | "type": "actions",
251 | "items": [
252 | {
253 | "type": "submit",
254 | "style": "btn-info",
255 | "title": "Do It!"
256 | },
257 | {
258 | "type": "button",
259 | "style": "btn-danger",
260 | "title": "Noooooooooooo",
261 | "onClick": "sayNo()"
262 | }
263 | ]
264 | }
265 | ]
266 | }
267 |
--------------------------------------------------------------------------------
/dist/json-schema-form-generator.min.js:
--------------------------------------------------------------------------------
1 | !function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports.jsonSchemaFormGenerator=n():t.jsonSchemaFormGenerator=n()}(this,function(){return function(t){function n(r){if(e[r])return e[r].exports;var i=e[r]={exports:{},id:r,loaded:!1};return t[r].call(i.exports,i,i.exports,n),i.loaded=!0,i.exports}var e={};return n.m=t,n.c=e,n.p="",n(0)}([function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=(e(1),e(3)["default"]),i=e(6)["default"],u={getFormBuilder:function(t,n){var e=void 0,i=void 0,u=void 0;return e=r.getSchema(),i=r.getForm(),u=r.getModel(t,n),{schema:e,form:i,model:u}},getDefinitions:function(t){return i.getFormDefinitions(t)}};n["default"]=u},function(t,n,e){var r;(function(t,i){(function(){function u(t,n){return t.set(n[0],n[1]),t}function o(t,n){return t.add(n),t}function a(t,n,e){var r=e.length;switch(r){case 0:return t.call(n);case 1:return t.call(n,e[0]);case 2:return t.call(n,e[0],e[1]);case 3:return t.call(n,e[0],e[1],e[2])}return t.apply(n,e)}function c(t,n,e,r){for(var i=-1,u=t?t.length:0;++i-1}function d(t,n,e){for(var r=-1,i=t?t.length:0;++r-1;);return e}function W(t,n){for(var e=t.length;e--&&x(n,t[e],0)>-1;);return e}function M(t){return t&&t.Object===Object?t:null}function B(t,n){for(var e=t.length,r=0;e--;)t[e]===n&&r++;return r}function T(t){return Ie[t]}function D(t){return Fe[t]}function $(t){return"\\"+Ee[t]}function z(t,n){return null==t?Q:t[n]}function P(t,n,e){for(var r=t.length,i=n+(e?1:-1);e?i--:++i-1}function Gn(t,n){var e=this.__data__,r=de(e,t);return r<0?e.push([t,n]):e[r][1]=n,this}function Jn(t){var n=-1,e=t?t.length:0;for(this.clear();++n=n?t:n)),t}function we(t,n,e,r,i,u,o){var a;if(r&&(a=u?r(t,i,u,o):r(t)),a!==Q)return a;if(!ga(t))return t;var c=gs(t);if(c){if(a=Ni(t),!n)return ei(t,a)}else{var l=Pi(t),s=l==Mt||l==Bt;if(ys(t))return Nr(t,n);if(l==$t||l==Ft||s&&!u){if(U(t))return u?t:{};if(a=Vi(s?{}:t),!n)return ii(t,_e(a,t))}else{if(!Se[l])return u?t:{};a=Ki(t,l,we,n)}}o||(o=new ue);var p=o.get(t);if(p)return p;if(o.set(t,a),!c)var h=e?Ri(t):rc(t);return f(h||t,function(i,u){h&&(u=i,i=t[u]),he(a,u,we(i,n,e,r,u,t,o))}),a}function Ie(t){var n=rc(t),e=n.length;return function(r){if(null==r)return!e;for(var i=e;i--;){var u=n[i],o=t[u],a=r[u];if(a===Q&&!(u in Object(r))||!o(a))return!1}return!0}}function Fe(t){return ga(t)?qf(t):{}}function Re(t,n,e){if("function"!=typeof t)throw new kf(nt);return Kf(function(){t.apply(Q,e)},n)}function Ee(t,n,e,r){var i=-1,u=h,o=!0,a=t.length,c=[],f=n.length;if(!a)return c;e&&(n=v(n,F(e))),r?(u=d,o=!1):n.length>=tt&&(u=E,o=!1,n=new ee(n));t:for(;++ii?0:i+e),r=r===Q||r>i?i:$a(r),r<0&&(r+=i),r=e>r?0:za(r);e0&&e(a)?n>1?ze(a,n-1,e,r,i):_(i,a):r||(i[i.length]=a)}return i}function qe(t,n){return t&&jl(t,n,rc)}function Ne(t,n){return t&&Ol(t,n,rc)}function Ve(t,n){return p(n,function(n){return da(t[n])})}function Ke(t,n){n=Qi(n,t)?[n]:Ur(n);for(var e=0,r=n.length;null!=t&&en}function Ge(t,n){return null!=t&&(Ff.call(t,n)||"object"==typeof t&&n in t&&null===$i(t))}function Je(t,n){return null!=t&&n in Object(t)}function Ye(t,n,e){return t>=tl(n,e)&&t=120&&l.length>=120)?new ee(o&&l):Q}l=t[0];var s=-1,p=a[0];t:for(;++s-1;)a!==t&&Vf.call(a,c,1),Vf.call(t,c,1);return t}function wr(t,n){for(var e=t?n.length:0,r=e-1;e--;){var i=n[e];if(e==r||i!==u){var u=i;if(Ji(i))Vf.call(t,i,1);else if(Qi(i,t))delete t[fu(i)];else{var o=Ur(i),a=au(t,o);null!=a&&delete a[fu(Fu(o))]}}}return t}function xr(t,n){return t+Zf(el()*(n-t+1))}function kr(t,n,e,r){for(var i=-1,u=Xf(Hf((n-t)/(e||1)),0),o=Array(u);u--;)o[r?u:++i]=t,t+=e;return o}function Ar(t,n){var e="";if(!t||n<1||n>At)return e;do n%2&&(e+=t),n=Zf(n/2),n&&(t+=t);while(n);return e}function jr(t,n,e,r){n=Qi(n,t)?[n]:Ur(n);for(var i=-1,u=n.length,o=u-1,a=t;null!=a&&++ii?0:i+n),e=e>i?i:e,e<0&&(e+=i),i=n>e?0:e-n>>>0,n>>>=0;for(var u=Array(i);++r>>1,o=t[u];null!==o&&!Ea(o)&&(e?o<=n:o=tt){var f=n?null:Sl(t);if(f)return K(f);o=!1,i=E,c=new ee}else c=n?[]:a;t:for(;++r=r?t:Or(t,n,e)}function Nr(t,n){if(n)return t.slice();var e=new t.constructor(t.length);return t.copy(e),e}function Vr(t){var n=new t.constructor(t.byteLength);return new $f(n).set(new $f(t)),n}function Kr(t,n){var e=n?Vr(t.buffer):t.buffer;return new t.constructor(e,t.byteOffset,t.byteLength)}function Hr(t,n,e){var r=n?e(N(t),!0):N(t);return g(r,u,new t.constructor)}function Zr(t){var n=new t.constructor(t.source,On.exec(t));return n.lastIndex=t.lastIndex,n}function Gr(t,n,e){var r=n?e(K(t),!0):K(t);return g(r,o,new t.constructor)}function Jr(t){return wl?Object(wl.call(t)):{}}function Yr(t,n){var e=n?Vr(t.buffer):t.buffer;return new t.constructor(e,t.byteOffset,t.length)}function Qr(t,n){if(t!==n){var e=t!==Q,r=null===t,i=t===t,u=Ea(t),o=n!==Q,a=null===n,c=n===n,f=Ea(n);if(!a&&!f&&!u&&t>n||u&&o&&c&&!a&&!f||r&&o&&c||!e&&c||!i)return 1;if(!r&&!u&&!f&&t=a)return c;var f=e[r];return c*("desc"==f?-1:1)}}return t.index-n.index}function ti(t,n,e,r){for(var i=-1,u=t.length,o=e.length,a=-1,c=n.length,f=Xf(u-o,0),l=Array(c+f),s=!r;++a1?e[i-1]:Q,o=i>2?e[2]:Q;for(u=t.length>3&&"function"==typeof u?(i--,u):Q,o&&Yi(e[0],e[1],o)&&(u=i<3?Q:u,i=1),n=Object(n);++r-1?n[u?u[o]:o]:Q}}function vi(t){return Vo(function(n){n=ze(n,1);var e=n.length,i=e,u=r.prototype.thru;for(t&&n.reverse();i--;){var o=n[i];if("function"!=typeof o)throw new kf(nt);if(u&&!a&&"wrapper"==Li(o))var a=new r([],(!0))}for(i=a?i:e;++i=tt)return a.plant(r).value();for(var i=0,u=e?n[i].apply(this,t):r;++i1&&y.reverse(),s&&ca))return!1;var f=u.get(t);if(f)return f==n;var l=-1,s=!0,p=i&dt?new ee:Q;for(u.set(t,n);++l-1&&t%1==0&&t=this.__values__.length,n=t?Q:this.__values__[this.__index__++];return{done:t,value:n}}function so(){return this}function po(t){for(var n,r=this;r instanceof e;){var i=su(r);i.__index__=0,i.__values__=Q,n?u.__wrapped__=i:n=i;var u=i;r=r.__wrapped__}return u.__wrapped__=t,n}function ho(){var t=this.__wrapped__;if(t instanceof i){var n=t;return this.__actions__.length&&(n=new i(this)),n=n.reverse(),n.__actions__.push({func:ao,args:[Tu],thisArg:Q}),new r(n,this.__chain__)}return this.thru(Tu)}function vo(){return Tr(this.__wrapped__,this.__actions__)}function _o(t,n,e){var r=gs(t)?s:Me;return e&&Yi(t,n,e)&&(n=Q),r(t,Mi(n,3))}function go(t,n){var e=gs(t)?p:$e;return e(t,Mi(n,3))}function yo(t,n){return ze(Ao(t,n),1)}function mo(t,n){return ze(Ao(t,n),kt)}function bo(t,n,e){return e=e===Q?1:$a(e),ze(Ao(t,n),e)}function wo(t,n){var e=gs(t)?f:kl;return e(t,Mi(n,3))}function xo(t,n){var e=gs(t)?l:Al;return e(t,Mi(n,3))}function ko(t,n,e,r){t=ia(t)?t:_c(t),e=e&&!r?$a(e):0;var i=t.length;return e<0&&(e=Xf(i+e,0)),Ra(t)?e<=i&&t.indexOf(n,e)>-1:!!i&&x(t,n,e)>-1}function Ao(t,n){var e=gs(t)?v:fr;return e(t,Mi(n,3))}function jo(t,n,e,r){return null==t?[]:(gs(n)||(n=null==n?[]:[n]),e=r?Q:e,gs(e)||(e=null==e?[]:[e]),vr(t,n,e))}function Oo(t,n,e){var r=gs(t)?g:j,i=arguments.length<3;return r(t,Mi(n,4),e,i,kl)}function Co(t,n,e){var r=gs(t)?y:j,i=arguments.length<3;return r(t,Mi(n,4),e,i,Al)}function So(t,n){var e=gs(t)?p:$e;return n=Mi(n,3),e(t,function(t,e,r){return!n(t,e,r)})}function Io(t){var n=ia(t)?t:_c(t),e=n.length;return e>0?n[xr(0,e-1)]:Q}function Fo(t,n,e){var r=-1,i=Ta(t),u=i.length,o=u-1;for(n=(e?Yi(t,n,e):n===Q)?1:ye($a(n),0,u);++r0&&(e=n.apply(this,arguments)),t<=1&&(n=Q),e}}function Do(t,n,e){n=e?Q:n;var r=Ci(t,at,Q,Q,Q,Q,Q,n);return r.placeholder=Do.placeholder,r}function $o(t,n,e){n=e?Q:n;var r=Ci(t,ct,Q,Q,Q,Q,Q,n);return r.placeholder=$o.placeholder,r}function zo(t,n,e){function r(n){var e=p,r=h;return p=h=Q,y=n,v=t.apply(r,e)}function i(t){return y=t,_=Kf(a,n),m?r(t):v}function u(t){var e=t-g,r=t-y,i=n-e;return b?tl(i,d-r):i}function o(t){var e=t-g,r=t-y;return g===Q||e>=n||e<0||b&&r>=d}function a(){var t=Wo();return o(t)?c(t):void(_=Kf(a,u(t)))}function c(t){return _=Q,w&&p?r(t):(p=h=Q,v)}function f(){y=0,p=g=h=_=Q}function l(){return _===Q?v:c(Wo())}function s(){var t=Wo(),e=o(t);if(p=arguments,h=this,g=t,e){if(_===Q)return i(g);if(b)return _=Kf(a,n),r(g)}return _===Q&&(_=Kf(a,n)),v}var p,h,d,v,_,g,y=0,m=!1,b=!1,w=!0;if("function"!=typeof t)throw new kf(nt);return n=Pa(n)||0,ga(e)&&(m=!!e.leading,b="maxWait"in e,d=b?Xf(Pa(e.maxWait)||0,n):d,w="trailing"in e?!!e.trailing:w),s.cancel=f,s.flush=l,s}function Po(t){return Ci(t,ht)}function Uo(t,n){if("function"!=typeof t||n&&"function"!=typeof n)throw new kf(nt);var e=function(){var r=arguments,i=n?n.apply(this,r):r[0],u=e.cache;if(u.has(i))return u.get(i);var o=t.apply(this,r);return e.cache=u.set(i,o),o};return e.cache=new(Uo.Cache||Jn),e}function qo(t){if("function"!=typeof t)throw new kf(nt);return function(){return!t.apply(this,arguments)}}function No(t){return To(2,t)}function Vo(t,n){if("function"!=typeof t)throw new kf(nt);return n=Xf(n===Q?t.length-1:$a(n),0),function(){for(var e=arguments,r=-1,i=Xf(e.length-n,0),u=Array(i);++r-1&&t%1==0&&t<=At}function ga(t){var n=typeof t;return!!t&&("object"==n||"function"==n)}function ya(t){return!!t&&"object"==typeof t}function ma(t){return ya(t)&&Pi(t)==Tt}function ba(t,n){return t===n||rr(t,n,Ti(n))}function wa(t,n,e){return e="function"==typeof e?e:Q,rr(t,n,Ti(n),e)}function xa(t){return Oa(t)&&t!=+t}function ka(t){if(El(t))throw new bf("This method is not supported with `core-js`. Try https://github.com/es-shims.");return ir(t)}function Aa(t){return null===t}function ja(t){return null==t}function Oa(t){return"number"==typeof t||ya(t)&&Lf.call(t)==Dt}function Ca(t){if(!ya(t)||Lf.call(t)!=$t||U(t))return!1;var n=$i(t);if(null===n)return!0;var e=Ff.call(n,"constructor")&&n.constructor;return"function"==typeof e&&e instanceof e&&If.call(e)==Ef}function Sa(t){return ga(t)&&Lf.call(t)==Pt}function Ia(t){return va(t)&&t>=-At&&t<=At}function Fa(t){return ya(t)&&Pi(t)==Ut}function Ra(t){return"string"==typeof t||!gs(t)&&ya(t)&&Lf.call(t)==qt}function Ea(t){return"symbol"==typeof t||ya(t)&&Lf.call(t)==Nt}function La(t){return ya(t)&&_a(t.length)&&!!Ce[Lf.call(t)]}function Wa(t){return t===Q}function Ma(t){return ya(t)&&Pi(t)==Vt}function Ba(t){return ya(t)&&Lf.call(t)==Kt}function Ta(t){if(!t)return[];if(ia(t))return Ra(t)?G(t):ei(t);if(Uf&&t[Uf])return q(t[Uf]());var n=Pi(t),e=n==Tt?N:n==Ut?K:_c;return e(t)}function Da(t){if(!t)return 0===t?t:0;if(t=Pa(t),t===kt||t===-kt){var n=t<0?-1:1;return n*jt}return t===t?t:0}function $a(t){var n=Da(t),e=n%1;return n===n?e?n-e:n:0}function za(t){return t?ye($a(t),0,Ct):0}function Pa(t){if("number"==typeof t)return t;if(Ea(t))return Ot;if(ga(t)){var n=da(t.valueOf)?t.valueOf():t;t=ga(n)?n+"":n}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(bn,"");var e=In.test(t);return e||Rn.test(t)?We(t.slice(2),e?2:8):Sn.test(t)?Ot:+t}function Ua(t){return ri(t,ic(t))}function qa(t){return ye($a(t),-At,At)}function Na(t){return null==t?"":Er(t)}function Va(t,n){var e=Fe(t);return n?_e(e,n):e}function Ka(t,n){return b(t,Mi(n,3),qe)}function Ha(t,n){return b(t,Mi(n,3),Ne)}function Za(t,n){return null==t?t:jl(t,Mi(n,3),ic)}function Ga(t,n){return null==t?t:Ol(t,Mi(n,3),ic)}function Ja(t,n){return t&&qe(t,Mi(n,3))}function Ya(t,n){return t&&Ne(t,Mi(n,3))}function Qa(t){return null==t?[]:Ve(t,rc(t))}function Xa(t){return null==t?[]:Ve(t,ic(t))}function tc(t,n,e){var r=null==t?Q:Ke(t,n);return r===Q?e:r}function nc(t,n){return null!=t&&qi(t,n,Ge)}function ec(t,n){return null!=t&&qi(t,n,Je)}function rc(t){var n=eu(t);if(!n&&!ia(t))return or(t);var e=Hi(t),r=!!e,i=e||[],u=i.length;for(var o in t)!Ge(t,o)||r&&("length"==o||Ji(o,u))||n&&"constructor"==o||i.push(o);return i}function ic(t){for(var n=-1,e=eu(t),r=ar(t),i=r.length,u=Hi(t),o=!!u,a=u||[],c=a.length;++nn){var r=t;t=n,n=r}if(e||t%1||n%1){var i=el();return tl(t+i*(n-t+Le("1e-"+((i+"").length-1))),n)}return xr(t,n)}function wc(t){return Ns(Na(t).toLowerCase())}function xc(t){return t=Na(t),t&&t.replace(Ln,T).replace(be,"")}function kc(t,n,e){t=Na(t),n=Er(n);var r=t.length;return e=e===Q?r:ye($a(e),0,r),e-=n.length,e>=0&&t.indexOf(n,e)==e}function Ac(t){return t=Na(t),t&&sn.test(t)?t.replace(fn,D):t}function jc(t){return t=Na(t),t&&mn.test(t)?t.replace(yn,"\\$&"):t}function Oc(t,n,e){t=Na(t),n=$a(n);var r=n?Z(t):0;if(!n||r>=n)return t;var i=(n-r)/2;return bi(Zf(i),e)+t+bi(Hf(i),e)}function Cc(t,n,e){t=Na(t),n=$a(n);var r=n?Z(t):0;return n&&r>>0)?(t=Na(t),t&&("string"==typeof n||null!=n&&!Sa(n))&&(n=Er(n),""==n&&ke.test(t))?qr(G(t),0,e):ul.call(t,n,e)):[]}function Lc(t,n,e){return t=Na(t),e=ye($a(e),0,t.length),t.lastIndexOf(Er(n),e)==e}function Wc(t,e,r){var i=n.templateSettings;r&&Yi(t,e,r)&&(e=Q),t=Na(t),e=ks({},e,i,se);var u,o,a=ks({},e.imports,i.imports,se),c=rc(a),f=R(a,c),l=0,s=e.interpolate||Wn,p="__p += '",h=xf((e.escape||Wn).source+"|"+s.source+"|"+(s===dn?jn:Wn).source+"|"+(e.evaluate||Wn).source+"|$","g"),d="//# sourceURL="+("sourceURL"in e?e.sourceURL:"lodash.templateSources["+ ++Oe+"]")+"\n";t.replace(h,function(n,e,r,i,a,c){return r||(r=i),p+=t.slice(l,c).replace(Mn,$),e&&(u=!0,p+="' +\n__e("+e+") +\n'"),a&&(o=!0,p+="';\n"+a+";\n__p += '"),r&&(p+="' +\n((__t = ("+r+")) == null ? '' : __t) +\n'"),l=c+n.length,n}),p+="';\n";var v=e.variable;v||(p="with (obj) {\n"+p+"\n}\n"),p=(o?p.replace(un,""):p).replace(on,"$1").replace(an,"$1;"),p="function("+(v||"obj")+") {\n"+(v?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(u?", __e = _.escape":"")+(o?", __j = Array.prototype.join;\nfunction print() { __p += __j.call(arguments, '') }\n":";\n")+p+"return __p\n}";var _=Vs(function(){return Function(c,d+"return "+p).apply(Q,f)});if(_.source=p,pa(_))throw _;return _}function Mc(t){return Na(t).toLowerCase()}function Bc(t){return Na(t).toUpperCase()}function Tc(t,n,e){if(t=Na(t),t&&(e||n===Q))return t.replace(bn,"");if(!t||!(n=Er(n)))return t;var r=G(t),i=G(n),u=L(r,i),o=W(r,i)+1;return qr(r,u,o).join("")}function Dc(t,n,e){if(t=Na(t),t&&(e||n===Q))return t.replace(xn,"");if(!t||!(n=Er(n)))return t;var r=G(t),i=W(r,G(n))+1;return qr(r,0,i).join("")}function $c(t,n,e){if(t=Na(t),t&&(e||n===Q))return t.replace(wn,"");if(!t||!(n=Er(n)))return t;var r=G(t),i=L(r,G(n));return qr(r,i).join("")}function zc(t,n){var e=_t,r=gt;if(ga(n)){var i="separator"in n?n.separator:i;e="length"in n?$a(n.length):e,r="omission"in n?Er(n.omission):r}t=Na(t);var u=t.length;if(ke.test(t)){var o=G(t);u=o.length}if(e>=u)return t;var a=e-Z(r);if(a<1)return r;var c=o?qr(o,0,a).join(""):t.slice(0,a);if(i===Q)return c+r;if(o&&(a+=c.length-a),Sa(i)){if(t.slice(a).search(i)){var f,l=c;for(i.global||(i=xf(i.source,Na(On.exec(i))+"g")),i.lastIndex=0;f=i.exec(l);)var s=f.index;c=c.slice(0,s===Q?a:s)}}else if(t.indexOf(Er(i),a)!=a){var p=c.lastIndexOf(i);p>-1&&(c=c.slice(0,p))}return c+r}function Pc(t){return t=Na(t),t&&ln.test(t)?t.replace(cn,J):t}function Uc(t,n,e){return t=Na(t),n=e?Q:n,n===Q&&(n=Ae.test(t)?xe:kn),t.match(n)||[]}function qc(t){var n=t?t.length:0,e=Mi();return t=n?v(t,function(t){if("function"!=typeof t[1])throw new kf(nt);return[e(t[0]),t[1]]}):[],Vo(function(e){for(var r=-1;++rAt)return[];var e=Ct,r=tl(t,Ct);n=Mi(n),t-=Ct;for(var i=S(r,n);++e0){if(++t>=yt)return e}else t=0;return Cl(e,r)}}(),Wl=Uo(function(t){var n=[];return Na(t).replace(gn,function(t,e,r,i){n.push(r?i.replace(An,"$1"):e||t)}),n}),Ml=Vo(function(t,n){return ua(t)?Ee(t,ze(n,1,ua,!0)):[]}),Bl=Vo(function(t,n){var e=Fu(n);return ua(e)&&(e=Q),ua(t)?Ee(t,ze(n,1,ua,!0),Mi(e)):[]}),Tl=Vo(function(t,n){var e=Fu(n);return ua(e)&&(e=Q),ua(t)?Ee(t,ze(n,1,ua,!0),Q,e):[]}),Dl=Vo(function(t){var n=v(t,zr);return n.length&&n[0]===t[0]?Qe(n):[]}),$l=Vo(function(t){var n=Fu(t),e=v(t,zr);return n===Fu(e)?n=Q:e.pop(),e.length&&e[0]===t[0]?Qe(e,Mi(n)):[]}),zl=Vo(function(t){var n=Fu(t),e=v(t,zr);return n===Fu(e)?n=Q:e.pop(),e.length&&e[0]===t[0]?Qe(e,Q,n):[]}),Pl=Vo(Lu),Ul=Vo(function(t,n){n=ze(n,1);var e=t?t.length:0,r=ge(t,n);return wr(t,v(n,function(t){return Ji(t,e)?+t:t}).sort(Qr)),r}),ql=Vo(function(t){return Lr(ze(t,1,ua,!0))}),Nl=Vo(function(t){var n=Fu(t);return ua(n)&&(n=Q),Lr(ze(t,1,ua,!0),Mi(n))}),Vl=Vo(function(t){var n=Fu(t);return ua(n)&&(n=Q),Lr(ze(t,1,ua,!0),Q,n)}),Kl=Vo(function(t,n){return ua(t)?Ee(t,n):[]}),Hl=Vo(function(t){return Dr(p(t,ua))}),Zl=Vo(function(t){var n=Fu(t);return ua(n)&&(n=Q),Dr(p(t,ua),Mi(n))}),Gl=Vo(function(t){var n=Fu(t);return ua(n)&&(n=Q),Dr(p(t,ua),Q,n)}),Jl=Vo(no),Yl=Vo(function(t){var n=t.length,e=n>1?t[n-1]:Q;return e="function"==typeof e?(t.pop(),e):Q,eo(t,e)}),Ql=Vo(function(t){t=ze(t,1);var n=t.length,e=n?t[0]:0,u=this.__wrapped__,o=function(n){return ge(n,t)};return!(n>1||this.__actions__.length)&&u instanceof i&&Ji(e)?(u=u.slice(e,+e+(n?1:0)),u.__actions__.push({func:ao,args:[o],thisArg:Q}),new r(u,this.__chain__).thru(function(t){return n&&!t.length&&t.push(Q),t})):this.thru(o)}),Xl=ui(function(t,n,e){Ff.call(t,e)?++t[e]:t[e]=1}),ts=di(bu),ns=di(wu),es=ui(function(t,n,e){Ff.call(t,e)?t[e].push(n):t[e]=[n]}),rs=Vo(function(t,n,e){var r=-1,i="function"==typeof n,u=Qi(n),o=ia(t)?Array(t.length):[];return kl(t,function(t){var c=i?n:u&&null!=t?t[n]:Q;o[++r]=c?a(c,t,e):tr(t,n,e)}),o}),is=ui(function(t,n,e){t[e]=n}),us=ui(function(t,n,e){t[e?0:1].push(n)},function(){return[[],[]]}),os=Vo(function(t,n){if(null==t)return[];var e=n.length;return e>1&&Yi(t,n[0],n[1])?n=[]:e>2&&Yi(n[0],n[1],n[2])&&(n=[n[0]]),n=1==n.length&&gs(n[0])?n[0]:ze(n,1,Gi),vr(t,n,[])}),as=Vo(function(t,n,e){var r=it;if(e.length){var i=V(e,Wi(as));r|=ft}return Ci(t,r,n,e,i)}),cs=Vo(function(t,n,e){var r=it|ut;if(e.length){var i=V(e,Wi(cs));r|=ft}return Ci(n,r,t,e,i)}),fs=Vo(function(t,n){return Re(t,1,n)}),ls=Vo(function(t,n,e){return Re(t,Pa(n)||0,e)});Uo.Cache=Jn;var ss=Vo(function(t,n){n=1==n.length&&gs(n[0])?v(n[0],F(Mi())):v(ze(n,1,Gi),F(Mi()));var e=n.length;return Vo(function(r){for(var i=-1,u=tl(r.length,e);++i=n}),gs=Array.isArray,ys=Bf?function(t){return t instanceof Bf}:rf,ms=ki(cr),bs=ki(function(t,n){return t<=n}),ws=oi(function(t,n){if(hl||eu(n)||ia(n))return void ri(n,rc(n),t);for(var e in n)Ff.call(n,e)&&he(t,e,n[e])}),xs=oi(function(t,n){if(hl||eu(n)||ia(n))return void ri(n,ic(n),t);for(var e in n)he(t,e,n[e])}),ks=oi(function(t,n,e,r){ri(n,ic(n),t,r)}),As=oi(function(t,n,e,r){ri(n,rc(n),t,r)}),js=Vo(function(t,n){return ge(t,ze(n,1))}),Os=Vo(function(t){return t.push(Q,se),a(ks,Q,t)}),Cs=Vo(function(t){return t.push(Q,ou),a(Es,Q,t)}),Ss=gi(function(t,n,e){t[n]=e},Vc(Kc)),Is=gi(function(t,n,e){Ff.call(t,n)?t[n].push(e):t[n]=[e]},Mi),Fs=Vo(tr),Rs=oi(function(t,n,e){pr(t,n,e)}),Es=oi(function(t,n,e,r){pr(t,n,e,r)}),Ls=Vo(function(t,n){return null==t?{}:(n=v(ze(n,1),fu),_r(t,Ee(Ei(t),n)))}),Ws=Vo(function(t,n){return null==t?{}:_r(t,v(ze(n,1),fu))}),Ms=Oi(rc),Bs=Oi(ic),Ts=si(function(t,n,e){return n=n.toLowerCase(),t+(e?wc(n):n)}),Ds=si(function(t,n,e){return t+(e?"-":"")+n.toLowerCase()}),$s=si(function(t,n,e){return t+(e?" ":"")+n.toLowerCase()}),zs=li("toLowerCase"),Ps=si(function(t,n,e){return t+(e?"_":"")+n.toLowerCase()}),Us=si(function(t,n,e){return t+(e?" ":"")+Ns(n)}),qs=si(function(t,n,e){return t+(e?" ":"")+n.toUpperCase()}),Ns=li("toUpperCase"),Vs=Vo(function(t,n){try{return a(t,Q,n)}catch(e){return pa(e)?e:new bf(e)}}),Ks=Vo(function(t,n){return f(ze(n,1),function(n){n=fu(n),t[n]=as(t[n],t)}),t}),Hs=vi(),Zs=vi(!0),Gs=Vo(function(t,n){return function(e){return tr(e,t,n)}}),Js=Vo(function(t,n){return function(e){return tr(t,e,n)}}),Ys=mi(v),Qs=mi(s),Xs=mi(m),tp=xi(),np=xi(!0),ep=yi(function(t,n){return t+n}),rp=ji("ceil"),ip=yi(function(t,n){return t/n}),up=ji("floor"),op=yi(function(t,n){return t*n}),ap=ji("round"),cp=yi(function(t,n){return t-n});return n.after=Mo,n.ary=Bo,n.assign=ws,n.assignIn=xs,n.assignInWith=ks,n.assignWith=As,n.at=js,n.before=To,n.bind=as,n.bindAll=Ks,n.bindKey=cs,n.castArray=Jo,n.chain=uo,n.chunk=pu,n.compact=hu,n.concat=du,n.cond=qc,n.conforms=Nc,n.constant=Vc,n.countBy=Xl,n.create=Va,n.curry=Do,n.curryRight=$o,n.debounce=zo,n.defaults=Os,n.defaultsDeep=Cs,n.defer=fs,n.delay=ls,n.difference=Ml,n.differenceBy=Bl,n.differenceWith=Tl,n.drop=vu,n.dropRight=_u,n.dropRightWhile=gu,n.dropWhile=yu,n.fill=mu,n.filter=go,n.flatMap=yo,n.flatMapDeep=mo,n.flatMapDepth=bo,n.flatten=xu,n.flattenDeep=ku,n.flattenDepth=Au,n.flip=Po,n.flow=Hs,n.flowRight=Zs,n.fromPairs=ju,n.functions=Qa,n.functionsIn=Xa,n.groupBy=es,n.initial=Su,n.intersection=Dl,n.intersectionBy=$l,n.intersectionWith=zl,n.invert=Ss,n.invertBy=Is,n.invokeMap=rs,n.iteratee=Hc,n.keyBy=is,n.keys=rc,n.keysIn=ic,n.map=Ao,n.mapKeys=uc,n.mapValues=oc,n.matches=Zc,n.matchesProperty=Gc,n.memoize=Uo,n.merge=Rs,n.mergeWith=Es,n.method=Gs,n.methodOf=Js,n.mixin=Jc,n.negate=qo,n.nthArg=Xc,n.omit=Ls,n.omitBy=ac,n.once=No,n.orderBy=jo,n.over=Ys,n.overArgs=ss,n.overEvery=Qs,n.overSome=Xs,n.partial=ps,n.partialRight=hs,n.partition=us,n.pick=Ws,n.pickBy=cc,n.property=tf,n.propertyOf=nf,n.pull=Pl,n.pullAll=Lu,n.pullAllBy=Wu,n.pullAllWith=Mu,n.pullAt=Ul,n.range=tp,n.rangeRight=np,n.rearg=ds,n.reject=So,n.remove=Bu,n.rest=Vo,n.reverse=Tu,n.sampleSize=Fo,n.set=lc,n.setWith=sc,n.shuffle=Ro,n.slice=Du,n.sortBy=os,n.sortedUniq=Vu,n.sortedUniqBy=Ku,n.split=Ec,n.spread=Ko,n.tail=Hu,n.take=Zu,n.takeRight=Gu,n.takeRightWhile=Ju,n.takeWhile=Yu,n.tap=oo,n.throttle=Ho,n.thru=ao,n.toArray=Ta,n.toPairs=Ms,n.toPairsIn=Bs,n.toPath=ff,n.toPlainObject=Ua,n.transform=pc,n.unary=Zo,n.union=ql,n.unionBy=Nl,n.unionWith=Vl,n.uniq=Qu,n.uniqBy=Xu,n.uniqWith=to,n.unset=hc,n.unzip=no,n.unzipWith=eo,n.update=dc,n.updateWith=vc,n.values=_c,n.valuesIn=gc,n.without=Kl,n.words=Uc,n.wrap=Go,n.xor=Hl,n.xorBy=Zl,n.xorWith=Gl,n.zip=Jl,n.zipObject=ro,n.zipObjectDeep=io,n.zipWith=Yl,n.entries=Ms,n.entriesIn=Bs,n.extend=xs,n.extendWith=ks,Jc(n,n),n.add=ep,n.attempt=Vs,n.camelCase=Ts,n.capitalize=wc,n.ceil=rp,n.clamp=yc,n.clone=Yo,n.cloneDeep=Xo,n.cloneDeepWith=ta,n.cloneWith=Qo,n.deburr=xc,n.divide=ip,n.endsWith=kc,n.eq=na,n.escape=Ac,n.escapeRegExp=jc,n.every=_o,n.find=ts,n.findIndex=bu,n.findKey=Ka,n.findLast=ns,n.findLastIndex=wu,n.findLastKey=Ha,n.floor=up,n.forEach=wo,n.forEachRight=xo,n.forIn=Za,n.forInRight=Ga,n.forOwn=Ja,n.forOwnRight=Ya,n.get=tc,n.gt=vs,n.gte=_s,n.has=nc,n.hasIn=ec,n.head=Ou,n.identity=Kc,n.includes=ko,n.indexOf=Cu,n.inRange=mc,n.invoke=Fs,n.isArguments=ea,n.isArray=gs,n.isArrayBuffer=ra,n.isArrayLike=ia,n.isArrayLikeObject=ua,n.isBoolean=oa,n.isBuffer=ys,n.isDate=aa,n.isElement=ca,n.isEmpty=fa,n.isEqual=la,n.isEqualWith=sa,n.isError=pa,n.isFinite=ha,n.isFunction=da,n.isInteger=va,n.isLength=_a,n.isMap=ma,n.isMatch=ba,n.isMatchWith=wa,n.isNaN=xa,n.isNative=ka,n.isNil=ja,n.isNull=Aa,n.isNumber=Oa,n.isObject=ga,n.isObjectLike=ya,n.isPlainObject=Ca,n.isRegExp=Sa,n.isSafeInteger=Ia,n.isSet=Fa,n.isString=Ra,n.isSymbol=Ea,n.isTypedArray=La,n.isUndefined=Wa,n.isWeakMap=Ma,n.isWeakSet=Ba,n.join=Iu,n.kebabCase=Ds,n.last=Fu,n.lastIndexOf=Ru,n.lowerCase=$s,n.lowerFirst=zs,n.lt=ms,n.lte=bs,n.max=sf,n.maxBy=pf,n.mean=hf,n.meanBy=df,n.min=vf,n.minBy=_f,n.stubArray=ef,n.stubFalse=rf,n.stubObject=uf,n.stubString=of,n.stubTrue=af,n.multiply=op,n.nth=Eu,n.noConflict=Yc,n.noop=Qc,n.now=Wo,n.pad=Oc,n.padEnd=Cc,n.padStart=Sc,n.parseInt=Ic,n.random=bc,n.reduce=Oo,n.reduceRight=Co,n.repeat=Fc,n.replace=Rc,n.result=fc,n.round=ap,n.runInContext=Y,n.sample=Io,n.size=Eo,n.snakeCase=Ps,n.some=Lo,n.sortedIndex=$u,n.sortedIndexBy=zu,n.sortedIndexOf=Pu,n.sortedLastIndex=Uu,n.sortedLastIndexBy=qu,n.sortedLastIndexOf=Nu,n.startCase=Us,n.startsWith=Lc,n.subtract=cp,n.sum=gf,n.sumBy=yf,n.template=Wc,n.times=cf,n.toFinite=Da,n.toInteger=$a,n.toLength=za,n.toLower=Mc,n.toNumber=Pa,n.toSafeInteger=qa,n.toString=Na,n.toUpper=Bc,n.trim=Tc,n.trimEnd=Dc,n.trimStart=$c,n.truncate=zc,n.unescape=Pc,n.uniqueId=lf,n.upperCase=qs,n.upperFirst=Ns,n.each=wo,n.eachRight=xo,n.first=Ou,Jc(n,function(){var t={};return qe(n,function(e,r){Ff.call(n.prototype,r)||(t[r]=e)}),t}(),{chain:!1}),n.VERSION=X,f(["bind","bindKey","curry","curryRight","partial","partialRight"],function(t){n[t].placeholder=n}),f(["drop","take"],function(t,n){i.prototype[t]=function(e){var r=this.__filtered__;if(r&&!n)return new i(this);e=e===Q?1:Xf($a(e),0);var u=this.clone();return r?u.__takeCount__=tl(e,u.__takeCount__):u.__views__.push({size:tl(e,Ct),type:t+(u.__dir__<0?"Right":"")}),u},i.prototype[t+"Right"]=function(n){return this.reverse()[t](n).reverse()}}),f(["filter","map","takeWhile"],function(t,n){var e=n+1,r=e==bt||e==xt;i.prototype[t]=function(t){var n=this.clone();return n.__iteratees__.push({iteratee:Mi(t,3),type:e}),n.__filtered__=n.__filtered__||r,n}}),f(["head","last"],function(t,n){var e="take"+(n?"Right":"");i.prototype[t]=function(){return this[e](1).value()[0]}}),f(["initial","tail"],function(t,n){var e="drop"+(n?"":"Right");i.prototype[t]=function(){return this.__filtered__?new i(this):this[e](1)}}),i.prototype.compact=function(){return this.filter(Kc)},i.prototype.find=function(t){return this.filter(t).head()},i.prototype.findLast=function(t){return this.reverse().find(t)},i.prototype.invokeMap=Vo(function(t,n){return"function"==typeof t?new i(this):this.map(function(e){return tr(e,t,n)})}),i.prototype.reject=function(t){return t=Mi(t,3),this.filter(function(n){return!t(n)})},i.prototype.slice=function(t,n){t=$a(t);var e=this;return e.__filtered__&&(t>0||n<0)?new i(e):(t<0?e=e.takeRight(-t):t&&(e=e.drop(t)),n!==Q&&(n=$a(n),e=n<0?e.dropRight(-n):e.take(n-t)),e)},i.prototype.takeRightWhile=function(t){return this.reverse().takeWhile(t).reverse()},i.prototype.toArray=function(){return this.take(Ct)},qe(i.prototype,function(t,e){var u=/^(?:filter|find|map|reject)|While$/.test(e),o=/^(?:head|last)$/.test(e),a=n[o?"take"+("last"==e?"Right":""):e],c=o||/^find/.test(e);a&&(n.prototype[e]=function(){var e=this.__wrapped__,f=o?[1]:arguments,l=e instanceof i,s=f[0],p=l||gs(e),h=function(t){var e=a.apply(n,_([t],f));return o&&d?e[0]:e};p&&u&&"function"==typeof s&&1!=s.length&&(l=p=!1);var d=this.__chain__,v=!!this.__actions__.length,g=c&&!d,y=l&&!v;if(!c&&p){e=y?e:new i(this);var m=t.apply(e,f);return m.__actions__.push({func:ao,args:[h],thisArg:Q}),new r(m,d)}return g&&y?t.apply(this,f):(m=this.thru(h),g?o?m.value()[0]:m.value():m)})}),f(["pop","push","shift","sort","splice","unshift"],function(t){var e=Af[t],r=/^(?:push|sort|unshift)$/.test(t)?"tap":"thru",i=/^(?:pop|shift)$/.test(t);n.prototype[t]=function(){var t=arguments;if(i&&!this.__chain__){var n=this.value();return e.apply(gs(n)?n:[],t)}return this[r](function(n){return e.apply(gs(n)?n:[],t)})}}),qe(i.prototype,function(t,e){var r=n[e];if(r){var i=r.name+"",u=dl[i]||(dl[i]=[]);u.push({name:e,func:r})}}),dl[_i(Q,ut).name]=[{name:"wrapper",func:Q}],i.prototype.clone=M,i.prototype.reverse=Bn,i.prototype.value=Tn,n.prototype.at=Ql,n.prototype.chain=co,n.prototype.commit=fo,n.prototype.next=lo,n.prototype.plant=po,n.prototype.reverse=ho,n.prototype.toJSON=n.prototype.valueOf=n.prototype.value=vo,Uf&&(n.prototype[Uf]=so),n}var Q,X="4.13.1",tt=200,nt="Expected a function",et="__lodash_hash_undefined__",rt="__lodash_placeholder__",it=1,ut=2,ot=4,at=8,ct=16,ft=32,lt=64,st=128,pt=256,ht=512,dt=1,vt=2,_t=30,gt="...",yt=150,mt=16,bt=1,wt=2,xt=3,kt=1/0,At=9007199254740991,jt=1.7976931348623157e308,Ot=NaN,Ct=4294967295,St=Ct-1,It=Ct>>>1,Ft="[object Arguments]",Rt="[object Array]",Et="[object Boolean]",Lt="[object Date]",Wt="[object Error]",Mt="[object Function]",Bt="[object GeneratorFunction]",Tt="[object Map]",Dt="[object Number]",$t="[object Object]",zt="[object Promise]",Pt="[object RegExp]",Ut="[object Set]",qt="[object String]",Nt="[object Symbol]",Vt="[object WeakMap]",Kt="[object WeakSet]",Ht="[object ArrayBuffer]",Zt="[object DataView]",Gt="[object Float32Array]",Jt="[object Float64Array]",Yt="[object Int8Array]",Qt="[object Int16Array]",Xt="[object Int32Array]",tn="[object Uint8Array]",nn="[object Uint8ClampedArray]",en="[object Uint16Array]",rn="[object Uint32Array]",un=/\b__p \+= '';/g,on=/\b(__p \+=) '' \+/g,an=/(__e\(.*?\)|\b__t\)) \+\n'';/g,cn=/&(?:amp|lt|gt|quot|#39|#96);/g,fn=/[&<>"'`]/g,ln=RegExp(cn.source),sn=RegExp(fn.source),pn=/<%-([\s\S]+?)%>/g,hn=/<%([\s\S]+?)%>/g,dn=/<%=([\s\S]+?)%>/g,vn=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,_n=/^\w*$/,gn=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(\.|\[\])(?:\4|$))/g,yn=/[\\^$.*+?()[\]{}|]/g,mn=RegExp(yn.source),bn=/^\s+|\s+$/g,wn=/^\s+/,xn=/\s+$/,kn=/[a-zA-Z0-9]+/g,An=/\\(\\)?/g,jn=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,On=/\w*$/,Cn=/^0x/i,Sn=/^[-+]0x[0-9a-f]+$/i,In=/^0b[01]+$/i,Fn=/^\[object .+?Constructor\]$/,Rn=/^0o[0-7]+$/i,En=/^(?:0|[1-9]\d*)$/,Ln=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g,Wn=/($^)/,Mn=/['\n\r\u2028\u2029\\]/g,Bn="\\ud800-\\udfff",Tn="\\u0300-\\u036f\\ufe20-\\ufe23",Dn="\\u20d0-\\u20f0",$n="\\u2700-\\u27bf",zn="a-z\\xdf-\\xf6\\xf8-\\xff",Pn="\\xac\\xb1\\xd7\\xf7",Un="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",qn="\\u2000-\\u206f",Nn=" \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",Vn="A-Z\\xc0-\\xd6\\xd8-\\xde",Kn="\\ufe0e\\ufe0f",Hn=Pn+Un+qn+Nn,Zn="['’]",Gn="["+Bn+"]",Jn="["+Hn+"]",Yn="["+Tn+Dn+"]",Qn="\\d+",Xn="["+$n+"]",te="["+zn+"]",ne="[^"+Bn+Hn+Qn+$n+zn+Vn+"]",ee="\\ud83c[\\udffb-\\udfff]",re="(?:"+Yn+"|"+ee+")",ie="[^"+Bn+"]",ue="(?:\\ud83c[\\udde6-\\uddff]){2}",oe="[\\ud800-\\udbff][\\udc00-\\udfff]",ae="["+Vn+"]",ce="\\u200d",fe="(?:"+te+"|"+ne+")",le="(?:"+ae+"|"+ne+")",se="(?:"+Zn+"(?:d|ll|m|re|s|t|ve))?",pe="(?:"+Zn+"(?:D|LL|M|RE|S|T|VE))?",he=re+"?",de="["+Kn+"]?",ve="(?:"+ce+"(?:"+[ie,ue,oe].join("|")+")"+de+he+")*",_e=de+he+ve,ge="(?:"+[Xn,ue,oe].join("|")+")"+_e,ye="(?:"+[ie+Yn+"?",Yn,ue,oe,Gn].join("|")+")",me=RegExp(Zn,"g"),be=RegExp(Yn,"g"),we=RegExp(ee+"(?="+ee+")|"+ye+_e,"g"),xe=RegExp([ae+"?"+te+"+"+se+"(?="+[Jn,ae,"$"].join("|")+")",le+"+"+pe+"(?="+[Jn,ae+fe,"$"].join("|")+")",ae+"?"+fe+"+"+se,ae+"+"+pe,Qn,ge].join("|"),"g"),ke=RegExp("["+ce+Bn+Tn+Dn+Kn+"]"),Ae=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,je=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","Reflect","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","isFinite","parseInt","setTimeout"],Oe=-1,Ce={};
3 | Ce[Gt]=Ce[Jt]=Ce[Yt]=Ce[Qt]=Ce[Xt]=Ce[tn]=Ce[nn]=Ce[en]=Ce[rn]=!0,Ce[Ft]=Ce[Rt]=Ce[Ht]=Ce[Et]=Ce[Zt]=Ce[Lt]=Ce[Wt]=Ce[Mt]=Ce[Tt]=Ce[Dt]=Ce[$t]=Ce[Pt]=Ce[Ut]=Ce[qt]=Ce[Vt]=!1;var Se={};Se[Ft]=Se[Rt]=Se[Ht]=Se[Zt]=Se[Et]=Se[Lt]=Se[Gt]=Se[Jt]=Se[Yt]=Se[Qt]=Se[Xt]=Se[Tt]=Se[Dt]=Se[$t]=Se[Pt]=Se[Ut]=Se[qt]=Se[Nt]=Se[tn]=Se[nn]=Se[en]=Se[rn]=!0,Se[Wt]=Se[Mt]=Se[Vt]=!1;var Ie={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss"},Fe={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},Re={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},Ee={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"},Le=parseFloat,We=parseInt,Me="object"==typeof n&&n,Be=Me&&"object"==typeof t&&t,Te=Be&&Be.exports===Me,De=M("object"==typeof i&&i),$e=M("object"==typeof self&&self),ze=M("object"==typeof this&&this),Pe=De||$e||ze||Function("return this")(),Ue=Y();($e||{})._=Ue,r=function(){return Ue}.call(n,e,n,t),!(r!==Q&&(t.exports=r))}).call(this)}).call(n,e(2)(t),function(){return this}())},function(t,n){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children=[],t.webpackPolyfill=1),t}},function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r=e(1),i={getModel:function(t,n){var e={},i=r.indexOf(n,"*");return i>-1&&(n.splice(i,1),r.each(t.properties,function(t,e){n.splice(i,0,{key:e}),i++})),n=r.map(n,function(n){return r.isString(n)&&(n={key:n}),n.schema=r.get(t.properties,n.key,{}),n=r.defaultsDeep(r.get(n.schema,"x-schema-form",{}),n,n.schema),"string"==n.type&&(n.type="text",n["enum"]&&(n.type="select")),n}),e.fields=n,e},getSchema:function(){var t=e(4);return console.log(t.schema),t.schema},getForm:function(){var t=e(5);return t.form}};n["default"]=i},function(t,n){"use strict";t.exports.schema={type:"object",title:"Comment",properties:{name:{type:"string"},fields:{type:"array",title:"Fields",items:{type:"object",properties:{open:{type:"boolean","default":!0},type:{title:"Type",type:"string","enum":["actions","array","boolean","button","checkbox","checkboxes","date","date-time","email","fieldset","help","number","password","radiobuttons","radios","radios-inline","reset","section","select","submit","submit","tab","tabarray","template","text","textarea","time"]},key:{title:"Key",type:"string",description:"Unique identifier"},title:{condition:"model.notitle",title:"Title",type:"string"},notitle:{type:"boolean",title:"Don't show title"},description:{title:"Description",type:"string"},validationMessage:{title:"Validation Message",description:"A custom validation error message. It can be a string, an object with error codes as key and messages as values or a custom message function",type:"string"},onChange:{title:"onChange",description:"onChange event handler, expression or function. For expression, modelValue and form are both available. For a function, they will be passed as parameters in that order",type:"string"},feedback:{title:"Feedback Icon",description:'Inline feedback icons. To turn off just set feedback to false. If set to a string that string is evaluated by a ngClass in the decorators scope. If not set att all the default value is { "glyphicon": true, "glyphicon-ok": hasSuccess(), "glyphicon-remove": hasError() }',type:"string"},disableSuccessState:{type:"boolean",title:"Disable Success State","default":!1},disableErrorState:{type:"boolean",title:"Disable Error State","default":!1},placeholder:{title:"Placeholder",description:"Placeholder on inputs and textarea",type:"string"},ngModelOptions:{title:"ng-Model Options",description:"Passed along to ng-model-options",type:"string"},readonly:{type:"boolean",title:"Readonly","default":!1},htmlClass:{title:"Class",description:"CSS Class(es) to be added to the container div e.g. : 'street foobar'",type:"string"},destroyStrategy:{title:"Destroy Strategy",description:"One of null, empty , remove, or retain. Changes model on $destroy event. default is remove.",type:"string"},copyValueTo:{title:"Copy Value To",description:"Copy values to these schema keys e.g ['address.street']. The receiving fields can be shown, but the intent for them is to be hidden.",type:"string"},fieldHtmlClass:{title:"Field Class",description:"CSS Class(es) to be added to field input (or similar)",type:"string"},labelHtmlClass:{title:"Label Class",description:"CSS Class(es) to be added to the label of the field (or similar)",type:"string"},condition:{title:"Condition",description:"Show or hide field depending on an angular expression e.g 'model.age < 18'. The expression has access to model, modelValue, arrayIndex. The condition need not reference a model value it could be anything on scope.",type:"string"},fieldAddonLeft:{title:"Field Addon - Left",description:"Add html code to left of input field. For reference check bootstrap input groups .",type:"string"},fieldAddonRight:{title:"Field Addon - Right",description:"Add html code to right of input field. For reference check bootstrap input groups .",type:"string"},onClick:{title:"onClick",description:"Function to call when a button/submit is clicked",type:"string"},showAdvanced:{title:"Show advance options",type:"boolean"}},required:["key"]}}},required:["name"]}},function(t,n){"use strict";t.exports.form=[{key:"fields",type:"array",title:"Form Fields",add:"Add a new Field",remove:"Remove Field",startEmpty:!0,items:[{key:"fields[].title",htmlClass:"hide-label",placeholder:"Title"},{type:"section",htmlClass:"row",items:[{key:"fields[].type",placeholder:"Type",notitle:!0,htmlClass:"col-sm-6 hide-label"},{key:"fields[].key",placeholder:"Key (Unique Identifier)",notitle:!0,htmlClass:"col-sm-6 hide-label"}]},{key:"fields[].open",notitle:!0,type:"hidden"},{key:"fields[].description",type:"textarea",placeholder:"Description",notitle:!0},{type:"section",htmlClass:"row",items:[{key:"fields[].notitle",htmlClass:"col-sm-6"},{key:"fields[].showAdvanced",htmlClass:"col-sm-6"}]},{condition:"model.fields[arrayIndex].showAdvanced",type:"help",helpvalue:" "},{type:"section",htmlClass:"row",items:[{type:"section",htmlClass:"col-md-4",items:[{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].disableSuccessState"}]},{type:"section",htmlClass:"col-md-4",items:[{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].disableErrorState"}]},{type:"section",htmlClass:"col-md-4",items:[{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].readonly"}]}]},{condition:"model.fields[arrayIndex].showAdvanced",type:"help",helpvalue:" "},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].validationMessage",type:"textarea"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].onChange",type:"textarea"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].feedback"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].placeholder"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].ngModelOptions",type:"textarea"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].htmlClass"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].destroyStrategy"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].copyValueTo"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].fieldHtmlClass"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].labelHtmlClass"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].condition"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].fieldAddonLeft"},{condition:"model.fields[arrayIndex].showAdvanced",key:"fields[].fieldAddonRight"}]}]},function(t,n,e){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r,i=e(1),u=e(7)["default"],o={getFormDefinitions:function(t){return r={schema:{type:"object",properties:{}},form:[]},i.isArray(t.fields)&&i.forEach(t.fields,function(t){t.type&&(r=u.generateField(t,r))}),r},addField:function(t){}};n["default"]=o},function(t,n,e){"use strict";function r(t,n,e){return n in t?Object.defineProperty(t,n,{value:e,enumerable:!0,configurable:!0,writable:!0}):t[n]=e,t}Object.defineProperty(n,"__esModule",{value:!0});var i,u=e(1),o=(i={generateField:function(t,n){var e=u.camelCase("_generate_"+t.type.replace("-","_")+"_field");return n=this.generateStandardFormAttributes(t,n),n=this.generateStandardSchemaAttributes(t,n),u.isFunction(this[e])&&(n=this[e](t,n)),n},generateStandardFormAttributes:function(t,n){var e=void 0,r=void 0,i=["key","condition","onChange","notitle","showAdvanced","validationMessage","onChange","ngModelOptions","condition","fieldAddonLeft","fieldAddonRight","showAdvanced","validationMessage","onChange","feedback","disableSuccessState","disableErrorState","placeholder","ngModelOptions","readonly","htmlClass","destroyStrategy","copyValueTo","fieldHtmlClass","labelHtmlClass","items"];return e=u.pick(t,i),r=u.findIndex(n,{key:t.key}),e.key||(e.type=t.type,e.title=t.title,r=u.findIndex(n,{key:void 0,type:t.type,title:t.title})),r>-1?n.form[r]=e:n.form.push(e),n},generateStandardSchemaAttributes:function(t,n){var e=["type","format","description","title","minLength","maxLength"];return t.key&&(n.schema.properties[t.key]=u.pick(t,e)),n},updateForm:function(t,n,e,r){var i=u.findKey(t.form,"key",n);return t.form[i][e]=r,t},generateTextField:function(t,n){return n.schema.properties[t.key].type="string",n},generateTextareaField:function(t,n){return n.schema.properties[t.key].type="string",n=this.updateForm(n,t.key,"type","textarea")},generateEmailField:function(t,n){return n.schema.properties[t.key].type="string",n.schema.properties[t.key].format="email",n},generateSelectField:function(t,n){return n.schema.properties[t.key].type="string",n.schema.properties[t.key]["enum"]=t["enum"],n},generateCheckboxField:function(t,n){return n.schema.properties[t.key].type="string",n.schema.properties[t.key]["enum"]=t["enum"],n},generateDateField:function(t,n){return n.schema.properties[t.key].type="string",n.schema.properties[t.key].format="date",n},generateTimeField:function(t,n){return n.schema.properties[t.key].type="string",n.schema.properties[t.key].format="time",n},generateDateTimeField:function(t,n){return n.schema.properties[t.key].type="string",n.schema.properties[t.key].format="date-time",n},generateFieldsetField:function(t,n){return t.key&&delete n.schema.properties[t.key],n},generateSectionField:function(t,n){return n},generateActionsField:function(t,n){return n},generateNumberField:function(t,n){return n},generatePasswordField:function(t,n){return n}},r(i,"generateCheckboxField",function(t,n){return n}),r(i,"generateCheckboxesField",function(t,n){return n}),r(i,"generateSubmitField",function(t,n){return n}),r(i,"generateButtonField",function(t,n){return n}),r(i,"generateRadiosField",function(t,n){return n}),r(i,"generateRadiosInlineField",function(t,n){return n}),r(i,"generateRadioButtonsField",function(t,n){return n}),r(i,"generateHelpField",function(t,n){return n}),r(i,"generateTemplateField",function(t,n){return n}),r(i,"generateTabField",function(t,n){return n}),r(i,"generateArrayField",function(t,n){return n}),r(i,"generateTabArrayField",function(t,n){return n}),i);n["default"]=o}])});
4 | //# sourceMappingURL=json-schema-form-generator.min.js.map
5 |
--------------------------------------------------------------------------------