@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
JavaScript
/*!
*
* 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