Coverage for src/ptf/cmds/xml/citation_html.py: 91%

347 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-05 09:56 +0000

1from django.conf import settings 

2 

3from ptf.cmds.xml.xml_base import RefBase 

4from ptf.cmds.xml.xml_utils import make_links_clickable 

5from ptf.model_data import ContributorDict 

6from ptf.utils import get_display_name 

7 

8# Bug fixed: 

9# 1. article_title / chapter_title 

10# TODO: 02/05/2020. Restore the line in comment below. There's a bug in production 

11# # &ldquo; is inside the <span>, but &rdquo; is outside 

12# 2. authors. if there is no author, there is still a span in HTML 

13# 3. institution is ignored in citation_html (except JEP) 

14# 4. month is ignored in citation_html (except JEP) 

15# 5. series. suffix is set to '</span>' but the opening <span> is missing 

16# 6. volume JEP. ", " is inside the <span> of the volume 

17 

18 

19REF_JEP_STYLE = getattr(settings, "REF_JEP_STYLE", False) 

20REF_ALCO_STYLE = getattr(settings, "REF_ALCO_STYLE", False) 

21REF_PCJ_STYLE = getattr(settings, "REF_PCJ_STYLE", False) 

22 

23 

24def helper_decorate_text(text, prefix, suffix): 

25 if text is None or text == "": 

26 return "" 

27 

28 text = prefix + text + suffix 

29 return text 

30 

31 

32def get_html_from(tag, ref_data): 

33 text = "" 

34 

35 fct_name = "get_html_from_" + tag.replace("-", "_") 

36 if fct_name in globals() and callable(globals()[fct_name]): 

37 text += globals()[fct_name](ref_data) 

38 else: 

39 fct_name = "add_prefix_to_html_from_" + tag.replace("-", "_") 

40 if fct_name in globals() and callable(globals()[fct_name]): 40 ↛ 43line 40 didn't jump to line 43 because the condition on line 40 was always true

41 text += globals()[fct_name](ref_data) 

42 

43 fct_name = "add_span_class_to_html_from_" + tag.replace("-", "_") 

44 if fct_name in globals() and callable(globals()[fct_name]): 

45 text = globals()[fct_name](text, ref_type=ref_data.type) 

46 

47 return text 

48 

49 

50def get_html_from_authors(ref_data: RefBase): 

51 """ 

52 authors may have <etal/> that require 2 spans 

53 We cannot use the add_prefix_ then add_span_class_ functions 

54 

55 :param ref_data: 

56 :return: 

57 """ 

58 contribs = ref_data.get_authors() 

59 text = get_html_from_contribs(contribs, with_span=True) if contribs else "" 

60 

61 return text 

62 

63 

64def get_html_from_contribs(contribs: list[ContributorDict], is_editor=False, with_span=False): 

65 text = "" 

66 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

67 ref_pcj_style = getattr(settings, "REF_PCJ_STYLE", False) 

68 i = 1 

69 size = len(contribs) 

70 

71 if with_span and not is_editor: 

72 text = '<span class="citation-author">' 

73 

74 for contrib in contribs: 

75 first_name = contrib["first_name"] 

76 if (ref_jep_style or ref_pcj_style) and first_name: 

77 # JEP_STYLE: Only the first name initials are used 

78 words = first_name.split() # first_name may have multiple words 

79 initials = [] 

80 for word in words: 

81 parts = word.split("-") # a first_name may be composed (ex: "Jean-Pierre") 

82 word = "-".join([f"{part[0]}." for part in parts if part]) 

83 initials.append(word) 

84 first_name = " ".join(initials) 

85 

86 string_name = get_display_name( 

87 contrib["prefix"], 

88 first_name, 

89 contrib["last_name"], 

90 contrib["suffix"], 

91 contrib["string_name"], 

92 ) 

93 

94 if i > 1: 

95 if i == size and contrib["contrib_xml"] == "<etal/>": 95 ↛ 96line 95 didn't jump to line 96 because the condition on line 95 was never true

96 text += '</span> <span class="citation_etal">' 

97 elif i == size and ref_jep_style: 

98 text += " & " 

