diff --git a/CISG-Online.js b/CISG-Online.js new file mode 100644 index 00000000000..0137747739d --- /dev/null +++ b/CISG-Online.js @@ -0,0 +1,551 @@ +{ + "translatorID": "045d1f03-d17b-4437-9290-d3a4203c4cbc", + "label": "CISG-Online", + "creator": "Jonas Zaugg", + "target": "^https?://cisg-online\\.org/", + "minVersion": "5.0", + "maxVersion": "", + "priority": 100, + "inRepository": true, + "translatorType": 4, + "browserSupport": "gcsibv", + "lastUpdated": "2024-10-01 16:50:52" +} + +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2023 Jonas Zaugg + + 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 ***** +*/ + + +function detectWeb(doc, url) { + if (url.includes('caseId=')) { + return 'case'; + } + else if (url.includes('search-for-cases')) { + // Only present on search form, not on top 50 pages + let searchResultsContainer = doc.querySelector('#searchCaseResult'); + if (searchResultsContainer) Z.monitorDOMChanges(searchResultsContainer); + if (getSearchResults(doc, true)) { + return 'multiple'; + } + } + return false; +} + +function getSearchResults(doc, checkOnly) { + var items = {}; + var found = false; + let selector = '.search-result a.search-result-link'; + var rows = doc.querySelectorAll(selector); + 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') { + 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); + } +} + +// Turns a two-item row into a formatted label/value pair +function labellize(row) { + let segments = row.querySelectorAll("div"); + if (segments.length != 2) { + return null; + } + + return "" + ZU.trimInternal(segments[0].textContent) + ": " + ZU.trimInternal(segments[1].textContent); +} + +function getRow(doc, sectionName, rowName) { + // the :not selector is to avoid selecting the drop-down rows + let selector = `div.${sectionName}-rows div.row:not([data-has-content]):not([data-is-content])`; + let rows = doc.querySelectorAll(selector); + let result; + for (let row of rows) { + if (row.textContent.includes(rowName)) return row.children[1]; + } + return result; +} + +function getRowText(doc, sectionName, rowName) { + let row = getRow(doc, sectionName, rowName); + return row ? ZU.trimInternal(row.textContent) : ""; +} + +// For sellers, buyers, claimants, respondents but not history +function getDataBlock(doc, selector, label) { + let blocks = doc.querySelectorAll(`div[data-is-content='${selector}'] div.is-content`); + + if (!blocks.length) return null; + + let result = ""; + for (let block of blocks) { + result += `

${label}

\n"; + } + return result; +} + +// For case history +function getCaseHistory(doc) { + let cases = doc.querySelectorAll(`div[data-is-content='history'] div.is-content-history`); + if (!cases.length) return null; + + let result = "

Case History

\n"; + return result; +} + +function getInfoBlock(doc, selector, label) { + let rows = doc.querySelectorAll(`.${selector}-rows > .row:not([data-has-content]):not([data-is-content])`); + if (!rows.length) return null; + + let result = `

${label}

"; + return result; +} + +function getContentCases(doc, selector) { + return doc.querySelectorAll(`div[data-is-content='${selector}'] .is-content-cases`); +} + +function addPDFs(doc, item) { + // Decision or abstract in PDF + let caseFiles = getContentCases(doc, 'fullTextTranslationFiles'); + for (let caseFile of caseFiles) { + let caseFileName = ZU.trimInternal(caseFile.textContent); + let caseFileAnchor = caseFile.querySelector("a"); + if (caseFileAnchor) { + item.attachments.push({ + title: caseFileName, + mimeType: "application/pdf", + url: caseFileAnchor.href + }); + } + } +} + +function getCISGCases(doc, selector, label) { + let cases = getContentCases(doc, selector); + if (!cases.length) return null; + + let note = `

${label} ${cases.length} case(s)

"; + return note; +} + +function getCommentExtras(doc, item, selector, label) { + let extras = getContentCases(doc, selector); + if (!extras.length) return null; + + let note = `

${label}

"; + return note; +} + +function addNote(item, note) { + if (note) item.notes.push({ note: note }); +} + +// Takes a string of judge names (with role in brackets) and returns a list of authors +/*function judgeCleanup(judges) { + return judges.split(", ").map(function (judge) { + let cleanJudge = judge.replace(/\s?\([^)]*\)/, ''); + return ZU.cleanAuthor(cleanJudge, 'author', false); + }); +}*/ + +async function scrape(doc, url = doc.location.href) { + // General + let eprint = getRowText(doc, "general-information", "CISG-online number"); + let caseName = getRowText(doc, "general-information", "Case name"); + let tribunal = getRowText(doc, "general-information", "Arbitral Tribunal"); + let court = getRowText(doc, "general-information", "Court"); + let jurisdiction = getRowText(doc, "general-information", "Jurisdiction"); + let judges = getRowText(doc, "general-information", "Judge"); // Also for Judges + let seat = getRowText(doc, "general-information", "Seat of the arbitration"); + let date = getRowText(doc, "general-information", "Date of decision"); + let docket = getRowText(doc, "general-information", "Case nr./docket nr."); + let claimants = getDataBlock(doc, "claimants", "Claimant"); + let respondents = getDataBlock(doc, "respondants", "Respondent"); // sic + let caseHistory = getCaseHistory(doc); + // +Chamber + + // Contract + let contractInfo = getInfoBlock(doc, 'contract-information', 'Contract information'); + let sellers = getDataBlock(doc, "sellers", "Seller"); + let buyers = getDataBlock(doc, "buyers", "Buyer"); + if (sellers) contractInfo += sellers; + if (buyers) contractInfo += buyers; + + // Decision info and comment + let decisionInfo = getInfoBlock(doc, 'decision-information', 'Decision information'); + let comment = getInfoBlock(doc, 'comment', 'Comments'); + + var item = new Z.Item('case'); + + item.caseName = caseName; + item.court = court ? court : tribunal; + item.country = jurisdiction ? jurisdiction : seat; + item.dateDecided = ZU.strToISO(date); + item.docketNumber = docket; + item["CISG-Online"] = eprint; + + //if (judges) judgeCleanup(judges).forEach(j => item.creators.push(j)); + + // Add decision information and comments + addNote(item, decisionInfo); + comment = comment ? comment : "

Comments

"; + let publishedIn = getCommentExtras(doc, item, 'publishedIn', 'Decision published in'); + if (publishedIn) comment += publishedIn; + let decisionComments = getCommentExtras(doc, item, 'decisionComments', 'Comment(s) on this decision'); + if (decisionComments) comment += decisionComments; + addNote(item, comment); + + // Add notes for CISG-Online cases that this case cites or where this case is cited + addNote(item, getCISGCases(doc, 'citedCISGs', 'Cites')); + addNote(item, getCISGCases(doc, 'citedBY', 'Cited by')); + + // Add all abstracts and full-text PDFs + addPDFs(doc, item); + + item.url = url; + + //item.notes.push({ note: decisionInfo }); + + // General information + if (judges || claimants || respondents || caseHistory) { + let generalInfo = "

General information

"; + if (claimants) generalInfo += claimants + "\n"; + if (respondents) generalInfo += respondents + "\n"; + if (judges) generalInfo += "

Judge(s)

" + judges + "\n"; + if (caseHistory) generalInfo += caseHistory + "\n"; + addNote(item, generalInfo); + } + + if (contractInfo || sellers || buyers) addNote(item, contractInfo); + + item.complete(); +} + +/** BEGIN TEST CASES **/ +var testCases = [ + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases?caseId=14425", + "items": [ + { + "itemType": "case", + "caseName": "Brands International Corporation v. Reach Companies, LLC", + "creators": [], + "dateDecided": "2023-10-02", + "court": "U.S. District Court for the District of Minnesota", + "docketNumber": "21-1026 (JRT/DLM)", + "url": "https://cisg-online.org/search-for-cases?caseId=14425", + "attachments": [ + { + "title": "Full text of decision Original language: English", + "mimeType": "application/pdf" + } + ], + "tags": [], + "notes": [ + { + "note": "

Decision information

" + }, + { + "note": "

Comments

Decision published in

" + }, + { + "note": "

Cites 4 case(s)

" + }, + { + "note": "

General information

Claimant

\n\n

Respondent

\n\n

Judge(s)

John R. Tunheim (District Judge)\n

Case History

\n\n" + }, + { + "note": "

Contract information

Seller

\n

Buyer

\n" + } + ], + "seeAlso": [] + } + ] + }, + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases/50-most-recently-added-cases", + "items": "multiple" + }, + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases?caseId=14276", + "items": [ + { + "itemType": "case", + "caseName": "Alcala v. Verbruggen Palletizing Solutions, Inc.", + "creators": [], + "dateDecided": "2023-06-14", + "court": "Supreme Court of the State of Idaho", + "docketNumber": "49473, 49474", + "url": "https://cisg-online.org/search-for-cases?caseId=14276", + "attachments": [ + { + "title": "Full text of decision Original language: English", + "mimeType": "application/pdf" + } + ], + "tags": [], + "notes": [ + { + "note": "

Decision information

" + }, + { + "note": "

Comments

Decision published in

" + }, + { + "note": "

Cites 1 case(s)

" + }, + { + "note": "

General information

Judge(s)

G. Richard Bevan (Presiding Judge), Robyn Brody (Reporting judge), Colleen Zahn (Judge), Gregory W. Moeller (Judge), John Stegner (Judge)\n" + } + ], + "seeAlso": [] + } + ] + }, + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases?caseId=6714", + "items": [ + { + "itemType": "case", + "caseName": "Organic barley case", + "creators": [], + "dateDecided": "2002-11-13", + "court": "Oberlandesgericht München (Court of Appeal Munich)", + "docketNumber": "27 U 346/02", + "url": "https://cisg-online.org/search-for-cases?caseId=6714", + "attachments": [ + { + "title": "Comment(s) on this decision", + "mimeType": "application/pdf" + }, + { + "title": "Full text of decision Original language: German", + "mimeType": "application/pdf" + } + ], + "tags": [], + "notes": [ + { + "note": "

Decision information

" + }, + { + "note": "

Comments

Decision published in

Comment(s) on this decision

" + }, + { + "note": "

Cited by 1 case(s)

" + }, + { + "note": "

General information

Claimant

\n\n

Respondent

\n\n

Judge(s)

Prof. Dr. Motzke (Presiding Judge), von Hofer (Judge), Dr. Ermer (Judge)\n

Case History

\n\n" + }, + { + "note": "

Contract information

Seller

\n

Buyer

\n" + } + ], + "seeAlso": [] + } + ] + }, + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases?caseId=7035", + "items": [ + { + "itemType": "case", + "caseName": "Dioctyl phthalate case", + "creators": [], + "dateDecided": "1996-08-16", + "court": "China International Economic & Trade Arbitration Commission (CIETAC)", + "docketNumber": "CISG/1996/39", + "url": "https://cisg-online.org/search-for-cases?caseId=7035", + "attachments": [ + { + "title": "Translation of decision Language: English translated by Meihua Xu", + "mimeType": "application/pdf" + } + ], + "tags": [], + "notes": [ + { + "note": "

Decision information

" + }, + { + "note": "

Comments

" + }, + { + "note": "

General information

Claimant

\n\n

Respondent

\n\n" + }, + { + "note": "

Contract information

Seller

\n

Buyer

\n" + } + ], + "seeAlso": [] + } + ] + }, + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases?caseId=8138", + "items": [ + { + "itemType": "case", + "caseName": "MSS, Inc. v. Maser Corp.", + "creators": [], + "dateDecided": "2011-07-18", + "court": "U.S. District Court for the District of Maryland", + "docketNumber": "3:09-cv-00601", + "url": "https://cisg-online.org/search-for-cases?caseId=8138", + "attachments": [ + { + "title": "Full text of decision Original language: English", + "mimeType": "application/pdf" + } + ], + "tags": [], + "notes": [ + { + "note": "

Decision information

" + }, + { + "note": "

Comments

Comment(s) on this decision

" + }, + { + "note": "

Cites 3 case(s)

" + }, + { + "note": "

General information

Claimant

\n\n

Respondent

\n\n

Judge(s)

John T. Nixon (Sole judge)\n" + }, + { + "note": "

Contract information

Seller

\n

Buyer

\n

Buyer

\n" + } + ], + "seeAlso": [] + } + ] + }, + { + "type": "web", + "url": "https://cisg-online.org/search-for-cases?caseId=14193", + "items": [ + { + "itemType": "case", + "caseName": "Brands International Corporation v. Reach Companies, LLC", + "creators": [], + "dateDecided": "2023-04-11", + "court": "U.S. District Court for the District of Minnesota", + "docketNumber": "0:2021cv01026", + "url": "https://cisg-online.org/search-for-cases?caseId=14193", + "attachments": [ + { + "title": "Full text of decision Original language: English", + "mimeType": "application/pdf" + } + ], + "tags": [], + "notes": [ + { + "note": "

Decision information

" + }, + { + "note": "

Comments

" + }, + { + "note": "

Cites 5 case(s)

" + }, + { + "note": "

Cited by 1 case(s)

" + }, + { + "note": "

General information

Claimant

\n\n

Respondent

\n\n

Judge(s)

John R. Tunheim (Sole judge)\n

Case History

\n\n" + }, + { + "note": "

Contract information

Seller

\n

Buyer

\n" + } + ], + "seeAlso": [] + } + ] + } +] +/** END TEST CASES **/