adapt-project 1.0.0

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.
@@ -0,0 +1,295 @@
1
+ import path from 'path'
2
+ import JSONFile from './JSONFile.js'
3
+ import Data from './Data.js'
4
+ import Translate from './Translate.js'
5
+ import Plugins from './Plugins.js'
6
+ import Schemas from './Schemas.js'
7
+
8
+ /**
9
+ * @typedef {import('./JSONFileItem')} JSONFileItem
10
+ */
11
+
12
+ /**
13
+ * The class represents an Adapt Framework root directory. It provides APIs for
14
+ * plugins, schemas, data and translations.
15
+ */
16
+ class Framework {
17
+ /**
18
+ * @param {Object} options
19
+ * @param {string} options.rootPath
20
+ * @param {string} options.outputPath
21
+ * @param {string} options.sourcePath
22
+ * @param {function} options.includedFilter
23
+ * @param {string} options.jsonext
24
+ * @param {string} options.trackingIdType,
25
+ * @param {boolean} options.useOutputData
26
+ * @param {function} options.log
27
+ * @param {function} options.warn
28
+ */
29
+ constructor ({
30
+ rootPath = process.cwd(),
31
+ outputPath = path.join(rootPath, '/build/'),
32
+ sourcePath = path.join(rootPath, '/src/'),
33
+ courseDir = 'course',
34
+ includedFilter = function () { return true },
35
+ jsonext = 'json',
36
+ trackingIdType = 'block',
37
+ useOutputData = false,
38
+ log = console.log,
39
+ warn = console.warn
40
+ } = {}) {
41
+ /** @type {string} */
42
+ this.rootPath = rootPath.replace(/\\/g, '/')
43
+ /** @type {string} */
44
+ this.outputPath = path.resolve(this.rootPath, outputPath).replace(/\\/g, '/').replace(/\/?$/, '/')
45
+ /** @type {string} */
46
+ this.sourcePath = path.resolve(this.rootPath, sourcePath).replace(/\\/g, '/').replace(/\/?$/, '/')
47
+ /** @type {string} */
48
+ this.courseDir = courseDir
49
+ /** @type {function} */
50
+ this.includedFilter = includedFilter
51
+ /** @type {string} */
52
+ this.jsonext = jsonext
53
+ /** @type {string} */
54
+ this.trackingIdType = trackingIdType
55
+ /** @type {boolean} */
56
+ this.useOutputData = useOutputData
57
+ /** @type {function} */
58
+ this.log = log
59
+ /** @type {function} */
60
+ this.warn = warn
61
+ /** @type {JSONFile} */
62
+ this.packageJSONFile = null
63
+ }
64
+
65
+ /** @returns {Framework} */
66
+ load () {
67
+ this.packageJSONFile = new JSONFile({
68
+ framework: this,
69
+ path: path.join(this.rootPath, 'package.json').replace(/\\/g, '/')
70
+ })
71
+ this.packageJSONFile.load()
72
+ return this
73
+ }
74
+
75
+ /** @returns {JSONFileItem} */
76
+ getPackageJSONFileItem () {
77
+ return this.packageJSONFile.firstFileItem
78
+ }
79
+
80
+ /** @returns {string} */
81
+ get version () {
82
+ return this.getPackageJSONFileItem().item.version
83
+ }
84
+
85
+ /**
86
+ * Returns a Data instance for either the src/course or build/course folder
87
+ * depending on the specification of the useOutputData property on either the
88
+ * function or the Framework instance.
89
+ * @returns {Data}
90
+ */
91
+ getData ({
92
+ useOutputData = this.useOutputData,
93
+ performLoad = true
94
+ } = {}) {
95
+ const data = new Data({
96
+ framework: this,
97
+ sourcePath: useOutputData ? this.outputPath : this.sourcePath,
98
+ courseDir: this.courseDir,
99
+ jsonext: this.jsonext,
100
+ trackingIdType: this.trackingIdType,
101
+ log: this.log
102
+ })
103
+ if (performLoad) data.load()
104
+ return data
105
+ }
106
+
107
+ /** @returns {Plugins} */
108
+ getPlugins ({
109
+ includedFilter = this.includedFilter
110
+ } = {}) {
111
+ const plugins = new Plugins({
112
+ framework: this.framework,
113
+ includedFilter,
114
+ sourcePath: this.sourcePath,
115
+ log: this.log,
116
+ warn: this.warn
117
+ })
118
+ plugins.load()
119
+ return plugins
120
+ }
121
+
122
+ /** @returns {Schemas} */
123
+ getSchemas ({
124
+ includedFilter = this.includedFilter
125
+ } = {}) {
126
+ const schemas = new Schemas({
127
+ framework: this,
128
+ includedFilter,
129
+ sourcePath: this.sourcePath,
130
+ log: this.log
131
+ })
132
+ schemas.load()
133
+ return schemas
134
+ }
135
+
136
+ /** @returns {Translate} */
137
+ getTranslate ({
138
+ includedFilter = this.includedFilter,
139
+ masterLang = 'en',
140
+ targetLang = null,
141
+ format = 'csv',
142
+ csvDelimiter = ',',
143
+ shouldReplaceExisting = false,
144
+ languagePath = '',
145
+ isTest = false
146
+ } = {}) {
147
+ const translate = new Translate({
148
+ framework: this,
149
+ includedFilter,
150
+ masterLang,
151
+ targetLang,
152
+ format,
153
+ csvDelimiter,
154
+ shouldReplaceExisting,
155
+ jsonext: this.jsonext,
156
+ sourcePath: this.sourcePath,
157
+ languagePath,
158
+ outputPath: this.outputPath,
159
+ courseDir: this.courseDir,
160
+ useOutputData: this.useOutputData,
161
+ isTest,
162
+ log: this.log,
163
+ warn: this.warn
164
+ })
165
+ translate.load()
166
+ return translate
167
+ }
168
+
169
+ /** @returns {Framework} */
170
+ applyGlobalsDefaults ({
171
+ includedFilter = this.includedFilter,
172
+ useOutputData = this.useOutputData,
173
+ schemas = this.getSchemas({
174
+ includedFilter
175
+ }),
176
+ data = this.getData(useOutputData)
177
+ } = {}) {
178
+ const courseSchema = schemas.getCourseSchema()
179
+ data.languages.forEach(language => {
180
+ const { file, item: course } = language.getCourseFileItem()
181
+ course._globals = courseSchema.applyDefaults(course._globals, '_globals')
182
+ file.changed()
183
+ })
184
+ data.save()
185
+ return this
186
+ }
187
+
188
+ /** @returns {Framework} */
189
+ applyScreenSizeDefaults ({
190
+ includedFilter = this.includedFilter,
191
+ useOutputData = this.useOutputData,
192
+ schemas = this.getSchemas({
193
+ includedFilter
194
+ }),
195
+ data = this.getData(useOutputData)
196
+ } = {}) {
197
+ const configSchema = schemas.getConfigSchema()
198
+ const { file, item: config } = data.getConfigFileItem()
199
+ config.screenSize = configSchema.applyDefaults(config.screenSize, 'screenSize')
200
+ file.changed()
201
+ data.save()
202
+ return this
203
+ }
204
+
205
+ /**
206
+ * Creates an includedFilter function based on config.build.includes and
207
+ * config.build.excludes from the course config.json. Automatically resolves
208
+ * plugin dependencies found in plugin bower.json / package.json files.
209
+ * @returns {function} A filter function: (sourcePath: string) => boolean
210
+ */
211
+ makeIncludeFilter () {
212
+ const data = this.getData()
213
+ const configFileItem = data.getConfigFileItem()
214
+ const buildConfig = (configFileItem && configFileItem.item && configFileItem.item.build) || {}
215
+ const buildIncludes = buildConfig.includes && buildConfig.includes.length ? buildConfig.includes : null
216
+ const buildExcludes = buildConfig.excludes && buildConfig.excludes.length ? buildConfig.excludes : null
217
+
218
+ if (!buildIncludes && !buildExcludes) {
219
+ return function () { return true }
220
+ }
221
+
222
+ // Resolve plugin dependencies for includes
223
+ let resolvedIncludes = null
224
+ if (buildIncludes) {
225
+ const allPlugins = this.getPlugins({ includedFilter: () => true })
226
+ const dependencies = []
227
+
228
+ allPlugins.plugins.forEach(plugin => {
229
+ if (!buildIncludes.includes(plugin.name)) return
230
+ const packageData = plugin.packageJSONFile.firstFileItem.item
231
+ const deps = packageData.dependencies
232
+ if (!deps || typeof deps !== 'object') return
233
+ Object.keys(deps).forEach(depName => {
234
+ if (!buildIncludes.includes(depName) && !dependencies.includes(depName)) {
235
+ dependencies.push(depName)
236
+ }
237
+ })
238
+ })
239
+
240
+ resolvedIncludes = [].concat(buildIncludes, dependencies)
241
+ }
242
+
243
+ // Build regex patterns
244
+ const pluginTypes = ['components', 'extensions', 'menu', 'theme']
245
+ const sourcedir = 'src/'
246
+
247
+ let includedRegExp = null
248
+ let nestedIncludedRegExp = null
249
+ if (resolvedIncludes) {
250
+ const includePatterns = resolvedIncludes.map(plugin => {
251
+ return pluginTypes.map(type => sourcedir + type + '/' + plugin + '/').join('|')
252
+ }).join('|')
253
+ const corePattern = sourcedir + 'core/'
254
+ includedRegExp = new RegExp(corePattern + '|' + includePatterns, 'i')
255
+
256
+ const nestedPatterns = resolvedIncludes.map(plugin => {
257
+ return sourcedir + '([^/]*)/([^/]*)/' + 'less/plugins' + '/' + plugin + '/'
258
+ }).join('|')
259
+ nestedIncludedRegExp = new RegExp(nestedPatterns, 'i')
260
+ }
261
+
262
+ let excludedRegExp = null
263
+ if (buildExcludes) {
264
+ const excludePatterns = buildExcludes.map(plugin => {
265
+ return pluginTypes.map(type => sourcedir + type + '/' + plugin + '/').join('|')
266
+ }).join('|')
267
+ excludedRegExp = new RegExp(excludePatterns, 'i')
268
+ }
269
+
270
+ // Return the filter closure
271
+ return function includedFilter (pluginPath) {
272
+ pluginPath = pluginPath.replace(/\\/g, '/')
273
+
274
+ const isIncluded = resolvedIncludes ? pluginPath.search(includedRegExp) !== -1 : undefined
275
+ const isExcluded = buildExcludes ? pluginPath.search(excludedRegExp) !== -1 : false
276
+
277
+ if (isExcluded || isIncluded === false) {
278
+ return false
279
+ }
280
+
281
+ const nestedPluginsPath = !!pluginPath.match(/(?:.)+(?:\/less\/plugins)/g)
282
+ if (!nestedPluginsPath) {
283
+ return true
284
+ }
285
+
286
+ if (resolvedIncludes) {
287
+ return !!pluginPath.match(nestedIncludedRegExp)
288
+ }
289
+
290
+ return true
291
+ }
292
+ }
293
+ }
294
+
295
+ export default Framework
@@ -0,0 +1,104 @@
1
+ import fs from 'fs-extra'
2
+ import JSONFileItem from './JSONFileItem.js'
3
+
4
+ /**
5
+ * @typedef {import('./Framework')} Framework
6
+ * @typedef {import('./JSONFile')} JSONFile
7
+ */
8
+
9
+ /**
10
+ * An abstraction for centralising the loading of JSON files, keeping track of
11
+ * sub-item changes and saving changed files.
12
+ */
13
+ class JSONFile {
14
+ /**
15
+ * @param {Object} options
16
+ * @param {Framework} options.framework
17
+ * @param {string} options.path
18
+ * @param {Object|Array} options.data
19
+ * @param {boolean} options.hasChanged
20
+ */
21
+ constructor ({
22
+ framework = null,
23
+ path = null,
24
+ jsonext = null,
25
+ data = null,
26
+ hasChanged = false
27
+ } = {}) {
28
+ /** @type {Framework} */
29
+ this.framework = framework
30
+ /** @type {string} */
31
+ this.path = path
32
+ /** @type {string} */
33
+ this.jsonext = jsonext
34
+ /** @type {Object|Array} */
35
+ this.data = data
36
+ /** @type {boolean} */
37
+ this.hasChanged = hasChanged
38
+ /** @type {[JSONFileItem]} */
39
+ this.fileItems = null
40
+ }
41
+
42
+ /** @returns {JSONFile} */
43
+ load () {
44
+ this.fileItems = []
45
+
46
+ if (this.path) {
47
+ this.data = fs.readJSONSync(this.path)
48
+ }
49
+
50
+ const addObject = (item, index = null) => {
51
+ this.fileItems.push(new JSONFileItem({
52
+ framework: this.framework,
53
+ file: this,
54
+ item,
55
+ index
56
+ }))
57
+ }
58
+
59
+ if (this.data instanceof Array) {
60
+ this.data.forEach((item, index) => addObject(item, index))
61
+ } else if (this.data instanceof Object) {
62
+ addObject(this.data, null)
63
+ } else {
64
+ const err = new Error(`Cannot load json file ${this.path} as it doesn't contain an Array or Object as its root`)
65
+ err.number = 10013
66
+ throw err
67
+ }
68
+
69
+ return this
70
+ }
71
+
72
+ /**
73
+ * This is useful for files such as config.json or course.json which only have
74
+ * one item/object per file.
75
+ * @returns {JSONFileItem}
76
+ */
77
+ get firstFileItem () {
78
+ return this.fileItems && this.fileItems[0]
79
+ }
80
+
81
+ /**
82
+ * Marks this file as having changed. This should be called after changing
83
+ * the fileItems contained in this instance.
84
+ * @returns {JSONFile}
85
+ */
86
+ changed () {
87
+ this.hasChanged = true
88
+ return this
89
+ }
90
+
91
+ /**
92
+ * Saves any fileItem changes to disk.
93
+ * @return {JSONFile}
94
+ */
95
+ save () {
96
+ if (!this.hasChanged) {
97
+ return this
98
+ }
99
+ fs.writeJSONSync(this.path, this.data, { spaces: 2 })
100
+ return this
101
+ }
102
+ }
103
+
104
+ export default JSONFile
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @typedef {import('./Framework')} Framework
3
+ * @typedef {import('./JSONFile')} JSONFile
4
+ */
5
+
6
+ /**
7
+ * An abstraction for carrying JSON sub-items with their file origins and locations.
8
+ */
9
+ class JSONFileItem {
10
+ constructor ({
11
+ framework = null,
12
+ file = null,
13
+ item = null,
14
+ index = null
15
+ } = {}) {
16
+ /** @type {Framework} */
17
+ this.framework = framework
18
+ /** @type {JSONFile} */
19
+ this.file = file
20
+ /** @type {Object} */
21
+ this.item = item
22
+ /** @type {number} */
23
+ this.index = index
24
+ }
25
+ }
26
+
27
+ export default JSONFileItem
package/lib/Plugins.js ADDED
@@ -0,0 +1,82 @@
1
+ import globs from 'globs'
2
+ import Plugin from './plugins/Plugin.js'
3
+
4
+ /**
5
+ * @typedef {import('./Framework')} Framework
6
+ * @typedef {import('./JSONFileItem')} JSONFileItem
7
+ */
8
+
9
+ /**
10
+ * Represents all of the plugins in the src/ folder.
11
+ */
12
+ class Plugins {
13
+ /**
14
+ * @param {Object} options
15
+ * @param {Framework} options.framework
16
+ * @param {function} options.includedFilter
17
+ * @param {string} options.sourcePath
18
+ * @param {function} options.log
19
+ * @param {function} options.warn
20
+ */
21
+ constructor ({
22
+ framework = null,
23
+ includedFilter = function () { return true },
24
+ sourcePath = process.cwd() + '/src/',
25
+ courseDir = 'course',
26
+ log = console.log,
27
+ warn = console.warn
28
+ } = {}) {
29
+ /** @type {Framework} */
30
+ this.framework = framework
31
+ /** @type {function} */
32
+ this.includedFilter = includedFilter
33
+ /** @type {string} */
34
+ this.sourcePath = sourcePath
35
+ /** @type {string} */
36
+ this.courseDir = courseDir
37
+ /** @type {function} */
38
+ this.log = log
39
+ /** @type {function} */
40
+ this.warn = warn
41
+ /** @type {[Plugin]} */
42
+ this.plugins = []
43
+ }
44
+
45
+ /**
46
+ * Returns the locations of all plugins in the src/ folder.
47
+ * @returns {[string]}
48
+ */
49
+ get pluginLocations () {
50
+ return [
51
+ `${this.sourcePath}core/`,
52
+ `${this.sourcePath}!(core|${this.courseDir})/*/`
53
+ ]
54
+ }
55
+
56
+ /** @returns {Plugins} */
57
+ load () {
58
+ this.plugins = globs.sync(this.pluginLocations)
59
+ .filter(sourcePath => this.includedFilter(sourcePath))
60
+ .map(sourcePath => {
61
+ const plugin = new Plugin({
62
+ framework: this.framework,
63
+ sourcePath,
64
+ log: this.log,
65
+ warn: this.warn
66
+ })
67
+ plugin.load()
68
+ return plugin
69
+ })
70
+ return this
71
+ }
72
+
73
+ /** @returns {JSONFileItem} */
74
+ getAllPackageJSONFileItems () {
75
+ return this.plugins.reduce((items, plugin) => {
76
+ items.push(...plugin.packageJSONFile.fileItems)
77
+ return items
78
+ }, [])
79
+ }
80
+ }
81
+
82
+ export default Plugins
package/lib/Schemas.js ADDED
@@ -0,0 +1,208 @@
1
+ import _ from 'lodash'
2
+ import path from 'path'
3
+ import fs from 'fs-extra'
4
+ import globs from 'globs'
5
+ import ExtensionSchema from './schema/ExtensionSchema.js'
6
+ import ModelSchema from './schema/ModelSchema.js'
7
+ import ModelSchemas from './schema/ModelSchemas.js'
8
+ import Plugins from './Plugins.js'
9
+
10
+ /**
11
+ * @typedef {import('./Framework')} Framework
12
+ * @typedef {import('./Plugins')} Plugins
13
+ * @typedef {import('./plugins/Plugin')} Plugin
14
+ */
15
+
16
+ /**
17
+ * Represents all of the schemas in a course.
18
+ * @todo Work out how to do schema inheritance properly (i.e. component+accordion)
19
+ * @todo Stop deriving schema types (model/extension) from bower and/or folder paths
20
+ * @todo Stop deriving schema names from bower.json or filenames
21
+ * @todo Combining and applying multiple schemas for validation or defaults needs consideration
22
+ */
23
+ class Schemas {
24
+ /**
25
+ * @param {Object} options
26
+ * @param {Framework} options.framework
27
+ * @param {function} options.includedFilter
28
+ * @param {Plugins} options.plugins
29
+ * @param {string} options.sourcePath
30
+ * @param {function} options.log
31
+ * @param {function} options.warn
32
+ */
33
+ constructor ({
34
+ framework = null,
35
+ includedFilter = function () { return true },
36
+ plugins = null,
37
+ sourcePath = '',
38
+ log = console.log,
39
+ warn = console.warn
40
+ } = {}) {
41
+ /** @type {Framework} */
42
+ this.framework = framework
43
+ /** @type {function} */
44
+ this.includedFilter = includedFilter
45
+ /** @type {string} */
46
+ this.sourcePath = sourcePath.replace(/\\/g, '/')
47
+ /** @type {Plugins} */
48
+ this.plugins = plugins
49
+ /** @type {[Schema]]} */
50
+ this.schemas = null
51
+ /** @type {function} */
52
+ this.log = log
53
+ /** @type {function} */
54
+ this.warn = warn
55
+ }
56
+
57
+ /** @returns {Schemas} */
58
+ load () {
59
+ /**
60
+ * @param {Plugin} plugin
61
+ * @param {string} filePath
62
+ */
63
+ const createSchema = (plugin, filePath) => {
64
+ const json = fs.readJSONSync(filePath)
65
+ const isExtensionSchema = Boolean(json.properties.pluginLocations)
66
+ const InferredSchemaClass = (isExtensionSchema ? ExtensionSchema : ModelSchema)
67
+ const inferredSchemaName = (plugin.name === 'core')
68
+ ? path.parse(filePath).name.split('.')[0] // if core, get schema name from file name
69
+ : isExtensionSchema
70
+ ? plugin.name // assume schema name is plugin name
71
+ : plugin.targetAttribute // assume schema name is plugin._[type] value
72
+ return new InferredSchemaClass({
73
+ name: inferredSchemaName,
74
+ plugin,
75
+ framework: this.framework,
76
+ filePath,
77
+ globalsType: plugin.type,
78
+ targetAttribute: plugin.targetAttribute
79
+ })
80
+ }
81
+
82
+ this.plugins = new Plugins({
83
+ framework: this.framework,
84
+ includedFilter: this.includedFilter,
85
+ sourcePath: this.sourcePath,
86
+ log: this.log,
87
+ warn: this.warn
88
+ })
89
+ this.plugins.load()
90
+
91
+ this.schemas = []
92
+ this.plugins.plugins.forEach(plugin => globs.sync(plugin.schemaLocations).forEach(filePath => {
93
+ const schema = createSchema(plugin, filePath)
94
+ schema.load()
95
+ this.schemas.push(schema)
96
+ }))
97
+
98
+ this.generateCourseGlobals()
99
+ this.generateModelExtensions()
100
+
101
+ return this
102
+ }
103
+
104
+ /**
105
+ * Copy globals schema extensions from model/extension plugins to the course._globals
106
+ * schema.
107
+ * @returns {Schemas}
108
+ * @example
109
+ * courseModelSchema.properties._globals.properties._components.properties._accordion
110
+ */
111
+ generateCourseGlobals () {
112
+ const courseSchema = this.getCourseSchema()
113
+ this.schemas.forEach(schema => {
114
+ const globalsPart = schema.getCourseGlobalsPart()
115
+ if (!globalsPart) {
116
+ return
117
+ }
118
+ _.merge(courseSchema.json.properties._globals.properties, globalsPart)
119
+ })
120
+ return this
121
+ }
122
+
123
+ /**
124
+ * Copy pluginLocations schema extensions from the extension plugins to the appropriate model schemas
125
+ * @returns {Schemas}
126
+ * @example
127
+ * courseModelSchema.properties._assessment
128
+ * articleModelSchema.properties._trickle
129
+ * blockModelSchema.properties._trickle
130
+ */
131
+ generateModelExtensions () {
132
+ const extensionSchemas = this.schemas.filter(schema => schema instanceof ExtensionSchema)
133
+ extensionSchemas.forEach(schema => {
134
+ const extensionParts = schema.getModelExtensionParts()
135
+ if (!extensionParts) {
136
+ return
137
+ }
138
+ for (const modelName in extensionParts) {
139
+ const extensionPart = extensionParts[modelName]
140
+ /**
141
+ * Check if the sub-schema part has any defined properties.
142
+ * A lot of extension schemas have empty objects with no properties.
143
+ */
144
+ if (!extensionPart.properties) {
145
+ continue
146
+ }
147
+ const modelSchema = this.getModelSchemaByName(modelName)
148
+ if (!modelSchema) {
149
+ const err = new Error(`Cannot add extensions to model which doesn't exits ${modelName}`)
150
+ err.number = 10012
151
+ throw err
152
+ }
153
+ /**
154
+ * Notice that the targetAttribute is not used here, we allow the extension schema
155
+ * to define its own _[targetAttribute] to extend any core model.
156
+ */
157
+ modelSchema.json.properties = _.merge({}, modelSchema.json.properties, extensionPart.properties)
158
+ }
159
+ })
160
+ return this
161
+ }
162
+
163
+ /**
164
+ * @param {string} schemaName
165
+ * @returns {ModelSchema}
166
+ */
167
+ getModelSchemaByName (schemaName) {
168
+ const modelSchemas = this.schemas.filter(schema => schema instanceof ModelSchema)
169
+ return modelSchemas.find(({ name }) => name === schemaName)
170
+ }
171
+
172
+ /** @returns {ModelSchema} */
173
+ getCourseSchema () {
174
+ return this.getModelSchemaByName('course')
175
+ }
176
+
177
+ /** @returns {ModelSchema} */
178
+ getConfigSchema () {
179
+ return this.getModelSchemaByName('config')
180
+ }
181
+
182
+ /**
183
+ * Uses a model JSON to derive the appropriate schemas for the model.
184
+ * @param {Object} json
185
+ * @returns {ModelSchemas}
186
+ */
187
+ getSchemasForModelJSON (json) {
188
+ const schemas = []
189
+ if (json._type) {
190
+ if (json._type === 'menu' || json._type === 'page') {
191
+ schemas.push(this.getModelSchemaByName('contentobject'))
192
+ }
193
+ schemas.push(this.getModelSchemaByName(json._type))
194
+ }
195
+ if (json._component) {
196
+ schemas.push(this.getModelSchemaByName(json._component))
197
+ }
198
+ if (json._model) {
199
+ schemas.push(this.getModelSchemaByName(json._model))
200
+ }
201
+ return new ModelSchemas({
202
+ framework: this.framework,
203
+ schemas: schemas.filter(Boolean)
204
+ })
205
+ }
206
+ }
207
+
208
+ export default Schemas