@wirenboard/json-editor 2.5.3-wb13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. package/.env-dist +2 -0
  2. package/.eslintrc +7 -0
  3. package/.gitattributes +1 -0
  4. package/.github/PULL_REQUEST_TEMPLATE.md +9 -0
  5. package/.github/issue_template +25 -0
  6. package/.github/workflows/build.yml +58 -0
  7. package/.travis.yml +70 -0
  8. package/CHANGELOG.md +915 -0
  9. package/CONTRIBUTING.md +92 -0
  10. package/LICENSE +20 -0
  11. package/Makefile +26 -0
  12. package/README.md +1646 -0
  13. package/README_ADDON.md +573 -0
  14. package/UPGRADING.md +46 -0
  15. package/build/CssToJson.js +55 -0
  16. package/codecept.conf.js +35 -0
  17. package/config/.eslintrc +7 -0
  18. package/config/codeceptjs_helpers.js +139 -0
  19. package/config/helpers.js +10 -0
  20. package/config/karma.conf.js +93 -0
  21. package/config/readme.md +31 -0
  22. package/config/webpack.common.js +75 -0
  23. package/config/webpack.dev.js +15 -0
  24. package/config/webpack.nonmin.js +19 -0
  25. package/config/webpack.prod.js +25 -0
  26. package/dist/jsoneditor.js +14 -0
  27. package/dist/nonmin/jsoneditor.js +29097 -0
  28. package/dist/nonmin/jsoneditor.js.map +1 -0
  29. package/docs/ace_editor.html +56 -0
  30. package/docs/advanced.html +136 -0
  31. package/docs/basic.html +63 -0
  32. package/docs/basic_person.json +26 -0
  33. package/docs/choices.html +86 -0
  34. package/docs/cleave.html +132 -0
  35. package/docs/colorpicker.html +194 -0
  36. package/docs/css_integration.html +135 -0
  37. package/docs/datetime.html +305 -0
  38. package/docs/describedby.html +161 -0
  39. package/docs/enumsource.html +67 -0
  40. package/docs/images/categoriesDemo.png +0 -0
  41. package/docs/images/inheritance_tree.png +0 -0
  42. package/docs/images/jsoneditor.png +0 -0
  43. package/docs/imask.html +192 -0
  44. package/docs/index.html +579 -0
  45. package/docs/materialize_css.html +164 -0
  46. package/docs/meta_schema.json +705 -0
  47. package/docs/multiple_upload_base64.html +65 -0
  48. package/docs/person.json +73 -0
  49. package/docs/polyfills/assign.js +29 -0
  50. package/docs/radio.html +156 -0
  51. package/docs/recursive.html +170 -0
  52. package/docs/select2.html +99 -0
  53. package/docs/selectize.html +100 -0
  54. package/docs/signature.html +42 -0
  55. package/docs/starrating.html +137 -0
  56. package/docs/upload.html +131 -0
  57. package/docs/uuid.html +70 -0
  58. package/docs/wysiwyg.html +56 -0
  59. package/jasmine.json +11 -0
  60. package/json-editor-json-editor-2.5.3-wb13.tgz +0 -0
  61. package/package.json +100 -0
  62. package/release-notes.md +88 -0
  63. package/src/core.js +412 -0
  64. package/src/defaults.js +402 -0
  65. package/src/editor.js +707 -0
  66. package/src/editors/ace.js +89 -0
  67. package/src/editors/array/choices.js +103 -0
  68. package/src/editors/array/select2.js +110 -0
  69. package/src/editors/array/selectize.js +103 -0
  70. package/src/editors/array.css +9 -0
  71. package/src/editors/array.css.js +3 -0
  72. package/src/editors/array.js +818 -0
  73. package/src/editors/autocomplete.js +58 -0
  74. package/src/editors/base64.js +157 -0
  75. package/src/editors/button.js +97 -0
  76. package/src/editors/checkbox.js +95 -0
  77. package/src/editors/choices.css +3 -0
  78. package/src/editors/choices.css.js +3 -0
  79. package/src/editors/choices.js +69 -0
  80. package/src/editors/colorpicker.js +103 -0
  81. package/src/editors/datetime.js +141 -0
  82. package/src/editors/describedby.js +188 -0
  83. package/src/editors/enum.js +136 -0
  84. package/src/editors/hidden.js +127 -0
  85. package/src/editors/index.js +81 -0
  86. package/src/editors/info.js +20 -0
  87. package/src/editors/integer.js +19 -0
  88. package/src/editors/ip.js +36 -0
  89. package/src/editors/jodit.js +64 -0
  90. package/src/editors/multiple.js +409 -0
  91. package/src/editors/multiselect.js +218 -0
  92. package/src/editors/null.js +18 -0
  93. package/src/editors/number.js +51 -0
  94. package/src/editors/object.css +41 -0
  95. package/src/editors/object.css.js +3 -0
  96. package/src/editors/object.js +1290 -0
  97. package/src/editors/radio.js +111 -0
  98. package/src/editors/sceditor.js +72 -0
  99. package/src/editors/select.js +370 -0
  100. package/src/editors/select2.js +110 -0
  101. package/src/editors/selectize.js +112 -0
  102. package/src/editors/signature.js +113 -0
  103. package/src/editors/simplemde.js +100 -0
  104. package/src/editors/starrating.css +52 -0
  105. package/src/editors/starrating.css.js +3 -0
  106. package/src/editors/starrating.js +135 -0
  107. package/src/editors/stepper.js +27 -0
  108. package/src/editors/string.js +372 -0
  109. package/src/editors/table.js +516 -0
  110. package/src/editors/upload.js +321 -0
  111. package/src/editors/uuid.js +56 -0
  112. package/src/iconlib.js +24 -0
  113. package/src/iconlibs/bootstrap2.js +28 -0
  114. package/src/iconlibs/bootstrap3.js +28 -0
  115. package/src/iconlibs/fontawesome3.js +28 -0
  116. package/src/iconlibs/fontawesome4.js +28 -0
  117. package/src/iconlibs/fontawesome5.js +28 -0
  118. package/src/iconlibs/foundation2.js +24 -0
  119. package/src/iconlibs/foundation3.js +28 -0
  120. package/src/iconlibs/index.js +25 -0
  121. package/src/iconlibs/jqueryui.js +28 -0
  122. package/src/iconlibs/materialicons.js +49 -0
  123. package/src/iconlibs/openiconic.js +28 -0
  124. package/src/iconlibs/spectre.js +28 -0
  125. package/src/resolvers.js +128 -0
  126. package/src/schemaloader.js +408 -0
  127. package/src/style.css +150 -0
  128. package/src/style.css.js +3 -0
  129. package/src/templates/default.js +52 -0
  130. package/src/templates/ejs.js +13 -0
  131. package/src/templates/handlebars.js +1 -0
  132. package/src/templates/hogan.js +10 -0
  133. package/src/templates/index.js +21 -0
  134. package/src/templates/lodash.js +9 -0
  135. package/src/templates/markup.js +9 -0
  136. package/src/templates/mustache.js +9 -0
  137. package/src/templates/swig.js +1 -0
  138. package/src/templates/underscore.js +9 -0
  139. package/src/theme.js +659 -0
  140. package/src/themes/barebones.css +35 -0
  141. package/src/themes/barebones.css.js +3 -0
  142. package/src/themes/barebones.js +28 -0
  143. package/src/themes/bootstrap2.js +319 -0
  144. package/src/themes/bootstrap3.css +0 -0
  145. package/src/themes/bootstrap3.css.js +3 -0
  146. package/src/themes/bootstrap3.js +315 -0
  147. package/src/themes/bootstrap4.css +89 -0
  148. package/src/themes/bootstrap4.css.js +3 -0
  149. package/src/themes/bootstrap4.js +690 -0
  150. package/src/themes/bootstrap5.css.js +3 -0
  151. package/src/themes/foundation.js +569 -0
  152. package/src/themes/html.css +60 -0
  153. package/src/themes/html.css.js +3 -0
  154. package/src/themes/html.js +71 -0
  155. package/src/themes/index.js +28 -0
  156. package/src/themes/jqueryui.js +198 -0
  157. package/src/themes/materialize.js +426 -0
  158. package/src/themes/spectre.css +208 -0
  159. package/src/themes/spectre.css.js +3 -0
  160. package/src/themes/spectre.js +406 -0
  161. package/src/themes/tailwind.css +249 -0
  162. package/src/themes/tailwind.css.js +3 -0
  163. package/src/themes/tailwind.js +443 -0
  164. package/src/utilities.js +138 -0
  165. package/src/validator.js +877 -0
  166. package/src/validators/ip-validator.js +51 -0
  167. package/tests/Dockerfile +3 -0
  168. package/tests/README.md +48 -0
  169. package/tests/codeceptjs/codecept.json +42 -0
  170. package/tests/codeceptjs/constrains/if-then-else_test.js +143 -0
  171. package/tests/codeceptjs/core_test.js +217 -0
  172. package/tests/codeceptjs/editors/advanced_test.js +13 -0
  173. package/tests/codeceptjs/editors/array_any_of_test.js +50 -0
  174. package/tests/codeceptjs/editors/array_test.js +900 -0
  175. package/tests/codeceptjs/editors/button_test.js +35 -0
  176. package/tests/codeceptjs/editors/checkbox_test.js +21 -0
  177. package/tests/codeceptjs/editors/colorpicker_test.js +27 -0
  178. package/tests/codeceptjs/editors/datetime_test.js +33 -0
  179. package/tests/codeceptjs/editors/inheritance_test.js +11 -0
  180. package/tests/codeceptjs/editors/integer_test.js +84 -0
  181. package/tests/codeceptjs/editors/issues/issue-gh-812_test.js +32 -0
  182. package/tests/codeceptjs/editors/jodit_test.js +24 -0
  183. package/tests/codeceptjs/editors/multiselect_test.js +8 -0
  184. package/tests/codeceptjs/editors/number_test.js +82 -0
  185. package/tests/codeceptjs/editors/object_test.js +204 -0
  186. package/tests/codeceptjs/editors/option-no_default_values_test.js +42 -0
  187. package/tests/codeceptjs/editors/programmatic-changes_test.js +20 -0
  188. package/tests/codeceptjs/editors/radio_test.js +10 -0
  189. package/tests/codeceptjs/editors/rating_test.js +13 -0
  190. package/tests/codeceptjs/editors/select_test.js +22 -0
  191. package/tests/codeceptjs/editors/stepper_test.js +27 -0
  192. package/tests/codeceptjs/editors/string_test.js +118 -0
  193. package/tests/codeceptjs/editors/table-confirm-delete_test.js +67 -0
  194. package/tests/codeceptjs/editors/tabs_test.js +14 -0
  195. package/tests/codeceptjs/editors/uuid_test.js +21 -0
  196. package/tests/codeceptjs/editors/validation_test.js +14 -0
  197. package/tests/codeceptjs/meta-schema_test.js +17 -0
  198. package/tests/codeceptjs/schemaloader_test.js +13 -0
  199. package/tests/codeceptjs/steps.d.ts +13 -0
  200. package/tests/codeceptjs/steps_file.js +12 -0
  201. package/tests/codeceptjs/themes_test.js +519 -0
  202. package/tests/docker-compose.yml +34 -0
  203. package/tests/fixtures/basic_person.json +26 -0
  204. package/tests/fixtures/nested_object.json +26 -0
  205. package/tests/fixtures/person.json +55 -0
  206. package/tests/fixtures/recursive.json +8 -0
  207. package/tests/fixtures/some_types.json +32 -0
  208. package/tests/fixtures/string.json +3 -0
  209. package/tests/fixtures/validation.json +1140 -0
  210. package/tests/pages/_demo.html +475 -0
  211. package/tests/pages/advanced.html +137 -0
  212. package/tests/pages/anyof.html +80 -0
  213. package/tests/pages/array-anyof.html +142 -0
  214. package/tests/pages/array-checkboxes.html +41 -0
  215. package/tests/pages/array-choices.html +45 -0
  216. package/tests/pages/array-integers.html +37 -0
  217. package/tests/pages/array-move-events.html +61 -0
  218. package/tests/pages/array-multiselects.html +42 -0
  219. package/tests/pages/array-nested-arrays.html +40 -0
  220. package/tests/pages/array-numbers.html +37 -0
  221. package/tests/pages/array-objects.html +42 -0
  222. package/tests/pages/array-ratings.html +40 -0
  223. package/tests/pages/array-selectize.html +51 -0
  224. package/tests/pages/array-selects.html +36 -0
  225. package/tests/pages/array-strings.html +36 -0
  226. package/tests/pages/array.html +42 -0
  227. package/tests/pages/assets/pages.css +130 -0
  228. package/tests/pages/button-callbacks.html +77 -0
  229. package/tests/pages/checkbox-labels.html +114 -0
  230. package/tests/pages/colorpicker-no-3rd-party.html +43 -0
  231. package/tests/pages/colorpicker-use-vanilla-picker.html +50 -0
  232. package/tests/pages/core.html +118 -0
  233. package/tests/pages/datetime.html +76 -0
  234. package/tests/pages/form-name.html +108 -0
  235. package/tests/pages/grid-strict.html +311 -0
  236. package/tests/pages/grid.html +284 -0
  237. package/tests/pages/if-then-else-allOf.html +117 -0
  238. package/tests/pages/inheritance.html +76 -0
  239. package/tests/pages/integer.html +68 -0
  240. package/tests/pages/issues/_template.html +50 -0
  241. package/tests/pages/issues/issue-gh-812.html +110 -0
  242. package/tests/pages/issues/issue-gh-823-meta-schema.html +35 -0
  243. package/tests/pages/issues/issue-gh-848.html +81 -0
  244. package/tests/pages/meta_schema.json +705 -0
  245. package/tests/pages/number.html +89 -0
  246. package/tests/pages/object-no-additional-properties.html +65 -0
  247. package/tests/pages/object-no-duplicated-id.html +68 -0
  248. package/tests/pages/object-required-properties.html +236 -0
  249. package/tests/pages/object-with-dependencies-array.html +46 -0
  250. package/tests/pages/object-with-dependencies.html +60 -0
  251. package/tests/pages/object.html +79 -0
  252. package/tests/pages/oneof.html +103 -0
  253. package/tests/pages/option-no_default_values.html +58 -0
  254. package/tests/pages/programmatic-changes.html +120 -0
  255. package/tests/pages/read-only.html +105 -0
  256. package/tests/pages/select.html +41 -0
  257. package/tests/pages/stepper.html +59 -0
  258. package/tests/pages/string-ace-editor.html +52 -0
  259. package/tests/pages/string-cleave.html +46 -0
  260. package/tests/pages/string-custom-attributes.html +62 -0
  261. package/tests/pages/string-formats.html +52 -0
  262. package/tests/pages/string-formats2.html +57 -0
  263. package/tests/pages/string-jodit-editor.html +49 -0
  264. package/tests/pages/string-sceditor.html +62 -0
  265. package/tests/pages/table-move-events.html +56 -0
  266. package/tests/pages/table.html +46 -0
  267. package/tests/pages/tabs.html +131 -0
  268. package/tests/pages/themes.html +527 -0
  269. package/tests/pages/translate-property.html +247 -0
  270. package/tests/pages/urn.html +93 -0
  271. package/tests/pages/uuid.html +72 -0
  272. package/tests/pages/validation.html +99 -0
  273. package/tests/unit/.eslintrc +8 -0
  274. package/tests/unit/core.spec.js +309 -0
  275. package/tests/unit/defaults.spec.js +40 -0
  276. package/tests/unit/editor.spec.js +160 -0
  277. package/tests/unit/editors/array.spec.js +86 -0
  278. package/tests/unit/editors/object.spec.js +79 -0
  279. package/tests/unit/editors/table.spec.js +91 -0
  280. package/tests/unit/readme.md +35 -0
  281. package/tests/unit/schemaloader.spec.js +498 -0
  282. package/tests/unit/validator.spec.js +94 -0
  283. package/tests/unit/validators/ip-validator.spec.js +62 -0
