Permalink
Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
Cannot retrieve contributors at this time
{ | |
"translatorID": "7bd82b70-1ed7-4aaf-bea2-bcbe6429a3ee", | |
"label": "National Library of Norway", | |
"creator": "Dan Michael O. Heggø", | |
"target": "^https?://(www\\.)?nb\\.no/", | |
"minVersion": "3.0", | |
"maxVersion": "", | |
"priority": 100, | |
"inRepository": true, | |
"translatorType": 4, | |
"browserSupport": "gcsibv", | |
"lastUpdated": "2017-11-29 23:36:00" | |
} | |
/* | |
***** BEGIN LICENSE BLOCK ***** | |
National Library of Norway Translator | |
Copyright © 2016 Dan Michael O. Heggø | |
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 <http://www.gnu.org/licenses/>. | |
***** END LICENSE BLOCK ***** | |
*/ | |
function detectWeb(doc, url) { | |
// The page can change from a search page to a single item page | |
// without loading the whole content as a new website, so we | |
// need to monitor for DOM changes. | |
Z.monitorDOMChanges(ZU.xpath(doc, '//div[contains(@class, "layout-content")]')[0], {childList: true}); | |
// New UI - search page | |
if (url.includes('nb.no/search?')){ | |
return 'multiple'; | |
} | |
// Old UI – item (these URLs are not yet redirected to the new UI) | |
if (url.includes('nb.no/nbsok/nb/')){ | |
var nodes = ZU.xpath(doc, '//meta[@name="dc:type"]'); | |
if (nodes.length) { | |
var dcType = nodes[0].getAttribute('content'); | |
return mapMediaType(dcType); | |
} | |
} | |
// New UI - item | |
if (url.includes('nb.no/items/')){ | |
// There is a dc:type meta tag, but it contains values like | |
// "nonfiction" or "Text", so not helpful like before when it contained | |
// material type. | |
return 'book'; | |
} | |
} | |
function doWeb(doc, url) { | |
if (detectWeb(doc, url) == 'multiple') { | |
var linkItems = ZU.xpath(doc, '//a[contains(@href, "items")]'); | |
var items = {}; | |
linkItems.forEach(function(linkItem) { | |
var link = linkItem.getAttribute('href'); | |
// The search result list has two different layouts: 'grid' and 'list'. | |
// The first xpath is for the grid view, the second for the list view. | |
var title = ZU.xpathText(linkItem, './/label[@class="title" or @class="subtitle"]') | |
|| ZU.xpathText(linkItem, './/dd[position() < 4]'); | |
if (title) { | |
items[link] = title; | |
} | |
}); | |
Zotero.selectItems(items, function(items) { | |
if (!items) { | |
return true; | |
} | |
var urls = Object.keys(items); | |
ZU.processDocuments(urls, processUrl); | |
}); | |
} else { | |
processUrl(doc, url); | |
} | |
} | |
function getIdentifierFromUrl(url) { | |
// New-style URL | |
var matches = url.match(/nb\.no\/items\/([^#?;]+)/); | |
if (matches) { | |
return matches[1]; | |
} | |
// Old-style URL | |
matches = url.match(/nb\.no\/nbsok\/nb\/([^#?;]+)/); | |
if (matches) { | |
return matches[1]; | |
} | |
} | |
function mapMediaType(mediaType) { | |
var mediaTypes = { | |
'Bøker': 'book', | |
'Tidsskrift': 'book', // complete issues or volumes, not articles | |
'Aviser': 'newspaperArticle', | |
'Film': 'videoRecording', | |
'Fjernsyn': 'videoRecording', | |
'Radio': 'radioBroadcast', | |
'Kart': 'map', | |
}; | |
return mediaTypes[mediaType] || 'book'; // default to 'book' | |
} | |
function trimBrackets(obj) { | |
// Trim brackets from all values | |
Object.keys(obj).forEach(function(key) { | |
if (typeof(obj[key]) == 'string') { | |
obj[key] = obj[key].replace(/^\[/, '').replace(/\]$/, ''); | |
} | |
}); | |
return obj; | |
} | |
function extractNumPages(str) { | |
// Borrowed from Library Catalog (PICA). See #756 | |
//make sure things like 2 partition don't match, but 2 p at the end of the field do | |
// f., p., and S. are "pages" in various languages | |
// For multi-volume works, we expect formats like: | |
// x-109 p., 510 p. and X, 106 S.; 123 S. | |
var numPagesRE = /\[?\b((?:[ivxlcdm\d]+[ ,\-]*)+)\]?\s+[fps]\b/ig, | |
numPages = [], m; | |
while (m = numPagesRE.exec(str)) { | |
numPages.push(m[1].trim() | |
.replace(/[ ,\-]+/g,'+') | |
.toLowerCase() // for Roman numerals | |
); | |
} | |
return numPages.join('; '); | |
} | |
function getMODS(url, cb) { | |
ZU.doGet(url, function(text){ | |
var translator = Zotero.loadTranslator('import'); | |
translator.setTranslator('0e2235e7-babf-413c-9acf-f27cce5f059c'); | |
translator.setString(text); | |
translator.setHandler('itemDone', function(obj, item) { | |
cb(item); | |
}); | |
translator.translate(); | |
}); | |
} | |
function apiRequest(url, cb) { | |
ZU.doGet(url, function(text){ | |
var obj; | |
try { | |
obj = JSON.parse(text); | |
} catch (e) { | |
throw('Failed parsing JSON from ' + url + '.json'); | |
} | |
cb(obj); | |
}); | |
} | |
function processUrl(doc, url) { | |
var identifier = getIdentifierFromUrl(url); | |
// Note to self: the identifier can be a URN, but also sesamid or other kind of identifier | |
var modsUrl = 'https://api.nb.no/catalog/v1/metadata/' + identifier + '/mods'; | |
var apiUrl = 'https://api.nb.no/catalog/v1/items/' + identifier ; | |
// Utilize the RIS importer to prepare a mostly complete record | |
getMODS(modsUrl, function(item) { | |
item = trimBrackets(item); | |
// Concat and normalize notes | |
var note = item.notes.map(function(note) { return note.note; }) | |
.join('.\n') | |
.replace(/<\/?p>/g, '') // paragraph tags | |
.replace(/ /g, ' ') // hard spaces | |
.replace(/ +/g, ' ') // multiple spaces | |
if (note) { | |
item.notes = [{ note: note }]; | |
} | |
item.date = ZU.strToISO(item.date); | |
if (item.archiveLocation) { | |
delete item.archiveLocation; | |
} | |
if (item.callNumber) { | |
delete item.callNumber; | |
} | |
item.tags = []; | |
// Use the (undocumented) JSON api to add some data missing in the RIS export | |
apiRequest(apiUrl, function(apiResponse) { | |
var m = apiResponse.metadata; | |
item = trimBrackets(item); | |
item.numPages = extractNumPages(m.physicalDescription.extent); | |
if (item.accessDate) { | |
// Better leave this to Zotero | |
delete item.accessDate; | |
} | |
if (m.identifiers.urn) { | |
item.url = 'https://urn.nb.no/' + apiResponse.metadata.identifiers.urn; | |
} | |
if (m.series && m.series.length) { | |
item.series = m.series[0]; | |
} | |
if (m.mediaTypes && m.mediaTypes.length) { | |
item.type = mapMediaType(m.mediaTypes[0]); | |
} | |
item.complete(); | |
}); | |
}); | |
} | |
/** BEGIN TEST CASES **/ | |
var testCases = [ | |
{ | |
"type": "web", | |
"url": "https://www.nb.no/items/URN:NBN:no-nb_digibok_2013022624011", | |
"items": [ | |
{ | |
"itemType": "book", | |
"title": "Memoirs of Lewis Holberg", | |
"creators": [ | |
{ | |
"lastName": "Holberg", | |
"firstName": "Ludvig", | |
"creatorType": "author" | |
} | |
], | |
"date": "1827", | |
"libraryCatalog": "National Library of Norway", | |
"numPages": "vii+289", | |
"place": "London", | |
"publisher": "Hunt and Clarke", | |
"language": "eng; lat", | |
"series": "Autobiography : a collection of the most instructive and amusing lives ever published vol. 12", | |
"url": "https://urn.nb.no/URN:NBN:no-nb_digibok_2013022624011", | |
"attachments": [], | |
"notes": [ | |
{ | |
"note": "statement of responsibility: written by himself in Latin : and now first translated into English.\nreproduction: Elektronisk reproduksjon [Norge] Nasjonalbiblioteket Digital 2013-03-01" | |
} | |
], | |
"tags": [], | |
"seeAlso": [] | |
} | |
] | |
}, | |
{ | |
"type": "web", | |
"url": "https://www.nb.no/items/URN:NBN:no-nb_digibok_2008030304011", | |
"items": [ | |
{ | |
"itemType": "book", | |
"title": "Mat frå gard og grend: om mat og matkultur i Lesja og Gudbrandsdalen gjennom 100år", | |
"creators": [ | |
{ | |
"lastName": "Nordset", | |
"firstName": "Bjørg", | |
"creatorType": "author" | |
}, | |
{ | |
"lastName": "Lesja bondekvinnelag", | |
"fieldMode": 1, | |
"creatorType": "author" | |
} | |
], | |
"date": "1995", | |
"ISBN": "9788291375052", | |
"libraryCatalog": "National Library of Norway", | |
"numPages": "176", | |
"publisher": "Snøhetta forl.", | |
"shortTitle": "Mat frå gard og grend", | |
"url": "https://urn.nb.no/URN:NBN:no-nb_digibok_2008030304011", | |
"attachments": [], | |
"notes": [ | |
{ | |
"note": "statement of responsibility: Lesja bondekvinnelag ; red.: Bjørg Nordset ; [foto: [hovedsakelig] Bjarne Fossøy].\nOpplagshistorikk: 2. oppl. 1995; 3. oppl. 2001.\nreproduction: Elektronisk reproduksjon [Norge] Nasjonalbiblioteket Digital 2009-04-09" | |
} | |
], | |
"seeAlso": [], | |
"tags": [], | |
"place": "Lesja", | |
"language": "nob" | |
} | |
] | |
} | |
] | |
/** END TEST CASES **/ |