« Module:ZoteroItem » : différence entre les versions
Aucun résumé des modifications |
Aucun résumé des modifications |
||
| (16 versions intermédiaires par le même utilisateur non affichées) | |||
| Ligne 1 : | Ligne 1 : | ||
local p = {} | local p = {} | ||
function | -- Fonction utilitaire pour récupérer les données JSON Zotero | ||
local function fetchZoteroData(itemKey) | |||
if not itemKey or itemKey == "" then return nil end | |||
local url = string.format( | |||
"https://api.zotero.org/groups/4893620/items/%s?format=json&include=data", | |||
itemKey | |||
) | |||
local data, errors = mw.ext.externalData.getExternalData{ | |||
url = url, | |||
format = "JSON", | |||
data = { json = "__json" } | |||
} | |||
if errors or not data or not data.json then | |||
return nil | |||
end | |||
return data.json | |||
end | |||
-- Fonction utilitaire de formatage | |||
local function htmlDecode(str) | |||
if not str then return nil end | |||
return str | |||
:gsub(":", ":") | |||
:gsub("[", "[") | |||
:gsub("]", "]") | |||
:gsub(""", '"') | |||
:gsub("&", "&") | |||
end | |||
-- Fonction générique pour retourner un champ simple | |||
local function getField(frame, path) | |||
local itemKey = frame.args[1] | |||
local data = fetchZoteroData(itemKey) | |||
if not data then return "" end | |||
local current = data | |||
for _, key in ipairs(path) do | |||
if type(current) ~= "table" or current[key] == nil then | |||
return "" | |||
end | |||
current = current[key] | |||
end | |||
return mw.text.nowiki(tostring(current)) | |||
end | |||
-- Fonctions individuelles | |||
function p.key(frame) | |||
return getField(frame, { "key" }) | |||
end | |||
function p.alternateLink(frame) | |||
local data = fetchZoteroData(frame.args[1]) | |||
if data and data.links and data.links.alternate and data.links.alternate.href then | |||
return htmlDecode(data.links.alternate.href) | |||
end | |||
return "" | |||
end | |||
function p.caseName(frame) | |||
return getField(frame, { "data", "caseName" }) | |||
end | |||
function p.abstractNote(frame) | |||
return getField(frame, { "data", "abstractNote" }) | |||
end | |||
function p.court(frame) | |||
return getField(frame, { "data", "court" }) | |||
end | |||
function p.dateDecided(frame) | |||
return getField(frame, { "data", "dateDecided" }) | |||
end | |||
function p.docketNumber(frame) | |||
return getField(frame, { "data", "docketNumber" }) | |||
end | |||
function p.reporter(frame) | |||
return getField(frame, { "data", "reporter" }) | |||
end | |||
function p.reporterVolume(frame) | |||
return getField(frame, { "data", "reporterVolume" }) | |||
end | |||
function p.firstPage(frame) | |||
return getField(frame, { "data", "firstPage" }) | |||
end | |||
function p.history(frame) | |||
return getField(frame, { "data", "history" }) | |||
end | |||
function p.language(frame) | |||
return getField(frame, { "data", "language" }) | |||
end | |||
function p.shortTitle(frame) | |||
return getField(frame, { "data", "shortTitle" }) | |||
end | |||
function p.url(frame) | |||
local data = fetchZoteroData(frame.args[1]) | |||
if data and data.data and data.data.url then | |||
return htmlDecode(data.data.url) | |||
end | |||
return "" | |||
end | |||
function p.rights(frame) | |||
return getField(frame, { "data", "rights" }) | |||
end | |||
function p.extra(frame) | |||
return getField(frame, { "data", "extra" }) | |||
end | |||
local function trimDate(dateStr) | |||
if type(dateStr) == "string" then | |||
return mw.text.nowiki(dateStr:sub(1, 10)) | |||
end | |||
return "" | |||
end | |||
function p.dateAdded(frame) | |||
local data = fetchZoteroData(frame.args[1]) | |||
if not data or not data.data or not data.data.dateAdded then return "" end | |||
return trimDate(data.data.dateAdded) | |||
end | |||
function p.dateModified(frame) | |||
local data = fetchZoteroData(frame.args[1]) | |||
if not data or not data.data or not data.data.dateModified then return "" end | |||
return trimDate(data.data.dateModified) | |||
end | |||
function p.accessDate(frame) | |||
local data = fetchZoteroData(frame.args[1]) | |||
if not data or not data.data or not data.data.accessDate then return "" end | |||
return trimDate(data.data.accessDate) | |||
end | |||
-- Créateurs (formaté en liste de noms complets) | |||
function p.creators(frame) | |||
local itemKey = frame.args[1] | |||
local data = fetchZoteroData(itemKey) | |||
if not data or not data.data or not data.data.creators then return "" end | |||
local authors = {} | |||
for _, c in ipairs(data.data.creators) do | |||
local name = c.name or ((c.firstName or "") .. " " .. (c.lastName or "")) | |||
if name ~= "" then | |||
table.insert(authors, mw.text.nowiki(name)) | |||
end | |||
end | |||
return table.concat(authors, ", ") | |||
end | |||
-- Tags | |||
function p.tags(frame) | |||
local itemKey = frame.args[1] | |||
local data = fetchZoteroData(itemKey) | |||
if not data or not data.data or not data.data.tags then return "" end | |||
local tags = {} | |||
for _, t in ipairs(data.data.tags) do | |||
if t.tag then | |||
table.insert(tags, mw.text.nowiki(t.tag)) | |||
end | |||
end | |||
return table.concat(tags, ", ") | |||
end | |||
-- Collections | |||
function p.collections(frame) | |||
local itemKey = frame.args[1] | |||
local data = fetchZoteroData(itemKey) | |||
if not data or not data.data or not data.data.collections then return "" end | |||
if #data.data.collections == 0 then return "" end | |||
local out = {} | |||
for _, id in ipairs(data.data.collections) do | |||
table.insert(out, mw.text.nowiki(id)) | |||
end | |||
return table.concat(out, ", ") | |||
end | |||
-- Relations | |||
function p.relations(frame) | |||
local itemKey = frame.args[1] | |||
local groupName = "alcolois" | |||
local groupId = "4893620" | |||
local data = fetchZoteroData(itemKey) | |||
if not data or not data.data or not data.data.relations then return "" end | |||
local rel = data.data.relations | |||
local urls = {} | |||
for k, v in pairs(rel) do | |||
if k == "dc:relation" then | |||
if type(v) == "string" then | |||
local id = v:match("/items/(%w+)$") | |||
if id then | |||
table.insert(urls, string.format( | |||
"https://www.zotero.org/groups/%s/%s/items/%s", | |||
groupId, groupName, id | |||
)) | |||
end | |||
elseif type(v) == "table" then | |||
for _, url in ipairs(v) do | |||
local id = tostring(url):match("/items/(%w+)$") | |||
if id then | |||
table.insert(urls, string.format( | |||
"https://www.zotero.org/groups/%s/%s/items/%s", | |||
groupId, groupName, id | |||
)) | |||
end | |||
end | |||
end | |||
end | |||
end | |||
return table.concat(urls, ", ") | |||
end | end | ||
function p.notes(frame) | |||
local itemKey = frame.args[1] | |||
if not itemKey or itemKey == "" then return "" end | |||
local url = string.format( | |||
"https://api.zotero.org/groups/4893620/items/%s/children?format=json&include=data", | |||
mw.uri.encode(itemKey) | |||
) | |||
local data, errors = mw.ext.externalData.getExternalData{ | |||
url = url, | |||
format = "JSON", | |||
data = { notes = "__json" } | |||
} | |||
if errors or not data or not data.notes then | |||
return "" | |||
end | |||
local output = {} | |||
for _, item in ipairs(data.notes) do | |||
if item.data and item.data.itemType == "note" then | |||
local rawHtml = item.data.note or "" | |||
local url = (item.links and item.links.alternate and item.links.alternate.href) or "" | |||
-- Étape 1 : supprimer tout sauf les balises autorisées | |||
-- Autorisé : <p>, </p>, <h1>, </h1>, <a href="...">, </a> | |||
local cleaned = rawHtml:gsub('<(.-)>', function(tag) | |||
-- Cas <a href="..."> | |||
if tag:match('^a%s+href=') then | |||
return "<" .. tag .. ">" | |||
end | |||
-- Cas </a>, <p>, </p>, <h1>, </h1> | |||
if tag == "/a" or tag == "p" or tag == "/p" or tag == "h1" or tag == "/h1" then | |||
return "<" .. tag .. ">" | |||
end | |||
-- Sinon : supprimer | |||
return "" | |||
end) | |||
if cleaned ~= "" then | |||
table.insert(output, cleaned) | |||
end | |||
if url ~= "" then | |||
table.insert(output, url) | |||
end | |||
end | |||
end | |||
return table.concat(output, "\n\n") | |||
end | |||
return p | return p | ||