zotero/translators/Bibliotheque nationale de F...

873 lines
21 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"translatorID": "47533cd7-ccaa-47a7-81bb-71c45e68a74d",
"label": "Bibliothèque nationale de France",
"creator": "Florian Ziche, Sylvain Machefert",
"target": "^https?://[^/]*catalogue\\.bnf\\.fr",
"minVersion": "3.0",
"maxVersion": "",
"priority": 100,
"inRepository": true,
"translatorType": 4,
"browserSupport": "gcsibv",
"lastUpdated": "2024-01-09 03:40:58"
}
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2010-2024 Florian Ziche, Sylvain Machefert
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 *****
*/
/* Bnf namespace. */
var BnfClass = function () {
// Private members
/* Map MARC responsibility roles to Zotero creator types.
See http://archive.ifla.org/VI/3/p1996-1/appx-c.htm.
*/
function getCreatorType(aut) {
// To avoid an error on certain pages where the item is not well catalogued
if (aut['4'] === undefined) return undefined;
var typeAut = aut['4'].trim();
switch (typeAut) {
case "005":
case "250":
case "275":
case "590": // performer
case "755": // vocalist
return "performer";
case "040":
case "130": // book designer
case "740": // type designer
case "750": // typographer
case "350": // engraver
case "360": // etcher
case "430": // illuminator
case "440": // illustrator
case "510": // lithographer
case "530": // metal engraver
case "600": // photographer
case "705": // sculptor
case "760": // wood engraver
return "artist";
case "070":
case "305":
case "330":
case undefined:
return "author";
case "020":
case "210":
case "212":
return "commenter";
case "180":
return "cartographer";
case "220":
case "340":
return "editor";
case "230":
return "composer";
case "245":
return "inventor";
case "255":
case "695": // scientific advisor
case "727": // thesis advisor
return "counsel";
case "300":
return "director";
case "400": // funder
case "723": // sponsor
return "sponsor";
case "460":
return "interviewee";
case "470":
return "interviewer";
case "480": // librettist
case "520": // lyricist
return "wordsBy";
case "605":
return "presenter";
case "630":
return "producer";
case "635":
return "programmer";
case "660":
return "recipient";
case "090": // author of dialog
case "690": // scenarist
return "scriptwriter";
case "730":
return "translator";
// Ignore (no matching Zotero creatorType):
case "320": // donor
case "610": // printer
case "650": // publisher
return undefined;
// Default
case "205":
default:
return "contributor";
}
}
/* Fix creators (MARC translator is not perfect). */
function getCreators(record, item) {
// Clear creators
item.creators = [];
// Extract creators (700, 701 & 702)
for (let i = 700; i < 703; i++) {
let authorTag = record.getFieldSubfields(i);
for (let j in authorTag) {
let aut = authorTag[j];
let authorText = "";
if (aut.b) {
authorText = aut.a + ", " + aut.b;
}
else {
authorText = aut.a;
}
let type = getCreatorType(aut);
if (type) {
item.creators.push(Zotero.Utilities.cleanAuthor(authorText, type, true));
}
}
}
// Extract corporate creators (710, 711 & 712)
for (let i = 710; i < 713; i++) {
let authorTag = record.getFieldSubfields(i);
for (let j in authorTag) {
if (authorTag[j].a) {
let type = getCreatorType(authorTag[j]);
if (type) {
item.creators.push({
lastName: authorTag[j].a,
creatorType: type,
fieldMode: true
});
}
}
}
}
}
// Add tag, if not present yet
function addTag(item, tag) {
for (var t in item.tags) {
if (item.tags[t] == tag) {
return;
}
}
item.tags.push(tag);
}
// Tagging
function getTags(record, item) {
var pTag = record.getFieldSubfields("600");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
if (person.b) {
tagText += ", " + person.b;
}
if (person.c) {
tagText += ", " + person.c;
}
if (person.f) {
tagText += " (" + person.f + ")";
}
addTag(item, tagText);
}
}
pTag = record.getFieldSubfields("601");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
addTag(item, tagText);
}
}
pTag = record.getFieldSubfields("605");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
addTag(item, tagText);
}
}
pTag = record.getFieldSubfields("606");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
addTag(item, tagText);
}
}
pTag = record.getFieldSubfields("607");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
addTag(item, tagText);
}
}
pTag = record.getFieldSubfields("602");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
if (person.f) {
tagText += " (" + person.f + ")";
}
addTag(item, tagText);
}
}
pTag = record.getFieldSubfields("604");
if (pTag) {
for (let j in pTag) {
let tagText = false;
let person = pTag[j];
tagText = person.a;
if (person.b) {
tagText += ", " + person.b;
}
if (person.f) {
tagText += " (" + person.f + ")";
}
if (person.t) {
tagText += ", " + person.t;
}
addTag(item, tagText);
}
}
}
// Get series (repeatable)
function getSeries(record, item) {
var seriesText = false;
var seriesTag = record.getFieldSubfields("225");
if (seriesTag && seriesTag.length > 1) {
for (let j in seriesTag) {
let series = seriesTag[j];
if (seriesText) {
seriesText += "; ";
}
else {
seriesText = "";
}
seriesText += series.a;
if (series.v) {
seriesText += ", " + series.v;
}
}
if (seriesText) {
delete item.seriesNumber;
item.series = seriesText;
}
}
// Try 461
if (!item.series) {
seriesTag = record.getFieldSubfields("461");
if (seriesTag) {
for (let j in seriesTag) {
let series = seriesTag[j];
if (seriesText) {
seriesText += "; ";
}
else {
seriesText = "";
}
seriesText += series.t;
}
}
if (seriesText) {
delete item.seriesNumber;
item.series = seriesText;
}
}
}
// Add extra text
function addExtra(noteText, extra) {
if (extra) {
if (noteText) {
if (!/\.$/.exec(noteText)) {
noteText += ". ";
}
else {
noteText += " ";
}
}
else {
noteText = "";
}
noteText += Zotero.Utilities.trim(extra);
}
return noteText;
}
// Assemble extra information
function getExtra(record, item) {
var noteText = false;
// Material description
var noteTag = record.getFieldSubfields("215");
if (noteTag) {
for (let j in noteTag) {
let note = noteTag[j];
noteText = addExtra(noteText, note.c);
noteText = addExtra(noteText, note.d);
noteText = addExtra(noteText, note.e);
}
}
// Note
noteTag = record.getFieldSubfields("300");
if (noteTag) {
for (let j in noteTag) {
let note = noteTag[j];
noteText = addExtra(noteText, note.a);
}
}
// Edition history notes
noteTag = record.getFieldSubfields("305");
if (noteTag) {
for (let j in noteTag) {
let note = noteTag[j];
noteText = addExtra(noteText, note.a);
}
}
if (noteText) {
if (!/\.$/.exec(noteText)) {
noteText += ".";
}
item.extra = noteText;
}
}
// Get title from 200
function getTitle(record, item) {
var titleTag = record.getFieldSubfields("200");
if (titleTag) {
titleTag = titleTag[0];
var titleText = titleTag.a;
if (titleTag.e) {
if (!/^[,.:;-]/.exec(titleTag.e)) {
titleText += ": ";
}
titleText += titleTag.e;
}
if (titleTag.h) {
titleText += ", " + titleTag.h;
if (titleTag.i) {
titleText += ": " + titleTag.i;
}
}
else if (titleTag.i) {
titleText += ", " + titleTag.i;
}
item.title = titleText;
}
}
function getCote(record, item) {
item.callNumber = "";
var coteTag = record.getFieldSubfields("930");
if (coteTag.length) {
item.callNumber += coteTag[0].c + "-" + coteTag[0].a;
}
}
// Do BnF specific Unimarc postprocessing
function postprocessMarc(record, newItem) {
// Title
getTitle(record, newItem);
// Fix creators
getCreators(record, newItem);
// Fix callNumber
getCote(record, newItem);
// Store perennial url from 003 as attachment and accession number
var url = record.getField("003");
if (url && url.length > 0 && url[0][1]) {
newItem.attachments.push({
title: 'Lien vers la notice du catalogue',
url: url[0][1],
mimeType: 'text/html',
snapshot: false
});
}
// Country (102a)
record._associateDBField(newItem, "102", "a", "country");
// Try to retrieve volumes/pages from 215d
if (!newItem.pages) {
var dimTag = record.getFieldSubfields("215");
for (let j in dimTag) {
var dim = dimTag[j];
if (dim.a) {
var pages = /[^\d]*(\d+)\s+p\..*/.exec(dim.a);
if (pages) {
newItem.numPages = pages[1];
}
var vols = /[^\d]*(\d+)\s+vol\..*/.exec(dim.a);
if (vols) {
newItem.numberOfVolumes = vols[1];
}
}
}
}
// Series
getSeries(record, newItem);
// Extra
getExtra(record, newItem);
// Tagging
getTags(record, newItem);
// Repository
newItem.libraryCatalog = "BnF Catalogue général (http:// catalogue.bnf.fr)";
}
// Public members
// Get the UNIMARC URL for a given single result page.
this.reformURL = function (url) {
url = url.replace(/(^.*\/ark:\/12148\/cb[0-9]+[a-z]*)(.*$)/, "$1.unimarc");
// Zotero.debug("URL1 "+ url);
return url;
};
// Get the results table from a list page, if any. Looks for // table[@class="ListeNotice"].
this.getResultsTable = function (doc) {
try {
var xPathObject = ZU.xpath(doc, '// div[@class="liste-notices"]');
return xPathObject;
}
catch (x) {
Zotero.debug(x.lineNumber + " " + x.message);
}
return undefined;
};
// Get selectable search items from a list page.
// Loops through //td[@class="mn_partienoticesynthetique"], extracting the single items URLs from
// their onclick attribute, thier titles by assembling the spans for each cell.
this.getSelectedItems = function (doc) {
var items = {};
var found = false;
var rows = ZU.xpath(doc, '//div[@class="liste-notices"]/div[@class="notice-item"]/div[@class="notice-contenu"]');
for (var i = 0; i < rows.length; i++) {
var title = "";
var href = attr(rows[i], 'div[class="notice-synthese"] a', "href");
title = ZU.trim(text(rows[i], 'div[class="notice-synthese"] a'));
var documentYear = text(rows[i], 'span[class="notice-ordre"]');
if (documentYear.length == 6) {
title += " / " + documentYear;
}
if (!href || !title) continue;
found = true;
items[href] = title;
}
return found ? items : false;
};
// Check for Gallica URL (digital version available), if found, set item.url
function checkGallica(record, item) {
var url = record.getFieldSubfields("856");
if (url && url.length > 0 && url[0].u) {
item.url = url[0].u;
}
}
// Process UNIMARC URL.
this.processMarcUrl = function (newDoc, _url) {
// Init MARC record.
// Load MARC
var translator = Zotero.loadTranslator("import");
translator.setTranslator("a6ee60df-1ddc-4aae-bb25-45e0537be973");
translator.getTranslatorObject(function (obj) {
var record = new obj.record();
// Get table cell containing MARC code.
var elmts = ZU.xpath(newDoc, '//div[@class="notice-detail"]/div/div[@class="zone"]');
// Line loop.
var elmt, tag, content;
var ind = "";
for (var i = 0; i < elmts.length; i++) {
elmt = elmts[i];
var line = Zotero.Utilities.superCleanString(elmt.textContent);
if (line.length == 0) {
continue;
}
if (line.substring(0, 6) == " ") {
content += " " + line.substring(6);
continue;
}
else if (tag) {
record.addField(tag, ind, content);
}
line = line.replace(/[_\t\xA0]/g, " "); // nbsp
tag = line.substr(0, 3);
if (tag[0] != "0" || tag[1] != "0") {
ind = line.substr(3, 2);
content = line.substr(5).replace(/\$([a-z]|[0-9])/g, obj.subfieldDelimiter + "$1");
content = content.replace(/ˆ([^‰]+)‰/g, "$1");
}
else if (tag == "000") {
tag = undefined;
record.leader = "0000" + line.substr(8);
}
else {
content = line.substr(3);
}
}
// case last zone
if (tag) {
record.addField(tag, ind, content);
}
// Create item
var newItem = new Zotero.Item();
record.translate(newItem);
// Do specific Unimarc postprocessing
postprocessMarc(record, newItem);
// Check for Gallica URL
checkGallica(record, newItem);
newItem.complete();
});
};
};
/* Global BnfClass object. */
var Bnf = new BnfClass();
/* Translator API implementation. */
var typeMapping = {
"moving image": "film",
text: "book",
"printed text": "book",
"electronic resource": "book",
score: "book",
sound: "audioRecording",
"sound recording": "audioRecording",
"cartographic resource": "map",
"still image": "artwork",
kit: "document",
"modern manuscript or archive": "manuscript",
"coin or medal": "document",
"physical object": "document",
"three dimensional object": "document"
};
function detectWeb(doc, url) {
var resultRegexp = /ark:\/12148\/cb[0-9]+/i;
// Single result ?
if (resultRegexp.test(url)) {
var itemType = attr(doc, 'meta[name="DC.type"][lang="eng"]', "content");
if (typeMapping[itemType]) {
return typeMapping[itemType];
}
else {
return "document";
}
}
// Muliple result ?
else if (Bnf.getResultsTable(doc)) {
return "multiple";
}
// No items
return undefined;
}
function doWeb(doc, url) {
// Check type.
var type = detectWeb(doc, url);
Zotero.debug("type " + type);
if (!type) {
return;
}
// Build array of MARC URLs.
var urls = [];
switch (type) {
case "multiple":
var items = Bnf.getSelectedItems(doc);
if (items) {
// Let user select items
Zotero.selectItems(items, function (items) {
for (var i in items) {
urls.push(Bnf.reformURL(i));
}
if (urls.length > 0) {
// Z.debug(urls)
Zotero.Utilities.processDocuments(urls, function (doc) {
Bnf.processMarcUrl(doc, urls[0]);
});
}
});
}
break;
default:
urls = [Bnf.reformURL(url)];
Zotero.Utilities.processDocuments(urls, function (doc) {
Bnf.processMarcUrl(doc, url);
});
break;
}
}
/** BEGIN TEST CASES **/
var testCases = [
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb40636779s",
"items": [
{
"itemType": "map",
"title": "Scotia Regnum divisum in Partem Septentrionalem et Meridionalem Subdivisas in Comitatus, Vicecomitatus, Provincias, Praefecturas, Dominia et Insulas",
"creators": [
{
"firstName": "Frederick",
"lastName": "De Wit ",
"creatorType": "author"
}
],
"date": "1680",
"extra": "510 x 570. Le titre est en bas et à gauche dans un cartouche monumental décoré d'un Amour. En haut de la carte, deux Amours portent un écu aux armes de l'Ecosse. Vers 1680.",
"language": "lat",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"place": "S.l.",
"publisher": "s.n.",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [
{
"tag": " Écosse, Royaume d' (843-1707) "
}
],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb43664161m",
"items": [
{
"itemType": "book",
"title": "La déesse des petites victoires",
"creators": [
{
"firstName": "Yannick",
"lastName": "Grannec ",
"creatorType": "author"
}
],
"date": "2012",
"ISBN": "9782286093051",
"callNumber": "Tolbiac - Rez de Jardin - Littérature et art - Magasin - 2013-334011",
"extra": "couv. ill. 21 cm. Bibliogr., 3 p.",
"language": "fre",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"numPages": "468",
"numberOfVolumes": "1",
"place": "Paris",
"publisher": "le Grand livre du mois",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb39209609w",
"items": [
{
"itemType": "film",
"title": "Problèmes et pratiques : sciences de la vie et de la terre",
"creators": [],
"date": "199",
"distributor": "Centre national de documentation pédagogique",
"extra": "coul. (SECAM), son. Titre de dos : \"Sciences de la vie et de la terre, problèmes et pratiques. Notice réd. d'après un document produit en 1996.",
"language": "fre",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"shortTitle": "Problèmes et pratiques",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb40494299f",
"items": [
{
"itemType": "artwork",
"title": "[Recueil. Vues stéréoscopiques de Louis] : [photographie",
"creators": [
{
"lastName": "Louis",
"creatorType": "artist"
}
],
"extra": "formats divers. Comprend deux séries : \"Le Petit Chaperon rouge\" et \"La Belle au Bois Dormant.",
"language": "fre",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"shortTitle": "[Recueil. Vues stéréoscopiques de Louis]",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [
{
"tag": " Figurines "
},
{
"tag": " Perrault , Charles ( 1628-1703 ), La Belle au bois dormant "
},
{
"tag": " Perrault , Charles ( 1628-1703 ), Le Petit Chaperon rouge "
}
],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb39755519v",
"items": [
{
"itemType": "manuscript",
"title": "[3 lettres et 1 carte de visite d'Adolphe Aderer à Adolphe Jullien]",
"creators": [
{
"firstName": "Adolphe",
"lastName": "Aderer ",
"creatorType": "author"
},
{
"firstName": "Adolphe",
"lastName": "Jullien ",
"creatorType": "recipient"
}
],
"language": "fre",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"place": "1895-1922",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb40025449j",
"items": [
{
"itemType": "audioRecording",
"title": "The complete D singles collection : the sounds of Houston, Texas",
"creators": [],
"extra": "6 brochures.",
"label": "Bear family records",
"language": "eng",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"place": "Hambergen (Allemagne)",
"shortTitle": "The complete D singles collection",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [],
"notes": [],
"seeAlso": []
}
]
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/rechercher.do?motRecherche=test&critereRecherche=0&depart=0&facetteModifiee=ok",
"items": "multiple"
},
{
"type": "web",
"url": "https://catalogue.bnf.fr/ark:/12148/cb410374690.public",
"items": [
{
"itemType": "artwork",
"title": "Les sorcières envahissent la forêt Lespinasse : [affiche",
"creators": [],
"date": "2007",
"extra": "60 x 40 cm.",
"language": "fre",
"libraryCatalog": "BnF Catalogue général (http:// catalogue.bnf.fr)",
"shortTitle": "Les sorcières envahissent la forêt Lespinasse",
"attachments": [
{
"title": "Lien vers la notice du catalogue",
"mimeType": "text/html",
"snapshot": false
}
],
"tags": [],
"notes": [],
"seeAlso": []
}
]
}
]
/** END TEST CASES **/