UNPKG

@kit-data-manager/pid-component

Version:

The PID-Component is a web component that can be used to evaluate and display FAIR Digital Objects, PIDs, ORCiDs, and possibly other identifiers in a user-friendly way. It is easily extensible to support other identifier types.

341 lines (340 loc) 14.9 kB
/*! * * Copyright 2024-2026 Karlsruhe Institute of Technology. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ import { FoldableItem } from "../../../utils/FoldableItem"; import { beautifyResourceType } from "../ResourceTypeIcons"; export class CrossRefInfo { constructor(doi, response, type = 'work') { this._doi = doi; this._type = type; this._rawMetadata = response; if (type === 'funder') { this._message = {}; } else { const cr = response; this._message = typeof cr.message === 'string' ? {} : cr.message || {}; } } get type() { return this._type; } get title() { if (this._type === 'funder') { const funderResponse = this._rawMetadata; const funderMsg = typeof funderResponse.message === 'string' ? null : funderResponse.message; return (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.name) || ''; } const titles = this._message.title || []; return titles[0] || ''; } get creators() { if (this._type === 'funder') return []; const authors = this._message.author || []; return authors.map((author) => { const result = { name: author.name || '', givenName: author.given, familyName: author.family, }; if (!result.name) { if (author.given && author.family) { result.name = `${author.given} ${author.family}`; } else { result.name = author.given || author.family || ''; } } if (author.ORCID) { result.orcid = author.ORCID.replace(/^https?:\/\/orcid\.org\//i, ''); } if (author.affiliation && author.affiliation.length > 0) { result.affiliation = author.affiliation[0].name; } return result; }).filter((c) => c.name); } get correspondingAuthor() { if (this._type === 'funder') return undefined; const authors = this._message.author || []; const firstAuthor = authors.find((a) => a.sequence === 'first') || authors[0]; if (!firstAuthor) return undefined; const result = { name: firstAuthor.name || '', givenName: firstAuthor.given, familyName: firstAuthor.family, isCorresponding: true, }; if (!result.name) { if (firstAuthor.given && firstAuthor.family) { result.name = `${firstAuthor.given} ${firstAuthor.family}`; } else { result.name = firstAuthor.given || firstAuthor.family || ''; } } if (firstAuthor.ORCID) { result.orcid = firstAuthor.ORCID.replace(/^https?:\/\/orcid\.org\//i, ''); } if (firstAuthor.affiliation && firstAuthor.affiliation.length > 0) { result.affiliation = firstAuthor.affiliation[0].name; } return result; } get publisher() { if (this._type === 'funder') return undefined; return this._message.publisher; } get publicationDate() { var _a; if (this._type === 'funder') { const funderResponse = this._rawMetadata; const funderMsg = typeof funderResponse.message === 'string' ? null : funderResponse.message; if (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.established) { return `${funderMsg.established}`; } return undefined; } const dateObj = this._message.issued || this._message.published || this._message.created; if (!((_a = dateObj === null || dateObj === void 0 ? void 0 : dateObj['date-parts']) === null || _a === void 0 ? void 0 : _a[0])) return undefined; const parts = dateObj['date-parts'][0]; const year = parts[0]; const month = parts[1]; const day = parts[2]; if (year && month && day) { return `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; } else if (year && month) { return `${year}-${String(month).padStart(2, '0')}`; } else if (year) { return `${year}`; } return undefined; } get resourceType() { if (this._type === 'funder') return 'Funder'; return this._message.type; } get description() { if (this._type === 'funder') return undefined; const abstract = this._message.abstract; return abstract ? this.parseJATS(abstract) : undefined; } get url() { var _a, _b; if (this._type === 'funder') { const funderResponse = this._rawMetadata; const funderMsg = typeof funderResponse.message === 'string' ? null : funderResponse.message; return (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.url) || this._doi.toURL(); } return this._message.URL || ((_b = (_a = this._message.resource) === null || _a === void 0 ? void 0 : _a.primary) === null || _b === void 0 ? void 0 : _b.URL) || this._doi.toURL(); } get subjects() { if (this._type === 'funder') { const funderResponse = this._rawMetadata; const funderMsg = typeof funderResponse.message === 'string' ? null : funderResponse.message; return (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg['alternate-name']) || []; } return this._message.subject || []; } get rawMetadata() { return this._rawMetadata; } static async fetch(doi) { const workResponse = await CrossRefInfo.fetchWork(doi); if (workResponse) { return new CrossRefInfo(doi, workResponse, 'work'); } const funderResponse = await CrossRefInfo.fetchFunder(doi); if (funderResponse) { return new CrossRefInfo(doi, funderResponse, 'funder'); } return null; } static async fetchWork(doi) { try { const apiUrl = `https://api.crossref.org/works/${doi.toString()}`; const response = await fetch(apiUrl); if (!response.ok) { console.debug(`CrossRef works error: ${response.status}`); return null; } const data = await response.json(); if (data.status !== 'ok' || !data.message || typeof data.message === 'string') { return null; } return data; } catch (error) { console.debug('CrossRef works fetch error:', error); return null; } } static async fetchFunder(doi) { try { const apiUrl = `https://api.crossref.org/funders/${doi.toString()}`; const response = await fetch(apiUrl); if (!response.ok) { console.debug(`CrossRef funders error: ${response.status}`); return null; } const data = await response.json(); if (data.status !== 'ok' || !data.message || typeof data.message === 'string') { return null; } return data; } catch (error) { console.debug('CrossRef funders fetch error:', error); return null; } } static fromObject(doiObj, obj) { return new CrossRefInfo(doiObj, obj.rawMetadata, obj.type || 'work'); } generateItems() { const items = []; const index = 10; if (this._type === 'funder') { return this.generateFunderItems(index); } return this.generateWorkItems(items, index); } generateWorkItems(items, index) { if (this.title) { items.push(new FoldableItem(index++, 'Title', this.title, 'The title of the resource.', undefined, undefined, false)); } const correspondingAuthor = this.correspondingAuthor; if (correspondingAuthor) { items.push(new FoldableItem(index++, 'Corresponding Author', correspondingAuthor.orcid || `${correspondingAuthor.name}${correspondingAuthor.affiliation ? ` (${correspondingAuthor.affiliation})` : ''}`, 'The first author of the resource, often the corresponding author.')); } const creators = this.creators; creators.forEach((creator, idx) => { if (idx === 0 && correspondingAuthor) return; items.push(new FoldableItem(index++, 'Author', creator.orcid || `${creator.name}${creator.affiliation ? ` (${creator.affiliation})` : ''}`, 'A creator/author of the resource.', creator.orcid ? `https://orcid.org/${creator.orcid}` : undefined)); }); if (this.publisher) { items.push(new FoldableItem(index++, 'Publisher', this.publisher, 'The publisher of the resource.')); } if (this.publicationDate) { items.push(new FoldableItem(index++, 'Publication Date', this.publicationDate, 'The publication date in ISO 8601 format.')); } if (this.resourceType) { items.push(new FoldableItem(index++, 'Resource Type', beautifyResourceType(this.resourceType), 'The type of the resource.')); } if (this.description) { items.push(new FoldableItem(index++, 'Abstract', this.description, 'The abstract of the resource.', undefined, undefined, false)); } this.subjects.forEach((subject) => { items.push(new FoldableItem(index++, 'Subject', subject, 'A subject area or keyword.')); }); return items; } generateFunderItems(index) { const items = []; const funderResponse = this._rawMetadata; const funderMsg = typeof funderResponse.message === 'string' ? null : funderResponse.message; if (this.title) { items.push(new FoldableItem(index++, 'Name', this.title, 'The name of the funder.', undefined, undefined, false)); } if (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.location) { items.push(new FoldableItem(index++, 'Location', funderMsg.location, 'The location of the funder.')); } if (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.established) { items.push(new FoldableItem(index++, 'Established', `${funderMsg.established}`, 'The year the funder was established.')); } if (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.id) { items.push(new FoldableItem(index++, 'CrossRef Funder ID', funderMsg.id, 'The CrossRef identifier for this funder.')); } if (funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.url) { items.push(new FoldableItem(index++, 'Website', funderMsg.url, 'The website of the funder.', funderMsg.url)); } if ((funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg['alternate-name']) && funderMsg['alternate-name'].length > 0) { items.push(new FoldableItem(index++, 'Alternate Names', funderMsg['alternate-name'].join(', '), 'Alternate names for the funder.', undefined, undefined, false)); } if ((funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg['hierarchy-names']) && Object.keys(funderMsg['hierarchy-names']).length > 0) { const hierarchyNames = Object.entries(funderMsg['hierarchy-names']) .map(([id, name]) => `${name} (${id})`) .join(', '); items.push(new FoldableItem(index++, 'Hierarchy', hierarchyNames, 'The funder hierarchy in the CrossRef organization tree.', undefined, undefined, false)); } if ((funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg['replaced-by']) && funderMsg['replaced-by'].length > 0) { const replacedBy = funderMsg['replaced-by'] .map(f => f.name || f.id) .filter(Boolean) .join(', '); if (replacedBy) { items.push(new FoldableItem(index++, 'Replaced By', replacedBy, 'Funders that have replaced this funder.')); } } if ((funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.replaces) && funderMsg.replaces.length > 0) { const replaces = funderMsg.replaces .map(f => f.name || f.id) .filter(Boolean) .join(', '); if (replaces) { items.push(new FoldableItem(index++, 'Replaces', replaces, 'Funders that this funder replaces.')); } } if ((funderMsg === null || funderMsg === void 0 ? void 0 : funderMsg.descendants) && funderMsg.descendants.length > 0) { const descendants = funderMsg.descendants .map(d => d.name || d.id) .filter(Boolean) .join(', '); if (descendants) { items.push(new FoldableItem(index++, 'Descendants', descendants, 'Descendant funders in the hierarchy.', undefined, undefined, false)); } } return items; } toObject() { return { doi: JSON.stringify(this._doi.toObject()), rawMetadata: this._rawMetadata, type: this._type, }; } parseJATS(text) { if (!text) return text; return text .replace(/<jats:p>/g, '') .replace(/<\/jats:p>/g, '\n') .replace(/<jats:italic>/g, '<i>') .replace(/<\/jats:italic>/g, '</i>') .replace(/<jats:bold>/g, '<b>') .replace(/<\/jats:bold>/g, '</b>') .replace(/<jats:sub>/g, '<sub>') .replace(/<\/jats:sub>/g, '</sub>') .replace(/<jats:sup>/g, '<sup>') .replace(/<\/jats:sup>/g, '</sup>') .replace(/<jats:title>/g, '<strong>') .replace(/<\/jats:title>/g, '</strong>') .replace(/\n\n+/g, '\n\n') .trim(); } } //# sourceMappingURL=CrossRefInfo.js.map