@@ -0,0 +1,49 @@
1
+ import { AbstractIconLib } from '../iconlib.js'
2
+
3
+ const iconClass = 'material-icons'
4
+ const iconPrefix = ''
5
+ const mapping = {
6
+ collapse: 'arrow_drop_up',
7
+ expand: 'arrow_drop_down',
8
+ delete: 'delete',
9
+ edit: 'edit',
10
+ add: 'add',
11
+ subtract: 'remove',
12
+ cancel: 'cancel',
13
+ save: 'save',
14
+ moveup: 'arrow_upward',
15
+ movedown: 'arrow_downward',
16
+ moveright: 'arrow_forward',
17
+ moveleft: 'arrow_back',
18
+ copy: 'content_copy',
19
+ clear: 'highlight_off',
20
+ time: 'access_time',
21
+ calendar: 'calendar_today',
22
+ upload: 'cloud_upload',
23
+ edit_properties: 'list'
24
+ }
25
+
26
+ export class materialiconsIconlib extends AbstractIconLib {
27
+ constructor () {
28
+ super(iconPrefix, mapping)
29
+ this.icon_class = iconClass
30
+ }
31
+
32
+ getIconClass (key) {
33
+ /* This method is unused. */
34
+ return this.icon_class
35
+ }
36
+
37
+ getIcon (key) {
38
+ /* Get the mapping. */
39
+ const mapping = this.mapping[key]
40
+ if (!mapping) return null
41
+
42
+ /* @see http://materializecss.com/icons.html */
43
+ const i = document.createElement('i')
44
+ i.classList.add(this.icon_class)
45
+ const t = document.createTextNode(mapping)
46
+ i.appendChild(t)
47
+ return i
48
+ }
49
+ }
@@ -0,0 +1,28 @@
1
+ import { AbstractIconLib } from '../iconlib.js'
2
+
3
+ const iconPrefix = 'oi oi-'
4
+ const mapping = {
5
+ collapse: 'collapse-down',
6
+ expand: 'expand-right',
7
+ delete: 'trash',
8
+ edit: 'pencil',
9
+ add: 'plus',
10
+ subtract: 'minus',
11
+ cancel: 'ban',
12
+ save: 'file',
13
+ moveup: 'arrow-thick-top',
14
+ moveright: 'arrow-thick-right',
15
+ movedown: 'arrow-thick-bottom',
16
+ moveleft: 'arrow-thick-left',
17
+ copy: 'clipboard',
18
+ clear: 'circle-x',
19
+ time: 'clock',
20
+ calendar: 'calendar',
21
+ edit_properties: 'list'
22
+ }
23
+
24
+ export class openiconicIconlib extends AbstractIconLib {
25
+ constructor () {
26
+ super(iconPrefix, mapping)
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ import { AbstractIconLib } from '../iconlib.js'
2
+
3
+ const iconPrefix = 'icon icon-'
4
+ const mapping = {
5
+ collapse: 'arrow-down',
6
+ expand: 'arrow-right',
7
+ delete: 'delete',
8
+ edit: 'edit',
9
+ add: 'plus',
10
+ subtract: 'minus',
11
+ cancel: 'cross',
12
+ save: 'check',
13
+ moveup: 'upward',
14
+ moveright: 'forward',
15
+ movedown: 'downward',
16
+ moveleft: 'back',
17
+ copy: 'copy',
18
+ clear: 'close',
19
+ time: 'time',
20
+ calendar: 'bookmark',
21
+ edit_properties: 'menu'
22
+ }
23
+
24
+ export class spectreIconlib extends AbstractIconLib {
25
+ constructor () {
26
+ super(iconPrefix, mapping)
27
+ }
28
+ }
@@ -0,0 +1,128 @@
1
+ /* Use "multiple" as a fall back for everything */
2
+ const defaultResolver = schema => typeof schema.type !== 'string' && 'multiple'
3
+
4
+ /* If the type is not set but properties are defined, we can infer the type is actually object */
5
+ const object = schema => !schema.type && schema.properties && 'object'
6
+
7
+ /* If the type is set and it's a basic type, use the primitive editor */
8
+ const primitive = schema => typeof schema.type === 'string' && schema.type
9
+
10
+ /* Use specialized editor for signatures */
11
+ const signature = schema => schema.type === 'string' && schema.format === 'signature' && 'signature'
12
+
13
+ /* Use the select editor for all boolean values */
14
+ const boolean = schema => {
15
+ if (schema.type === 'boolean') {
16
+ /* If explicitly set to 'checkbox', use that */
17
+ if (schema.format === 'checkbox' || (schema.options && schema.options.checkbox)) return 'checkbox'
18
+ /* Otherwise, default to select menu */
19
+ if (schema.format === 'select2') return 'select2'
20
+ if (schema.format === 'selectize') return 'selectize'
21
+ if (schema.format === 'choices') return 'choices'
22
+ return 'select'
23
+ }
24
+ }
25
+
26
+ /* Use the multiple editor for schemas where the `type` is set to "any" */
27
+ const any = schema => schema.type === 'any' && 'multiple'
28
+
29
+ /* Editor for base64 encoded files */
30
+ const base64 = schema => schema.type === 'string' && schema.media && schema.media.binaryEncoding === 'base64' && 'base64'
31
+
32
+ /* Editor for uploading files */
33
+ const upload = schema => schema.type === 'string' && schema.format === 'url' && window.FileReader && schema.options && schema.options.upload === Object(schema.options.upload) && 'upload'
34
+
35
+ /* Use the table editor for arrays with the format set to `table` */
36
+ const table = schema => schema.type === 'array' && schema.format === 'table' && 'table'
37
+
38
+ /* Use the `select` editor for dynamic enumSource enums */
39
+ const enumSource = schema => {
40
+ if (schema.enumSource) {
41
+ if (schema.format === 'radio') return 'radio'
42
+ if (schema.format === 'select2') return 'select2'
43
+ if (schema.format === 'selectize') return 'selectize'
44
+ if (schema.format === 'choices') return 'choices'
45
+ return 'select'
46
+ }
47
+ }
48
+
49
+ /* Use the `enum` or `select` editors for schemas with enumerated properties */
50
+ const enumeratedProperties = schema => {
51
+ if (schema.enum) {
52
+ if (schema.type === 'array' || schema.type === 'object') return 'enum'
53
+ if (schema.type === 'number' || schema.type === 'integer' || schema.type === 'string') {
54
+ if (schema.format === 'radio') return 'radio'
55
+ if (schema.format === 'select2') return 'select2'
56
+ if (schema.format === 'selectize') return 'selectize'
57
+ if (schema.format === 'choices') return 'choices'
58
+ return 'select'
59
+ }
60
+ }
61
+ }
62
+
63
+ /* Specialized editors for arrays of strings */
64
+ const arraysOfStrings = schema => {
65
+ if (schema.type === 'array' && schema.items && !(Array.isArray(schema.items)) && ['string', 'number', 'integer'].includes(schema.items.type)) {
66
+ if (schema.format === 'choices') return 'arrayChoices'
67
+ if (schema.uniqueItems) {
68
+ /* if 'selectize' enabled it is expected to be selectized control */
69
+ if (schema.format === 'selectize') return 'arraySelectize'
70
+ if (schema.format === 'select2') return 'arraySelect2'
71
+ if (schema.items.enum) return 'multiselect' /* otherwise it is select */
72
+ }
73
+ }
74
+ }
75
+
76
+ /* Use the multiple editor for schemas with `oneOf` or `anyOf` set */
77
+ const oneOf = schema => (schema.oneOf || schema.anyOf) && 'multiple'
78
+
79
+ /* Use the multiple editor for schemas with `if` set */
80
+ const ifThenElse = schema => (schema.if) && 'multiple'
81
+
82
+ /* Specialized editor for date, time and datetime-local formats */
83
+ const date = schema => ['string', 'integer'].includes(schema.type) && ['date', 'time', 'datetime-local'].includes(schema.format) && 'datetime'
84
+
85
+ /* Use a specialized editor for starratings */
86
+ const starratings = schema => ['string', 'integer'].includes(schema.type) && ['starrating', 'rating'].includes(schema.format) && 'starrating'
87
+
88
+ /* Hyper-link describeBy resolver */
89
+ const describeBy = schema => {
90
+ if (schema.links) {
91
+ for (let i = 0; i < schema.links.length; i++) {
92
+ if (schema.links[i].rel && schema.links[i].rel.toLowerCase() === 'describedby') return 'describedBy'
93
+ }
94
+ }
95
+ }
96
+
97
+ /* Use the stepper editor for schemas with type `number` or `integer` and format `stepper` */
98
+ const stepper = schema => {
99
+ if ((schema.type === 'integer' || schema.type === 'number') && schema.format === 'stepper') {
100
+ return 'stepper'
101
+ }
102
+ }
103
+
104
+ /* Enable custom editor type */
105
+ const button = schema => schema.format === 'button' && 'button'
106
+
107
+ const info = schema => schema.format === 'info' && 'info'
108
+
109
+ const uuid = schema => schema.type === 'string' && schema.format === 'uuid' && 'uuid'
110
+
111
+ const autoComplete = schema => schema.type === 'string' && schema.format === 'autocomplete' && 'autocomplete'
112
+
113
+ const jodit = schema => schema.type === 'string' && schema.format === 'jodit' && 'jodit'
114
+
115
+ const markdown = schema => schema.type === 'string' && schema.format === 'markdown' && 'simplemde'
116
+
117
+ const xhtml = schema => schema.type === 'string' && ['xhtml', 'bbcode'].includes(schema.format) && 'sceditor'
118
+
119
+ /* Use the ace editor for schemas with format equals any of ace editor modes */
120
+ const aceModes = ['actionscript', 'batchfile', 'c', 'c++', 'cpp', 'coffee', 'csharp', 'css', 'dart', 'django', 'ejs', 'erlang', 'golang', 'groovy', 'handlebars', 'haskell', 'haxe', 'html', 'ini', 'jade', 'java', 'javascript', 'json', 'less', 'lisp', 'lua', 'makefile', 'matlab', 'mysql', 'objectivec', 'pascal', 'perl', 'pgsql', 'php', 'python', 'r', 'ruby', 'sass', 'scala', 'scss', 'smarty', 'sql', 'sqlserver', 'stylus', 'svg', 'twig', 'vbscript', 'xml', 'yaml']
121
+ const ace = schema => schema.type === 'string' && aceModes.includes(schema.format) && 'ace'
122
+
123
+ const ip = schema => schema.type === 'string' && ['ip', 'ipv4', 'ipv6', 'hostname'].includes(schema.format) && 'ip'
124
+
125
+ const colorPicker = schema => schema.type === 'string' && schema.format === 'color' && 'colorpicker'
126
+
127
+ /* Export resolvers in order of discovery, first to last */
128
+ export const resolvers = [colorPicker, ip, ace, xhtml, markdown, jodit, autoComplete, uuid, info, button, stepper, describeBy, starratings, date, oneOf, ifThenElse, arraysOfStrings, enumeratedProperties, enumSource, table, upload, base64, any, boolean, signature, primitive, object, defaultResolver]
@@ -0,0 +1,408 @@
1
+ import { extend, hasOwnProperty } from './utilities.js'
2
+
3
+ export class SchemaLoader {
4
+ constructor (options) {
5
+ this.options = options || {}
6
+ this.refs = this.options.refs || {}
7
+ this.refs_with_info = {}
8
+ this.refs_prefix = '#/counter/'
9
+ this.refs_counter = 1
10
+
11
+ this._subSchema1 = {
12
+ /* Version 3 `type` */
13
+ type (schema) {
14
+ if (typeof schema.type === 'object') {
15
+ schema.type = this._expandSubSchema(schema.type)
16
+ }
17
+ },
18
+ /* Version 3 `disallow` */
19
+ disallow (schema) {
20
+ if (typeof schema.disallow === 'object') {
21
+ schema.disallow = this._expandSubSchema(schema.disallow)
22
+ }
23
+ },
24
+ /* Version 4 `anyOf` */
25
+ anyOf (schema) {
26
+ Object.entries(schema.anyOf).forEach(([key, value]) => {
27
+ schema.anyOf[key] = this.expandSchema(value)
28
+ })
29
+ },
30
+ /* Version 4 `dependencies` (schema dependencies) */
31
+ dependencies (schema) {
32
+ Object.entries(schema.dependencies).forEach(([key, value]) => {
33
+ if (typeof value === 'object' && !(Array.isArray(value))) {
34
+ schema.dependencies[key] = this.expandSchema(value)
35
+ }
36
+ })
37
+ },
38
+ /* Version 4 `not` */
39
+ not (schema) {
40
+ schema.not = this.expandSchema(schema.not)
41
+ }
42
+ }
43
+
44
+ this._subSchema2 = {
45
+ /* allOf schemas should be merged into the parent */
46
+ allOf (schema, extended) {
47
+ let _extended = extend({}, extended)
48
+ Object.entries(schema.allOf).forEach(([key, value]) => {
49
+ schema.allOf[key] = this.expandRefs(value, true)
50
+ _extended = this.extendSchemas(_extended, this.expandSchema(value))
51
+ })
52
+ delete _extended.allOf
53
+ return _extended
54
+ },
55
+ /* extends schemas should be merged into parent */
56
+ extends (schema, extended) {
57
+ let _extended
58
+ /* If extends is a schema */
59
+ if (!(Array.isArray(schema.extends))) {
60
+ _extended = this.extendSchemas(extended, this.expandSchema(schema.extends))
61
+ } else {
62
+ /* If extends is an array of schemas */
63
+ _extended = schema.extends.reduce((e, s, i) => {
64
+ return this.extendSchemas(e, this.expandSchema(s))
65
+ }, extended)
66
+ }
67
+ delete _extended.extends
68
+ return _extended
69
+ },
70
+ /* parent should be merged into oneOf schemas */
71
+ oneOf (schema, extended) {
72
+ const tmp = extend({}, extended)
73
+ delete tmp.oneOf
74
+ schema.oneOf.reduce((e, s, i) => {
75
+ e.oneOf[i] = this.extendSchemas(this.expandSchema(s), tmp)
76
+ return e
77
+ }, extended)
78
+ return extended
79
+ }
80
+ }
81
+ }
82
+
83
+ load (schema, callback, fetchUrl, location) {
84
+ this._loadExternalRefs(schema, () => {
85
+ this._getDefinitions(schema, `${fetchUrl}#/definitions/`)
86
+ callback(this.expandRefs(schema))
87
+ }, fetchUrl, this._getFileBase(location))
88
+ }
89
+
90
+ expandRefs (schema, recurseAllOf) {
91
+ if (!schema.$ref) return schema
92
+ const _schema = extend({}, schema)
93
+
94
+ const refObj = this.refs_with_info[_schema.$ref]
95
+ delete _schema.$ref
96
+ const fetchUrl = refObj.$ref.startsWith('#')
97
+ ? refObj.fetchUrl
98
+ : ''
99
+ const ref = this._getRef(fetchUrl, refObj)
100
+ if (!this.refs[ref]) { /* if reference not found */
101
+ // eslint-disable-next-line no-console
102
+ console.warn(`reference:'${ref}' not found!`)
103
+ } else if (recurseAllOf && hasOwnProperty(this.refs[ref], 'allOf')) {
104
+ const allOf = this.refs[ref].allOf
105
+ Object.keys(allOf).forEach(key => {
106
+ allOf[key] = this.expandRefs(allOf[key], true)
107
+ })
108
+ }
109
+
110
+ return this.extendSchemas(_schema, this.expandSchema(this.refs[ref]))
111
+ }
112
+
113
+ expandSchema (schema, fileBase) {
114
+ Object.entries(this._subSchema1).forEach(([key, func]) => {
115
+ if (schema[key]) {
116
+ func.call(this, schema)
117
+ }
118
+ })
119
+
120
+ let extended = extend({}, schema)
121
+
122
+ Object.entries(this._subSchema2).forEach(([key, func]) => {
123
+ if (schema[key]) {
124
+ extended = func.call(this, schema, extended)
125
+ }
126
+ })
127
+
128
+ return this.expandRefs(extended)
129
+ }
130
+
131
+ _getRef (fetchUrl, refObj) {
132
+ const ref = fetchUrl + refObj
133
+
134
+ return this.refs[ref] ? ref : fetchUrl + decodeURIComponent(refObj.$ref)
135
+ }
136
+
137
+ _expandSubSchema (subschema) {
138
+ /* Array of types */
139
+ if (Array.isArray(subschema)) return subschema.map(m => typeof m === 'object' ? this.expandSchema(m) : m)
140
+
141
+ /* Schema */
142
+ return this.expandSchema(subschema)
143
+ }
144
+
145
+ _getDefinitions (schema, path) {
146
+ if (schema.definitions) {
147
+ Object.keys(schema.definitions).forEach(i => {
148
+ this.refs[path + i] = schema.definitions[i]
149
+ if (schema.definitions[i].definitions) {
150
+ this._getDefinitions(schema.definitions[i], `${path + i}/definitions/`)
151
+ }
152
+ })
153
+ }
154
+ }
155
+
156
+ _getExternalRefs (schema, fetchUrl) {
157
+ const refs = {}
158
+ const mergeRefs = newrefs => Object.keys(newrefs).forEach(i => { refs[i] = true })
159
+
160
+ if (schema.$ref && typeof schema.$ref !== 'object') {
161
+ const refCounter = this.refs_prefix + this.refs_counter++
162
+ if (schema.$ref.substr(0, 1) !== '#' && !this.refs[schema.$ref]) {
163
+ refs[schema.$ref] = true
164
+ }
165
+ this.refs_with_info[refCounter] = { fetchUrl, $ref: schema.$ref }
166
+ schema.$ref = refCounter
167
+ }
168
+
169
+ Object.values(schema).forEach(value => {
170
+ if (!value || typeof value !== 'object') return
171
+ if (Array.isArray(value)) {
172
+ Object.values(value).forEach(e => {
173
+ if (e && typeof e === 'object') {
174
+ mergeRefs(this._getExternalRefs(e, fetchUrl))
175
+ }
176
+ })
177
+ } else {
178
+ mergeRefs(this._getExternalRefs(value, fetchUrl))
179
+ }
180
+ })
181
+
182
+ if (schema.id && typeof schema.id === 'string' && schema.id.substr(0, 4) === 'urn:') {
183
+ this.refs[schema.id] = schema
184
+ } else if (schema.$id && typeof schema.$id === 'string' && schema.$id.substr(0, 4) === 'urn:') {
185
+ this.refs[schema.$id] = schema
186
+ }
187
+
188
+ return refs
189
+ }
190
+
191
+ _getFileBase (location) {
192
+ if (!location) return '/'
193
+
194
+ const { ajaxBase } = this.options
195
+
196
+ return typeof ajaxBase === 'undefined' ? this._getFileBaseFromFileLocation(location) : ajaxBase
197
+ }
198
+
199
+ _getFileBaseFromFileLocation (fileLocationString) {
200
+ const pathItems = fileLocationString.split('/')
201
+ pathItems.pop()
202
+ return `${pathItems.join('/')}/`
203
+ }
204
+
205
+ _joinUrl (url, fileBase) {
206
+ var fetchUrl = url
207
+
208
+ if (url.substr(0, 7) !== 'http://' &&
209
+ url.substr(0, 8) !== 'https://' &&
210
+ url.substr(0, 5) !== 'blob:' &&
211
+ url.substr(0, 5) !== 'data:' &&
212
+ url.substr(0, 1) !== '#' &&
213
+ url.substr(0, 1) !== '/'
214
+ ) {
215
+ fetchUrl = fileBase + url
216
+ }
217
+
218
+ // strip #fragment from URI, so json pointers resolve correctly #928
219
+ if (fetchUrl.indexOf('#') > 0) fetchUrl = fetchUrl.substr(0, fetchUrl.indexOf('#'))
220
+
221
+ return fetchUrl
222
+ }
223
+
224
+ _isUniformResourceName (uri) {
225
+ return uri.substr(0, 4) === 'urn:'
226
+ }
227
+
228
+ _loadExternalRefs (schema, callback, fetchUrl, fileBase) {
229
+ const refs = this._getExternalRefs(schema, fetchUrl)
230
+ let done = false; let waiting = 0
231
+
232
+ Object.keys(refs).forEach(uri => {
233
+ if (this.refs[uri]) return
234
+
235
+ if (this._isUniformResourceName(uri)) {
236
+ this.refs[uri] = 'loading'
237
+ waiting++
238
+
239
+ const urnResolver = this.options.urn_resolver
240
+ let urn = uri
241
+ if (typeof urnResolver !== 'function') {
242
+ // eslint-disable-next-line no-console
243
+ console.log(`No "urn_resolver" callback defined to resolve "${urn}"`)
244
+ throw new Error(`Must set urn_resolver option to a callback to resolve ${urn}`)
245
+ }
246
+ // theoretically a URN can contain a JSON pointer
247
+ if (urn.indexOf('#') > 0) urn = urn.substr(0, urn.indexOf('#'))
248
+ let response
249
+ try {
250
+ response = urnResolver(urn, responseText => {
251
+ try {
252
+ schema = JSON.parse(responseText)
253
+ } catch (e) {
254
+ // eslint-disable-next-line no-console
255
+ console.log(e)
256
+ throw new Error(`Failed to parse external ref ${urn}`)
257
+ }
258
+ if (!(typeof schema === 'boolean' || typeof schema === 'object') || schema === null || Array.isArray(schema)) {
259
+ throw new Error(`External ref does not contain a valid schema - ${urn}`)
260
+ }
261
+ this.refs[uri] = schema
262
+ this._getDefinitions(schema, `${urn}#/definitions/`)
263
+ this._loadExternalRefs(schema, () => {
264
+ waiting--
265
+ if (done && !waiting) {
266
+ callback()
267
+ }
268
+ }, uri, '/')
269
+ })
270
+ } catch (e) {
271
+ // eslint-disable-next-line no-console
272
+ console.log(e)
273
+ throw new Error(`Failed to parse external ref ${urn}`)
274
+ }
275
+
276
+ if (typeof response !== 'boolean') {
277
+ throw new Error(`External ref does not contain a valid schema - ${urn}`)
278
+ } else if (response !== true) {
279
+ throw new Error(`External ref did not resolve - ${urn}`)
280
+ }
281
+
282
+ return
283
+ }
284
+
285
+ if (!this.options.ajax) throw new Error(`Must set ajax option to true to load external ref ${uri}`)
286
+ this.refs[uri] = 'loading'
287
+ waiting++
288
+ let url = this._joinUrl(uri, fileBase)
289
+
290
+ const r = new XMLHttpRequest()
291
+ r.overrideMimeType('application/json')
292
+ r.open('GET', url, true)
293
+ if (this.options.ajaxCredentials) r.withCredentials = this.options.ajaxCredentials
294
+ r.onreadystatechange = () => {
295
+ if (r.readyState !== 4) return
296
+ /* Request succeeded */
297
+ if (r.status === 200) {
298
+ let schema
299
+ try {
300
+ schema = JSON.parse(r.responseText)
301
+ } catch (e) {
302
+ // eslint-disable-next-line no-console
303
+ console.log(e)
304
+ throw new Error(`Failed to parse external ref ${url}`)
305
+ }
306
+ if (!(typeof schema === 'boolean' || typeof schema === 'object') || schema === null || Array.isArray(schema)) {
307
+ throw new Error(`External ref does not contain a valid schema - ${url}`)
308
+ }
309
+
310
+ this.refs[uri] = schema
311
+ const fileBase = this._getFileBaseFromFileLocation(url)
312
+
313
+ // add leading slash
314
+ if (url !== uri) {
315
+ const pathItems = url.split('/')
316
+ url = (uri.substr(0, 1) === '/' ? '/' : '') + pathItems.pop()
317
+ }
318
+
319
+ this._getDefinitions(schema, `${url}#/definitions/`)
320
+ this._loadExternalRefs(schema, () => {
321
+ waiting--
322
+ if (done && !waiting) {
323
+ callback()
324
+ }
325
+ }, url, fileBase)
326
+ } else {
327
+ /* Request failed */
328
+ // eslint-disable-next-line no-console
329
+ console.log(r)
330
+ throw new Error(`Failed to fetch ref via ajax - ${uri}`)
331
+ }
332
+ }
333
+ r.send()
334
+ })
335
+
336
+ done = true
337
+ if (!waiting) {
338
+ callback()
339
+ }
340
+ }
341
+
342
+ extendSchemas (obj1, obj2) {
343
+ obj1 = extend({}, obj1)
344
+ obj2 = extend({}, obj2)
345
+
346
+ const extended = {}
347
+ const isRequiredOrDefaultProperties = (prop, val) => (prop === 'required' || prop === 'defaultProperties') && typeof val === 'object' && Array.isArray(val)
348
+ const merge = (prop, val) => {
349
+ /* Required and defaultProperties arrays should be unioned together */
350
+ if (isRequiredOrDefaultProperties(prop, val)) {
351
+ /* Union arrays and unique */
352
+ extended[prop] = val.concat(obj2[prop]).reduce((p, c) => {
353
+ if (!p.includes(c)) p.push(c)
354
+ return p
355
+ }, [])
356
+ } else if (prop === 'type' && (typeof val === 'string' || Array.isArray(val))) {
357
+ mergeType(val)
358
+ } else if (typeof val === 'object' && !Array.isArray(val) && val !== null) {
359
+ /* Objects should be recursively merged */
360
+ extended[prop] = this.extendSchemas(val, obj2[prop])
361
+ } else {
362
+ /* Otherwise, use the first value */
363
+ extended[prop] = val
364
+ }
365
+ }
366
+
367
+ const mergeType = (val) => {
368
+ /* Type should be intersected and is either an array or string */
369
+ /* Make sure we're dealing with arrays */
370
+ if (typeof val === 'string') val = [val]
371
+ if (typeof obj2.type === 'string') obj2.type = [obj2.type]
372
+
373
+ /* If type is only defined in the first schema, keep it */
374
+ if (!obj2.type || !obj2.type.length) {
375
+ extended.type = val
376
+ } else {
377
+ /* If type is defined in both schemas, do an intersect */
378
+ extended.type = val.filter(n => obj2.type.includes(n))
379
+ }
380
+
381
+ /* If there's only 1 type and it's a primitive, use a string instead of array */
382
+ if (extended.type.length === 1 && typeof extended.type[0] === 'string') {
383
+ extended.type = extended.type[0]
384
+ } else if (extended.type.length === 0) {
385
+ /* Remove the type property if it's empty */
386
+ delete extended.type
387
+ }
388
+ }
389
+
390
+ Object.entries(obj1).forEach(([prop, val]) => {
391
+ /* If this key is also defined in obj2, merge them */
392
+ if (typeof obj2[prop] !== 'undefined') {
393
+ merge(prop, val)
394
+ } else {
395
+ /* Otherwise, just use the one in obj1 */
396
+ extended[prop] = val
397
+ }
398
+ })
399
+
400
+ /* Properties in obj2 that aren't in obj1 */
401
+ Object.entries(obj2).forEach(([prop, val]) => {
402
+ if (typeof obj1[prop] === 'undefined') {
403
+ extended[prop] = val
404
+ }
405
+ })
406
+ return extended
407
+ }
408
+ }