semantic-analysis
Version:
Extensible semantic Structured Data analysis library for Microdata and JSON-LD
139 lines • 5.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SchemaValidator = void 0;
var schema_1 = require("./schema");
var item_1 = require("../item");
var spec_1 = require("../item/spec");
// TODO Fix wrong property name!
/**
* Validates result against schema.org
*/
var SchemaValidator = /** @class */ (function () {
/* Initialization */
function SchemaValidator(schema) {
var _this = this;
this.schema = schema;
this.superClasses = function (type) {
var classes = [type];
var pending = classes.slice();
while (pending.length) {
var c = pending.shift();
if (!c || !schema_1.isClass(c) || !c.subClassOf) {
continue;
}
classes.push.apply(classes, c.subClassOf);
pending.push.apply(pending, c.subClassOf);
}
return classes;
};
this.completeRange = function (defs) {
return ['Text', 'URL']
.map(function (d) { return _this.schema.get(schemaOrg(d)); })
.concat(defs.rangeIncludes || []);
};
}
/* Validator */
SchemaValidator.prototype.validate = function (result) {
var _this = this;
console.groupCollapsed('Schema validation');
result.items.forEach(function (item) { return _this.inspect(item); });
console.groupEnd();
};
SchemaValidator.prototype.inspect = function (item) {
var _this = this;
var itemTypes = this.obtainClass(item);
if (!itemTypes.length || itemTypes.find(function (t) { return !t.id.startsWith(namespaceSchema) || !(t.type && t.type.includes('Class')); })) {
return;
}
var domain = this.obtainDomain(itemTypes.filter(function (t) { return schema_1.isClass(t); }));
// TODO Move to PropertyValidator in case term marking can be specified on item
for (var name_1 in item.propMeta) {
if (!item.propMeta.hasOwnProperty(name_1)) {
continue;
}
var def = domain[name_1];
if (!def) {
var message = "Property " + name_1 + " is not present in the types' domain " + item.type.join(', ');
console.debug(message);
// TODO Use item property values wrapped log instead when implemented
item.meta.logs.push({
message: message,
sort: 'Error',
phase: 'Semantics',
});
continue;
}
var _loop_1 = function (prop) {
var type = this_1.determineType(prop.value);
var range = this_1.completeRange(def);
if (!type.every(function (t) {
var inherentTypes = _this.superClasses(t)
.map(function (tp) { return tp.id; });
return !!range.find(function (r) {
return inherentTypes.includes(r.id);
});
})) {
// TODO IMPORTANT! TEST!
var message = "The value is not in valid range of types";
console.error(message, '\nvalue:', prop.value, '\ntype:', type, '\nrange', range);
prop.meta.logs.push({
message: message,
sort: 'Error',
phase: 'Semantics',
});
}
};
var this_1 = this;
for (var _i = 0, _a = item.propMeta[name_1]; _i < _a.length; _i++) {
var prop = _a[_i];
_loop_1(prop);
}
}
};
/* Helpers */
SchemaValidator.prototype.obtainClass = function (item) {
var _this = this;
return item.type
.filter(function (v, i, s) { return s.indexOf(v) === i; }) // TODO Warning about duplicate types
.map(function (type) {
var term = _this.schema.get(type);
if (!term && type.startsWith(namespaceSchema)) {
var message_1 = "Type " + type + " is not a recognized term of schema.org vocabulary";
if (!item.meta.logs.find(function (l) { return l.message === message_1; })) {
console.debug(message_1);
item.meta.logs.push({
message: message_1,
sort: 'Error',
phase: 'Semantics',
});
}
}
return term || { id: type };
})
.filter(function (term) { return term; });
};
SchemaValidator.prototype.obtainDomain = function (classes) {
var _a;
var domain = {};
(_a = this.schema).getProperties.apply(_a, classes).forEach(function (p) {
domain[p.id] = p;
});
return domain;
};
SchemaValidator.prototype.determineType = function (value) {
if (item_1.Spec.isItem(value)) {
this.inspect(value);
return this.obtainClass(value);
}
if (item_1.Spec.isValuePrimitive(value)) {
// TODO IMPORTANT! Add type assumption algorithm
return [this.schema.get(schemaOrg('Text'))];
}
throw new TypeError('Given value is neither an item or a string');
};
return SchemaValidator;
}());
exports.SchemaValidator = SchemaValidator;
var namespaceSchema = 'http://schema.org';
var schemaOrg = function (id) { return spec_1.combine(id, namespaceSchema); };
//# sourceMappingURL=SchemaValidator.js.map