UNPKG

@botonic/plugin-contentful

Version:

Botonic Plugin Contentful is one of the **[available](https://github.com/hubtype/botonic/tree/master/packages)** plugins for Botonic. **[Contentful](http://www.contentful.com)** is a CMS (Content Management System) which manages contents of a great variet

165 lines 6.77 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.I18nEntryTraverser = exports.LoggerContentfulVisitor = exports.VisitedField = void 0; const tslib_1 = require("tslib"); const button_1 = require("./contents/button"); class VisitedField { constructor(entry, locale, field, value) { this.entry = entry; this.locale = locale; this.field = field; this.value = value; } } exports.VisitedField = VisitedField; class LoggerContentfulVisitor { constructor(visitor) { this.visitor = visitor; } name() { return this.visitor.name(); } visitEntry(entry) { this.log('visitEntry', entry); return this.visitor.visitEntry(entry); } visitStringField(field) { this.log('visitStringField', field.entry, field.field); return this.visitor.visitStringField(field); } visitMultipleStringField(field) { this.log('visitMultipleStringField', field.entry, field.field); return this.visitor.visitMultipleStringField(field); } visitOtherField(field) { this.log('visitOtherField', field.entry, field.field); return this.visitor.visitOtherField(field); } visitSingleReference(field) { this.log('visitSingleReference', field.entry, field.field); return this.visitor.visitSingleReference(field); } visitMultipleReference(field) { this.log('visitMultipleReference', field.entry, field.field); return this.visitor.visitMultipleReference(field); } log(method, entry, field) { const on = field ? LoggerContentfulVisitor.describeField(entry, field.id) : LoggerContentfulVisitor.describeEntry(entry); console.log(`Visiting '${this.visitor.name()}.${method}' on ${on}`); } static describeEntry(entry) { if (!entry.sys.contentType) { return `entry with id ${entry.sys.id}`; } return `entry of type ${entry.sys.contentType.sys.id} (id:${entry.sys.id})`; } static describeField(entry, name) { // cannot stringify field values because they may contain circular references return `field '${name}' of ${LoggerContentfulVisitor.describeEntry(entry)}`; } } exports.LoggerContentfulVisitor = LoggerContentfulVisitor; /** * Traverser a contentful Entry which has been requested for all locales. * Limitations. It does not fetch entries from references which have not yet been delivered. * ATTENTION Due to the complexity of traversing links with potential circular references, it stops recursion on button * callbacks. This causes some entries to get wrong values. */ class I18nEntryTraverser { constructor(api, visitor) { this.api = api; this.visitor = visitor; this.visited = new Set(); } traverse(entry, context) { return tslib_1.__awaiter(this, void 0, void 0, function* () { //in the future we might extending to traverse all locales console.assert(context.locale); console.assert(context.ignoreFallbackLocale); const promise = this.traverseCore(entry, context); this.visited.add(entry.sys.id); return promise; }); } traverseCore(entry, context) { return tslib_1.__awaiter(this, void 0, void 0, function* () { entry = Object.assign(Object.assign({}, entry), { fields: Object.assign({}, entry.fields) }); const fields = entry.fields; if (!entry.sys.contentType) { // it's a file or a dangling reference return entry; } const contentType = yield this.api.getContentType(entry.sys.contentType.sys.id); for (const fieldId in fields) { const field = contentType.fields.find(f => f.id == fieldId); const i18nValue = Object.assign({}, fields[fieldId]); const locale = field.localized ? context.locale : Object.keys(i18nValue)[0]; const vf = new VisitedField(entry, locale, field, i18nValue); fields[fieldId] = yield this.traverseField(context, vf); } entry = this.visitor.visitEntry(entry); return entry; }); } traverseField(context, vf) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let val = vf.value[vf.locale]; const visitOrTraverse = (val) => tslib_1.__awaiter(this, void 0, void 0, function* () { if (this.visited.has(val.sys.id) && val.sys.id >= vf.entry.sys.id) { // break deadlock if contents have cyclic dependencies return val; } return this.traverse(val, context); }); if (vf.field.type === 'Symbol' || vf.field.type === 'Text') { return this.visitor.visitStringField(vf); } else if (vf.field.type == 'Link') { if (val) { val = this.stopRecursionOnButtonCallbacks(vf.field, val); vf.value[vf.locale] = visitOrTraverse(val); } return this.visitor.visitSingleReference(vf); } else if (this.isArrayOfType(vf.field, 'Link')) { if (val) { val = yield Promise.all(val.map(v => visitOrTraverse(v))); vf.value[vf.locale] = val; } return this.visitor.visitMultipleReference(vf); } else if (this.isArrayOfType(vf.field, 'Symbol')) { return this.visitor.visitMultipleStringField(vf); } else { return this.visitor.visitOtherField(vf); } }); } isArrayOfType(field, itemType) { var _a; return field.type == 'Array' && ((_a = field.items) === null || _a === void 0 ? void 0 : _a.type) == itemType; } /** * When a content has a button with another content reference, we just need the referred content id * to create the content. Hence, we stop traversing. */ stopRecursionOnButtonCallbacks(field, val) { var _a; if (field.id !== 'target') { return val; } if (!val.fields || val.fields.payload || ((_a = val.sys.contentType) === null || _a === void 0 ? void 0 : _a.sys.id) == button_1.ButtonDelivery.BUTTON_CONTENT_TYPE) { return val; } return Object.assign(Object.assign({}, val), { fields: {} }); } } exports.I18nEntryTraverser = I18nEntryTraverser; //# sourceMappingURL=traverser.js.map