diff --git a/tests/validate_animations.test.js b/tests/validate_animations.test.js index 1a3c4ea..8d3f400 100644 --- a/tests/validate_animations.test.js +++ b/tests/validate_animations.test.js @@ -12,6 +12,24 @@ const ajv = new Ajv({ }); const validate = ajv.compile(schema); +expect.extend({ + toBeValid(data) { + + if ( validate(data) ) + { + return { + message: () => "data NOT be valid", + pass: true + }; + } + + return { + message: () => "Invalid data: " + JSON.stringify(validate.errors, null, 4), + pass: false + }; + } +}); + describe('run schema validation', () => { describe('example animations', () => { const exampleFiles = fs.readdirSync(EXAMPLES_DIR).map(file => EXAMPLES_DIR + file); @@ -19,9 +37,7 @@ describe('run schema validation', () => { exampleFiles.forEach((file) => { test(file, () => { const animation = fs.readFileSync(file, 'utf8'); - const valid = validate(JSON.parse(animation)); - - expect(valid).toBe(true); + expect(JSON.parse(animation)).toBeValid(); }); }); }); @@ -33,7 +49,7 @@ describe('run schema validation', () => { test(file, () => { const animation = fs.readFileSync(file, 'utf8'); const valid = validate(JSON.parse(animation)); - + expect(valid).toBe(true); }); }); @@ -46,7 +62,7 @@ describe('run schema validation', () => { test(file, () => { const animation = fs.readFileSync(file, 'utf8'); const valid = validate(JSON.parse(animation)); - + expect(valid).toBe(false); }); }); diff --git a/tools/lottie_markdown.py b/tools/lottie_markdown.py index 5dd8d76..3ad20c5 100644 --- a/tools/lottie_markdown.py +++ b/tools/lottie_markdown.py @@ -512,12 +512,13 @@ def handleMatch(self, match, data): schema_obj = self.schema_data.from_path(match.group("path")) for row in schema_obj.concrete: - tr = etree.SubElement(tbody, "tr") - prop_schema = row.properties[attribute] - etree.SubElement(etree.SubElement(tr, "td"), "code").text = repr(prop_schema.const) + prop_schema = row.properties.get(attribute) + if prop_schema: + tr = etree.SubElement(tbody, "tr") + etree.SubElement(etree.SubElement(tr, "td"), "code").text = repr(prop_schema.const) - td = etree.SubElement(tr, "td") - row.link.to_element(td, self.md) + td = etree.SubElement(tr, "td") + row.link.to_element(td, self.md) return table, match.start(0), match.end(0) diff --git a/tools/schema-merge.py b/tools/schema-merge.py index bd56f09..326fa9a 100755 --- a/tools/schema-merge.py +++ b/tools/schema-merge.py @@ -41,9 +41,9 @@ def add_vals_to_unknown_object( types = [] for ele in objects.concrete: - type = ele.properties['ty'].const - if type is not None: - types.append(type) + type = ele.properties.get('ty', None) + if type is not None and type.const is not None: + types.append(type.const) unknown_type_dict["properties"]["ty"]["not"]["enum"] = types diff --git a/tools/schema_tools/type_info.py b/tools/schema_tools/type_info.py index f2f3b7e..ce1a209 100644 --- a/tools/schema_tools/type_info.py +++ b/tools/schema_tools/type_info.py @@ -27,6 +27,16 @@ def load(path): schema_data = Schema(json.load(file)) return TypeSystem(schema_data) + def resolve_type(self, schema: Schema): + if "oneOf" in schema: + local_type = schema.get("type", None) + if local_type is not None: + return local_type + return [self.resolve_type(choice) for choice in schema / "oneOf"] + if "$ref" in schema: + return self.types[schema["$ref"]] + return schema.get("type", None) + class Type: def __init__(self, type_system: TypeSystem, schema: Schema): @@ -50,20 +60,10 @@ def __init__(self, type_system: TypeSystem, schema: Schema): super().__init__(type_system, schema) self.const = schema.get("const", None) - def resolve_type(self, schema: Schema): - if "oneOf" in schema: - local_type = schema.get("type", None) - if local_type is not None: - return local_type - return [self.resolve_type(choice) for choice in schema / "oneOf"] - if "$ref" in schema: - return self.type_system.types[schema["$ref"]] - return schema.get("type", None) - def resolve(self): - self.type = self.resolve_type(self.schema) + self.type = self.type_system.resolve_type(self.schema) if "items" in self.schema: - self.item_type = self.resolve_type(self.schema / "items") + self.item_type = self.type_system.resolve_type(self.schema / "items") else: self.item_type = "" @@ -89,6 +89,12 @@ def __init__(self, type_system: TypeSystem, schema: Schema): def get_properties(self, schema: Schema): if "properties" in schema: for name, value in (schema / "properties").items(): + if ( + isinstance(value.schema, dict) and + len(value.schema) == 1 and + list(value.schema.keys())[0] == "not" + ): + continue self.properties[name] = Property(self.type_system, value) def resolve(self):