semantic-analysis
Version:
Extensible semantic Structured Data analysis library for Microdata and JSON-LD
275 lines • 9.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.JsonExtractor = void 0;
var tslib_1 = require("tslib");
require("../../util");
var spec_1 = require("../item/spec");
var util_1 = require("../../util");
/**
* Simplified JSON-LD extractor based on Google structured data examples
* @see https://developers.google.com/search/docs/guides/intro-structured-data
*/
var JsonExtractor = /** @class */ (function () {
/* Initialization */
function JsonExtractor(doc) {
this.doc = doc;
this.meta = {
type: 'JSON-LD',
extractor: this,
document: doc,
};
}
/* Extractor */
JsonExtractor.prototype.extract = function () {
console.groupCollapsed('JSON-LD extraction');
console.debug('Initializing...');
var result = this.findItems();
console.groupEnd();
return result;
};
JsonExtractor.prototype.findItems = function () {
var _this = this;
var result = { items: [], logs: [], document: this.doc };
var scripts = this.doc.document.querySelectorAll('script[type="application/ld+json"]');
var _loop_1 = function (script) {
var json = void 0;
try {
json = JSON.parse(script.innerHTML);
}
catch (e) {
var message = 'Contents could not be parsed as JSON';
console.debug(message);
result.logs.push({
message: message,
sort: 'Error',
phase: 'Parsing',
element: script,
});
return "continue";
}
if (typeof json !== 'object' || json === null) {
var message = "Invalid type " + (json !== null ? typeof json : 'null') + ", expected non-null object or array";
console.debug(message);
result.logs.push({
message: message,
sort: 'Error',
phase: 'Extraction',
element: script,
});
return "continue";
}
(Array.isArray(json) ? json : [json])
.filter(function (o) {
if (typeof o === 'object' && o !== null) {
return true;
}
else {
var message = "Skipping " + (o !== null ? typeof o : 'null') + ", expected non-null object";
console.debug(message);
result.logs.push({
message: message,
sort: 'Warning',
phase: 'Extraction',
element: script,
});
return false;
}
})
.forEach(function (o) {
console.debug('Building item from: ', o);
result.items.push(new JsonItem(o, tslib_1.__assign(tslib_1.__assign({}, _this.meta), { element: script, logs: [] })));
});
};
for (var _i = 0, _a = Array.from(scripts); _i < _a.length; _i++) {
var script = _a[_i];
_loop_1(script);
}
console.debug('Extractions finished');
return result;
};
;
return JsonExtractor;
}());
exports.JsonExtractor = JsonExtractor;
// TODO Move classes into a separate package
/**
* Local implementation of an item
*/
var JsonItem = /** @class */ (function () {
/* Initialization */
function JsonItem(json, meta) {
this.builder = new JsonItemBuilder(json, meta);
}
Object.defineProperty(JsonItem.prototype, "item", {
get: function () {
if (!this._item) {
this._item = this.builder.build();
}
return this._item;
},
enumerable: false,
configurable: true
});
;
Object.defineProperty(JsonItem.prototype, "type", {
/* Extraction Item */
get: function () {
return this.item.type;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItem.prototype, "id", {
get: function () {
return this.item.id;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItem.prototype, "properties", {
get: function () {
return this.item.properties;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItem.prototype, "meta", {
get: function () {
return this.item.meta;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItem.prototype, "propMeta", {
get: function () {
return this.item.propMeta;
},
enumerable: false,
configurable: true
});
return JsonItem;
}());
var JsonItemBuilder = /** @class */ (function () {
/* Initialization */
function JsonItemBuilder(json, meta, context) {
var _this = this;
this.json = json;
this.meta = meta;
/* Build */
this.build = function () { return ({
type: _this.type,
id: _this.id,
get properties() {
return unwrapProperties(this.propMeta);
},
meta: tslib_1.__assign(tslib_1.__assign({}, _this.meta), { logs: [] }),
propMeta: util_1.map(_this.propMeta, function (props) { return props.map(function (prop) { return (tslib_1.__assign(tslib_1.__assign({}, prop), { value: prop.value instanceof JsonItemBuilder
? prop.value.build()
: prop.value })); }); }),
}); };
/* Helpers */
this.parseType = function () {
var type = _this.json['@type'];
if (!type) {
return [];
}
if (Array.isArray(type)) {
return type.map(function (t) { return String(t); });
}
else {
return [String(type)];
}
};
this.applyContext = function (type) {
return type.map(function (t) { return spec_1.combine(t, _this.context); });
};
this.findProperties = function () {
var properties = {};
util_1.map(util_1.filter(_this.json, (function (value, key) { return !String(key).startsWith('@'); })), function (val, name) {
var completeName = spec_1.combine(String(name), _this.context);
var values = (Array.isArray(val) ? val : [val])
.filter(function (value) {
return value !== null &&
String(value).trim() !== '';
})
.map(function (value) { return ({
name: completeName,
value: typeof value === 'object'
? new JsonItemBuilder(value, _this.meta, _this.context)
: String(value).trim(),
meta: tslib_1.__assign(tslib_1.__assign({}, _this.meta), { logs: [] }),
}); });
properties[completeName] = values;
return values;
});
return properties;
};
if (context) {
this.context = context;
}
else {
var c = json['@context'];
if (typeof c === 'string') {
try {
this.context = new URL(c).toString();
}
catch (e) {
var message = 'Given context is not a valid URL, ignoring';
console.debug(message);
meta.logs.push({
message: message,
sort: 'Error',
element: meta.element,
phase: 'Extraction',
});
}
}
else if (c !== undefined) {
var message = 'The app cannot inspect non-string contexts yet';
console.error(message);
meta.logs.push({
message: message,
sort: 'Notice',
element: meta.element,
phase: 'Extraction',
});
}
}
}
Object.defineProperty(JsonItemBuilder.prototype, "type", {
/* Item */
get: function () {
return this.applyContext(this.parseType());
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItemBuilder.prototype, "id", {
get: function () {
return typeof this.json['@id'] === 'string' ? this.json['@id'] : undefined;
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItemBuilder.prototype, "properties", {
get: function () {
return unwrapProperties(this.propMeta);
},
enumerable: false,
configurable: true
});
Object.defineProperty(JsonItemBuilder.prototype, "propMeta", {
get: function () {
return this.findProperties();
},
enumerable: false,
configurable: true
});
return JsonItemBuilder;
}());
var unwrapProperties = function (propMeta) {
return util_1.map(propMeta, function (props) {
return props.map(function (prop) { return prop.value; });
});
};
//# sourceMappingURL=JsonExtractor.js.map