99 elif ref_jep_style: 99 ↛ 100line 99 didn't jump to line 100 because the condition on line 99 was never true

100 text += ", " 

101 else: 

102 text += "; " 

103 

104 if contrib["contrib_xml"] == "<etal/>": 104 ↛ 105line 104 didn't jump to line 105 because the condition on line 104 was never true

105 text += "et al." 

106 else: 

107 text += string_name 

108 i += 1 

109 

110 if is_editor: 

111 if len(contribs) > 1: 111 ↛ 114line 111 didn't jump to line 114 because the condition on line 111 was always true

112 text += ", eds." 

113 else: 

114 text += ", ed." 

115 elif with_span: 115 ↛ 118line 115 didn't jump to line 118 because the condition on line 115 was always true

116 text += "</span>" 

117 

118 return text 

119 

120 

121def get_html_from_pages(ref_data): 

122 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

123 if ref_jep_style and ref_data.type == "book": 123 ↛ 124line 123 didn't jump to line 124 because the condition on line 123 was never true

124 return "" 

125 

126 text = helper_decorate_text(ref_data.size, ", ", " pages") 

127 

128 if not text and ref_data.fpage: 

129 fpage_int = lpage_int = 0 

130 

131 try: 

132 fpage_int = int(ref_data.fpage) 

133 except ValueError: 

134 pass 

135 

136 try: 

137 lpage_int = int(ref_data.lpage) 

138 except ValueError: 

139 pass 

140 

141 if lpage_int > 0 and lpage_int - fpage_int >= 1 and not ref_jep_style: 

142 text += ", pp. " 

143 else: 

144 text += ", p. " 

145 

146 text += ref_data.fpage 

147 if ref_data.lpage: 

148 text += "-" + ref_data.lpage 

149 

150 if not text and ref_data.page_range: 

151 prefix = ", pp. " 

152 suffix = "" 

153 if ref_jep_style: 153 ↛ 154line 153 didn't jump to line 154 because the condition on line 153 was never true

154 prefix = ", p. " 

155 text += helper_decorate_text(ref_data.page_range, prefix, suffix) 

156 

157 return text 

158 

159 

160def get_html_from_source(ref_data): 

161 with_article_or_chapter_title = ref_data.article_title_tex or ref_data.chapter_title_tex 

162 value_html = add_prefix_to_html_from_source(ref_data) 

163 text = add_span_class_to_html_from_source( 

164 value_html, 

165 ref_type=ref_data.type, 

166 with_article_or_chapter_title=with_article_or_chapter_title, 

167 ) 

168 

169 return text 

170 

171 

172def add_prefix_to_html_from_annotation(ref_data): 

173 if ref_data.type in ["phdthesis", "masterthesis", "mastersthesis"]: 

174 prefix = ", " 

175 suffix = "" 

176 else: 

177 prefix = " (" 

178 suffix = ")" 

179 

180 text = helper_decorate_text(ref_data.annotation, prefix, suffix) 

181 return text 

182 

183 

184def add_prefix_to_html_from_article_title(ref_data): 

185 prefix = " " 

186 suffix = "" 

187 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

188 

189 if ref_jep_style: 189 ↛ 190line 189 didn't jump to line 190 because the condition on line 189 was never true

190 prefix = " - &ldquo;" 

191 suffix = "&rdquo;" 

192 

193 text = helper_decorate_text(ref_data.article_title_tex, prefix, suffix) 

194 return text 

195 

196 

197def add_prefix_to_html_from_authors(ref_data: RefBase): 

198 contribs = ref_data.get_authors() 

199 text = get_html_from_contribs(contribs) if contribs else "" 

200 return text 

201 

202 

203def add_prefix_to_html_from_chapter_title(ref_data): 

204 prefix = " " 

205 suffix = "" 

206 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

207 

208 if ref_jep_style: 

209 prefix = " - &ldquo;" 

210 suffix = "&rdquo;" 

211 

212 text = helper_decorate_text(ref_data.chapter_title_tex, prefix, suffix) 

213 return text 

214 

215 

216def add_prefix_to_html_from_comment(ref_data): 

217 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

218 

