The translator metadata had '2026-02-08 23:00:00' (space-separated) instead of '2026-02-08T23:00:00Z'. Zotero validates this field and throws 'accessDate must be in ISO 8601' when loading translators with non-conformant dates.
118 lines
3.5 KiB
JavaScript
118 lines
3.5 KiB
JavaScript
{
|
|
"translatorID": "68c61549-9e8c-4645-8061-64281058c2f9",
|
|
"label": "CMS 4innovation",
|
|
"creator": "ACO Data Platform",
|
|
"target": "^https?://4innovation\\.cms\\.gov/secure/knowledge-management/view/",
|
|
"minVersion": "3.0",
|
|
"maxVersion": "",
|
|
"priority": 100,
|
|
"inRepository": false,
|
|
"translatorType": 4,
|
|
"browserSupport": "gcsibv",
|
|
"lastUpdated": "2026-02-08T23:00:00Z"
|
|
}
|
|
|
|
/*
|
|
CMS 4innovation Knowledge Management Translator
|
|
|
|
Captures structured metadata from 4innovation.cms.gov knowledge
|
|
base articles.
|
|
|
|
Captured fields: title, subcategory, description, date, author,
|
|
views, KM article ID, attachment filenames.
|
|
|
|
TODO: File download via API. The 4i API proxy at
|
|
https://4innovation.cms.gov/api/knowledge-management/{kmId}
|
|
returns article JSON including files[].fileMetaId. Download URL:
|
|
https://4innovation.cms.gov/api/knowledge-management/download/{fileMetaId}
|
|
The callback-based ZU.doGet approach with same-origin URLs is the
|
|
correct path forward. async/await crashes the Connector sandbox.
|
|
The cross-origin API (4innovation-api.cms.gov) returns 403.
|
|
Need to debug why ZU.doGet callback doesn't trigger file saves.
|
|
|
|
License: AGPL-3.0
|
|
*/
|
|
|
|
function detectWeb(doc, url) {
|
|
if (/\/secure\/knowledge-management\/view\/\d+/.test(url)) {
|
|
return 'webpage';
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function doWeb(doc, url) {
|
|
var item = new Zotero.Item('webpage');
|
|
item.url = url;
|
|
item.websiteTitle = '4Innovation';
|
|
|
|
var kmId = '';
|
|
var idMatch = url.match(/\/view\/(\d+)/);
|
|
if (idMatch) kmId = idMatch[1];
|
|
|
|
// Title
|
|
var el = doc.querySelector('[id="title-1"]');
|
|
item.title = (el && el.textContent) ? el.textContent.replace(/\s+/g, ' ').trim() : ('4i Article ' + kmId);
|
|
|
|
// Date
|
|
var el2 = doc.querySelector('[id="state-last-updated-date"]');
|
|
if (el2 && el2.textContent) {
|
|
var dateRaw = el2.textContent.replace(/\s+/g, ' ').trim();
|
|
var dm = dateRaw.match(/(\d{2})\/(\d{2})\/(\d{4})/);
|
|
if (dm) item.date = dm[3] + '-' + dm[1] + '-' + dm[2];
|
|
}
|
|
|
|
// Author
|
|
var el3 = doc.querySelector('[id="state-creatdBy"]');
|
|
if (el3 && el3.textContent) {
|
|
var author = el3.textContent.replace(/\s+/g, ' ').trim();
|
|
if (author) {
|
|
item.creators.push({ lastName: author, creatorType: 'author', fieldMode: 1 });
|
|
}
|
|
}
|
|
|
|
// Description
|
|
var el4 = doc.querySelector('[id="description-1"]');
|
|
if (el4 && el4.textContent) {
|
|
var desc = el4.textContent.replace(/\s+/g, ' ').trim();
|
|
if (desc) item.abstractNote = desc;
|
|
}
|
|
|
|
// Subcategory
|
|
var subcategory = '';
|
|
var el5 = doc.querySelector('[id="subcategory-1"]');
|
|
if (el5 && el5.textContent) subcategory = el5.textContent.replace(/\s+/g, ' ').trim();
|
|
|
|
// Views
|
|
var views = '';
|
|
var el6 = doc.querySelector('[id="view-count-1"]');
|
|
if (el6 && el6.textContent) views = el6.textContent.replace(/\s+/g, ' ').trim();
|
|
|
|
// Extra
|
|
var extraParts = [];
|
|
if (kmId) extraParts.push('KM-ID: ' + kmId);
|
|
if (subcategory) extraParts.push('Subcategory: ' + subcategory);
|
|
if (views) extraParts.push('Views: ' + views);
|
|
|
|
// Filenames from DOM (recorded but not downloaded)
|
|
var fileEls = doc.querySelectorAll('[id^="file-"]');
|
|
var filenames = [];
|
|
for (var i = 0; i < fileEls.length; i++) {
|
|
var fn = fileEls[i].textContent.replace(/\s+/g, ' ').trim();
|
|
if (fn && fn.indexOf('.') !== -1) filenames.push(fn);
|
|
}
|
|
if (filenames.length) extraParts.push('Attachments: ' + filenames.join('; '));
|
|
|
|
item.extra = extraParts.join('\n');
|
|
|
|
// Tags
|
|
item.tags.push({ tag: 'source:4i' });
|
|
if (subcategory) {
|
|
item.tags.push({ tag: 'category:' + subcategory.toLowerCase().replace(/\s+/g, '-') });
|
|
}
|
|
|
|
// Snapshot
|
|
item.attachments.push({ document: doc, title: 'Snapshot' });
|
|
|
|
item.complete();
|
|
}
|