{ "translatorID": "4a3820a3-a7bd-44a1-8711-acf7b57d2c37", "translatorType": 4, "label": "Web of Science Nextgen", "creator": "Abe Jellinek", "target": "^https://(www\\.webofscience\\.com|webofscience\\.clarivate\\.cn)/", "minVersion": "3.0", "maxVersion": null, "priority": 100, "inRepository": true, "browserSupport": "gcsibv", "lastUpdated": "2026-01-05 17:50:00" } /* ***** BEGIN LICENSE BLOCK ***** Copyright © 2021 Abe Jellinek This file is part of Zotero. Zotero is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Zotero is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with Zotero. If not, see . ***** END LICENSE BLOCK ***** */ // These always seem to take the form `/wos/woscc/summary//[/]/[...]`, // but we'll be tolerant const SEARCH_RE = /\/(?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:-[0-9a-f]+)?)\/(?:[0-9a-f-]+\/)?(?[^#?/]+)/; function detectWeb(doc, url) { if (url.includes('/full-record/') && getItemID(url) && doc.querySelector('app-full-record-export-option')) { let docType = text(doc, '#FullRTa-doctype-0').trim().toLowerCase(); if (docType == 'proceedings paper') { return "conferencePaper"; } else if (docType == "book") { return "book"; } else if (docType == "data set") { return "dataset"; } else if (text(doc, '#FullRTa-patentNumber-0, #FullRTa-assigneeName-0')) { return "patent"; } else { return "journalArticle"; } } else if (doc.querySelector('app-records-list > app-record') && SEARCH_RE.test(url) || getSearchResults(doc, true)) { return "multiple"; } Z.monitorDOMChanges(doc.querySelector('app-wos')); return false; } // Handle search results on lazy-loaded pages: // export the full result set instead of scraping // URLs from the DOM async function getSearchResultsLazy(doc, url) { let [, qid, sortBy] = url.match(SEARCH_RE); Z.debug('Export params:'); Z.debug({ qid, sortBy }); let markFrom = parseInt(text(doc, 'app-records-list > app-record .mdc-label')); if (isNaN(markFrom)) { markFrom = 1; } let markTo = parseInt(text(doc, '.tab-results-count').replace(/[,.\s]/g, '')); if (isNaN(markTo) || markTo - markFrom > 49) { markTo = markFrom + 49; } Zotero.debug(`Exporting ${markFrom} to ${markTo}`); let taggedText = await requestText('/api/wosnx/indic/export/saveToFile', { method: 'POST', headers: { 'X-1P-WOS-SID': await getSessionID(doc) }, body: JSON.stringify({ action: 'saveToFieldTagged', colName: 'WOS', displayCitedRefs: 'true', displayTimesCited: 'true', displayUsageInfo: 'true', fileOpt: 'othersoftware', filters: 'fullRecord', isRefQuery: 'false', markFrom: String(markFrom), markTo: String(markTo), parentQid: qid, product: 'UA', sortBy, view: 'summary', }) }); let trans = Zotero.loadTranslator('import'); // Web of Science Tagged trans.setTranslator('594ebe3c-90a0-4830-83bc-9502825a6810'); trans.setString(taggedText); trans.setHandler('itemDone', () => {}); return trans.translate(); } // Handle author pages and other eagerly loaded result pages function getSearchResults(doc, checkOnly) { var items = {}; var found = false; var rows = doc.querySelectorAll('app-article-metadata a[href*="/WOS:"], app-summary-title a[href*="/WOS:"]'); for (let row of rows) { let href = row.href; let title = ZU.trimInternal(row.textContent); if (!href || !title) continue; if (checkOnly) return true; found = true; items[href] = title; } return found ? items : false; } async function doWeb(doc, url) { if (detectWeb(doc, url) == 'multiple') { // If it's a lazy-loaded search page, use getSearchResultsLazy(), // which returns full items if (doc.querySelector('app-records-list > app-record') && SEARCH_RE.test(url)) { let items = await getSearchResultsLazy(doc, url); let filteredItems = await Zotero.selectItems( Object.fromEntries(items.entries()) ); if (!filteredItems) return; for (let i of Object.keys(filteredItems)) { let item = items[i]; applyFixes(item); item.complete(); } } // Otherwise, use getSearchResults(), which returns URLs else { let items = await Zotero.selectItems(getSearchResults(doc, false)); if (!items) return; for (let url of Object.keys(items)) { await scrape(await requestDocument(url)); } } } else { await scrape(doc, url); } } async function scrape(doc, url = doc.location.href) { async function processTaggedData(text) { let url = attr(doc, 'a#FRLinkTa-link-1', 'href'); if (url) { try { url = await resolveGateway(url); } catch (e) {} } let importer = Zotero.loadTranslator("import"); // Web of Science Tagged importer.setTranslator("594ebe3c-90a0-4830-83bc-9502825a6810"); importer.setString(text); importer.setHandler('itemDone', function (obj, item) { applyFixes(item); if (!item.url) { item.url = url; } item.complete(); }); await importer.translate(); } let id = getItemID(url); let sessionID = await getSessionID(doc); let postData = { action: 'saveToFieldTagged', colName: id.split(':')[0] || 'WOS', displayCitedRefs: 'true', displayTimesCited: 'true', displayUsageInfo: 'true', fileOpt: 'othersoftware', filters: 'fullRecord', product: 'UA', view: 'fullrec', ids: [id] }; await processTaggedData(await requestText('/api/wosnx/indic/export/saveToFile', { method: 'POST', body: JSON.stringify(postData), headers: { 'X-1P-WOS-SID': sessionID } })); } function getItemID(url) { let idInURL = url.match(/((?:WOS|RSCI|KJD|DIIDW|MEDLINE|DRCI|BCI|SCIELO|ZOOREC|CCC):[^/?&(]+)/); // Z.debug(idInURL) return idInURL && idInURL[1]; } async function getSessionID(doc) { const sidRegex = /(?:sid=|"SID":")([a-zA-Z0-9]+)/i; // session ID is embedded in the static page inside an inline