219 if ref_jep_style: 

220 prefix = ", " 

221 suffix = "" 

222 else: 

223 if "(" in ref_data.comment: 

224 prefix = " " 

225 suffix = "" 

226 else: 

227 prefix = " (" 

228 suffix = ")" 

229 

230 text = helper_decorate_text(ref_data.comment, prefix, suffix) 

231 return text 

232 

233 

234def add_prefix_to_html_from_editors(ref_data): 

235 contribs = ref_data.get_editors() 

236 text = get_html_from_contribs(contribs, is_editor=True) if contribs else "" 

237 text = helper_decorate_text(text, " (", ")") 

238 return text 

239 

240 

241def add_prefix_to_html_from_eids(ref_data): 

242 text = "" 

243 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

244 

245 for extid in ref_data.extids: 

246 if extid[0] == "eid": 

247 if ref_jep_style: 247 ↛ 248line 247 didn't jump to line 248 because the condition on line 247 was never true

248 text += ", article ID " + extid[1] 

249 elif REF_ALCO_STYLE: 249 ↛ 250line 249 didn't jump to line 250 because the condition on line 249 was never true

250 text += ", Paper no. " + extid[1] 

251 else: 

252 text += ", " + extid[1] 

253 return text 

254 

255 

256def add_prefix_to_html_from_ext_links(ref_data): 

257 text = "" 

258 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

259 

260 for link in ref_data.ext_links: 

261 href = link["location"] 

262 

263 # bibitem with ext-links pointing to numdam.org have a numdam-id 

264 # ext-links to doi.org are transformed in an extid 

265 # We can ignore both cases 

266 if "www.numdam.org" not in href and "doi.org" not in href and not ref_jep_style: 

267 href = make_links_clickable(href, link["metadata"]) 

268 text += " " + href 

269 return text 

270 

271 

272def add_prefix_to_html_from_institution(ref_data): 

273 text = helper_decorate_text(ref_data.institution, ", ", "") 

274 return text 

275 

276 

277def add_prefix_to_html_from_label(ref_data): 

278 text = helper_decorate_text(ref_data.label, "", " ") 

279 return text 

280 

281 

282def add_prefix_to_html_from_month(ref_data): 

283 text = helper_decorate_text(ref_data.month, ", ", "") 

284 return text 

285 

286 

287def add_prefix_to_html_from_number(ref_data): 

288 text = helper_decorate_text(ref_data.issue, " no. ", "") 

289 return text 

290 

291 

292def add_prefix_to_html_from_publisher(ref_data): 

293 text = helper_decorate_text(ref_data.publisher_name, ", ", "") 

294 text += helper_decorate_text(ref_data.publisher_loc, ", ", "") 

295 return text 

296 

297 

298def add_prefix_to_html_from_series(ref_data): 

299 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

300 

301 if ref_data.chapter_title_tex or ref_data.article_title_tex: 

302 if ref_jep_style and ref_data.type == "incollection": 

303 prefix = ", " 

304 suffix = "" 

305 else: 

306 prefix = " (" 

307 suffix = ")" 

308 else: 

309 prefix = ", " 

310 suffix = "" 

311 

312 text = helper_decorate_text(ref_data.series, prefix, suffix) 

313 return text 

314 

315 

316def add_prefix_to_html_from_source(ref_data): 

317 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

318 ref_pcj_style = getattr(settings, "REF_PCJ_STYLE", False) 

319 if ref_data.article_title_tex or ref_data.chapter_title_tex: 

320 if ref_jep_style and ref_data.type == "incollection": 

321 prefix = ", in " 

322 elif ref_pcj_style and ref_data.type == "inbook": 322 ↛ 323line 322 didn't jump to line 323 because the condition on line 322 was never true

323 prefix = " In: " 

324 else: 

325 prefix = ", " 

326 suffix = "" 

327 else: 

328 prefix = " " 

329 suffix = "" 

330 

331 if ref_jep_style: 331 ↛ 332line 331 didn't jump to line 332 because the condition on line 331 was never true

332 prefix = " - " 

333 if ref_data.type in ["unpublished", "misc"]: 

334 prefix += "&ldquo;" 

335 suffix = "&rdquo;" 

336 

337 text = helper_decorate_text(ref_data.source_tex, prefix, suffix) 

338 return text 

339 

340 

341def add_prefix_to_html_from_volume(ref_data): 

342 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

343 

344 if ref_jep_style: 

345 if ref_data.type in ["incollection", "book"]: 345 ↛ 348line 345 didn't jump to line 348 because the condition on line 345 was always true

346 prefix = ", vol. " 

347 else: 

348 prefix = " " 

349 else: 

350 if ref_data.article_title_tex or ref_data.chapter_title_tex: 

351 prefix = ", Volume " 

352 else: 

353 prefix = ", " 

354 

355 text = helper_decorate_text(ref_data.volume, prefix, "") 

356 return text 

357 

358 

359def add_prefix_to_html_from_year(ref_data): 

360 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

361 

362 if ref_jep_style and ref_data.type in ["phdthesis", "masterthesis", "mastersthesis"]: 362 ↛ 363line 362 didn't jump to line 363 because the condition on line 362 was never true

363 prefix = ", " if ref_data.month == "" else " " 

364 suffix = "" 

365 elif ref_data.type in ["incollection", "book", "misc"]: 

366 prefix = ", " 

367 suffix = "" 

368 else: 

369 prefix = " (" 

370 suffix = ")" 

371 

372 text = helper_decorate_text(ref_data.year, prefix, suffix) 

373 return text 

374 

375 

376def add_span_class_to_html_from_article_title(value_html, **kwargs): 

377 text = helper_decorate_text(value_html, '<span class="citation-document-title">', "</span>") 

378 return text 

379 

380 

381def add_span_class_to_html_from_authors(value_html, **kwargs): 

382 text = helper_decorate_text(value_html, '<span class="citation-author">', "</span>") 

383 return text 

384 

385 

386def add_span_class_to_html_from_chapter_title(value_html, **kwargs): 

387 text = helper_decorate_text(value_html, '<span class="citation-document-title">', "</span>") 

388 return text 

389 

390 

391def add_span_class_to_html_from_series(value_html, **kwargs): 

392 # TODO: Check JEP for series (not span except for books: citation-publication-title-book (not found in CSS) 

393 text = helper_decorate_text(value_html, '<span class="citation-series">', "</span>") 

394 return text 

395 

396 

397def add_span_class_to_html_from_source(value_html, **kwargs): 

398 suffix = "</span>" 

399 

400 if "with_article_or_chapter_title" not in kwargs or kwargs["with_article_or_chapter_title"]: 

401 prefix = '<span class="citation-publication-title">' 

402 else: 

403 prefix = '<span class="citation-document-title">' 

404 

405 text = helper_decorate_text(value_html, prefix, suffix) 

406 return text 

407 

408 

409def add_span_class_to_html_from_volume(value_html, **kwargs): 

410 ref_jep_style = getattr(settings, "REF_JEP_STYLE", False) 

411 

412 if ref_jep_style and "ref_type" in kwargs and kwargs["ref_type"] in ["incollection", "book"]: 

413 text = helper_decorate_text( 

414 value_html, '<span class="citation-volume-incollection">', "</span>" 

415 ) 

416 else: 

417 text = helper_decorate_text(value_html, '<span class="citation-volume">', "</span>") 

418 return text 

419 

420 

421def get_citation_for_article(ref_data): 

422 text = get_html_from("authors", ref_data) 

423 text += get_html_from("article_title", ref_data) 

424 text += get_html_from("source", ref_data) 

425 text += get_html_from("series", ref_data) 

426 text += get_html_from("volume", ref_data) 

427 text += get_html_from("year", ref_data) 

428 text += get_html_from("number", ref_data) 

429 text += get_html_from("eids", ref_data) 

430 text += get_html_from("pages", ref_data) 

431 text += get_html_from("ext_links", ref_data) 

432 return text 

433 

434 

435def get_citation_for_book(ref_data): 

436 text = get_html_from("authors", ref_data) 

437 text += get_html_from("source", ref_data) 

438 text += get_html_from("editors", ref_data) 

439 text += get_html_from("series", ref_data) 

440 text += get_html_from("volume", ref_data) 

441 text += get_html_from("publisher", ref_data) 

442 text += get_html_from("institution", ref_data) 

443 text += get_html_from("year", ref_data) 

444 text += get_html_from("number", ref_data) 

445 text += get_html_from("eids", ref_data) 

446 text += get_html_from("pages", ref_data) 

447 text += get_html_from("ext_links", ref_data) 

448 return text 

449 

450 

451def get_citation_for_incollection(ref_data): 

452 text = get_html_from("authors", ref_data) 

453 

454 # <title> becomes a <chapter-title> in JATS for inbook, 

455 # but becomes a <source> for incollection. 

456 # We can call get_html_from_chapter_title then get_html_from_source because 1 of them will be empty in both cases 

457 text += get_html_from("chapter_title", ref_data) 

458 text += get_html_from("source", ref_data) 

459 

460 # TODO: BUG in JATS; editors are not displayed for inbook 

461 if ref_data.type != "inbook": 461 ↛ 464line 461 didn't jump to line 464 because the condition on line 461 was always true

462 text += get_html_from("editors", ref_data) 

463 

464 text += get_html_from("series", ref_data) 

465 text += get_html_from("volume", ref_data) 

466 text += get_html_from("publisher", ref_data) 

467 text += get_html_from("institution", ref_data) 

468 text += get_html_from("year", ref_data) 

469 text += get_html_from("number", ref_data) 

470 text += get_html_from("eids", ref_data) 

471 text += get_html_from("pages", ref_data) 

472 text += get_html_from("ext_links", ref_data) 

473 return text 

474 

475 

476def get_citation_for_misc(ref_data): 

477 text = get_html_from("authors", ref_data) 

478 

479 # TODO: BUG in JATS ? article_title is used for misc but source for unpublished ? 

480 text += get_html_from("article_title", ref_data) 

481 text += get_html_from("source", ref_data) 

482 text += get_html_from("series", ref_data) 

483 text += get_html_from("volume", ref_data) 

484 text += get_html_from("year", ref_data) 

485 text += get_html_from("number", ref_data) 

486 text += get_html_from("eids", ref_data) 

487 text += get_html_from("pages", ref_data) 

488 text += get_html_from("ext_links", ref_data) 

489 return text 

490 

491 

492def get_citation_for_thesis(ref_data): 

493 text = get_html_from("authors", ref_data) 

494 text += get_html_from("source", ref_data) 

495 text += get_html_from("series", ref_data) 

496 text += get_html_from("volume", ref_data) 

497 

498 text += get_html_from("annotation", ref_data) 

499 text += get_html_from("institution", ref_data) 

500 text += get_html_from("publisher", ref_data) 

501 text += get_html_from("month", ref_data) 

502 text += get_html_from("year", ref_data) 

503 text += get_html_from("number", ref_data) 

504 

505 text += get_html_from("eids", ref_data) 

506 text += get_html_from("pages", ref_data) 

507 text += get_html_from("ext_links", ref_data) 

508 

509 return text 

510 

511 

512def get_citation_html(ref_data): 

513 text = get_html_from("label", ref_data) 

514 

515 # article - book - incollection inbook - thesis phdthesis masterthesis - misc unpublished 

516 # manual techreport coursenotes proceedings ? 

517 type_ = ref_data.type 

518 

519 if type_ in ("inbook", "inproceedings"): 

520 type_ = "incollection" 

521 elif "thesis" in type_: 

522 type_ = "thesis" 

523 elif type_ not in ("article", "book", "incollection"): 

524 type_ = "misc" 

525 

526 fct_name = "get_citation_for_" + type_.replace("-", "_") 

527 if fct_name in globals() and callable(globals()[fct_name]): 527 ↛ 530line 527 didn't jump to line 530 because the condition on line 527 was always true

528 text += globals()[fct_name](ref_data) 

529 

530 text += get_html_from("comment", ref_data) 

531 

532 if ref_data.type not in ["phdthesis", "masterthesis", "mastersthesis"]: 

533 text += get_html_from("annotation", ref_data) 

534 

535 return text