Coverage for apps/ptf/cmds/xml/citation_html.py: 93%

346 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-05-19 19:20 +0000

1from django.conf import settings 

2 

3from ptf.cmds.xml.xml_utils import make_links_clickable 

4from ptf.utils import get_display_name 

5 

6# Bug fixed: 

7# 1. article_title / chapter_title 

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

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

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

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

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

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

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

15 

16 

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

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

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

20 

21 

22def helper_decorate_text(text, prefix, suffix): 

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

24 return "" 

25 

26 text = prefix + text + suffix 

27 return text 

28 

29 

30def get_html_from(tag, ref_data): 

31 text = "" 

32 

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

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

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

36 else: 

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

38 if fct_name in globals() and callable(globals()[fct_name]): 38 ↛ 41line 38 didn't jump to line 41, because the condition on line 38 was never false

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

40 

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

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

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

44 

45 return text 

46 

47 

48def get_html_from_authors(ref_data): 

49 """ 

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

51 We cannot use the add_prefix_ then add_span_class_ functions 

52 

53 :param ref_data: 

54 :return: 

55 """ 

56 contribs = ref_data.get_authors() 

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

58 

59 return text 

60 

61 

62def get_html_from_contribs(contribs, is_editor=False, with_span=False): 

63 text = "" 

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

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

66 i = 1 

67 size = len(contribs) 

68 

69 if with_span and not is_editor: 

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

71 

72 for contrib in contribs: 

73 first_name = contrib["first_name"] 

74 if (ref_jep_style or ref_pcj_style) and first_name: 

75 # JEP_STYLE: Only the first name initials are used 

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

77 initials = [] 

78 for word in words: 

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

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

81 initials.append(word) 

82 first_name = " ".join(initials) 

83 

84 string_name = get_display_name( 

85 contrib["prefix"], 

86 first_name, 

87 contrib["last_name"], 

88 contrib["suffix"], 

89 contrib["string_name"], 

90 ) 

91 

92 if i > 1: 

93 if i == size and contrib["contrib_xml"] == "<etal/>": 

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

95 elif i == size and ref_jep_style: 

96 text += " & " 

97 elif ref_jep_style: 97 ↛ 98line 97 didn't jump to line 98, because the condition on line 97 was never true

98 text += ", " 

99 else: 

100 text += "; " 

101 

102 if contrib["contrib_xml"] == "<etal/>": 

103 text += "et al." 

104 else: 

105 text += string_name 

106 i += 1 

107 

108 if is_editor: 

109 if len(contribs) > 1: 

110 text += ", eds." 

111 else: 

112 text += ", ed." 

113 elif with_span: 113 ↛ 116line 113 didn't jump to line 116, because the condition on line 113 was never false

114 text += "</span>" 

115 

116 return text 

117 

118 

119def get_html_from_pages(ref_data): 

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

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

122 return "" 

123 

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

125 

126 if not text and ref_data.fpage: 

127 fpage_int = lpage_int = 0 

128 

129 try: 

130 fpage_int = int(ref_data.fpage) 

131 except ValueError: 

132 pass 

133 

134 try: 

135 lpage_int = int(ref_data.lpage) 

136 except ValueError: 

137 pass 

138 

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

140 text += ", pp. " 

141 else: 

142 text += ", p. " 

143 

144 text += ref_data.fpage 

145 if ref_data.lpage: 

146 text += "-" + ref_data.lpage 

147 

148 if not text and ref_data.page_range: 

149 prefix = ", pp. " 

150 suffix = "" 

151 if ref_jep_style: 151 ↛ 152line 151 didn't jump to line 152, because the condition on line 151 was never true

152 prefix = ", p. " 

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

154 

155 return text 

156 

157 

158def get_html_from_source(ref_data): 

159 with_article_or_chapter_title = ref_data.article_title_tex or ref_data.chapter_title_tex 

160 value_html = add_prefix_to_html_from_source(ref_data) 

161 text = add_span_class_to_html_from_source( 

162 value_html, 

163 ref_type=ref_data.type, 

164 with_article_or_chapter_title=with_article_or_chapter_title, 

165 ) 

166 

167 return text 

168 

169 

170def add_prefix_to_html_from_annotation(ref_data): 

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

172 prefix = ", " 

173 suffix = "" 

174 else: 

175 prefix = " (" 

176 suffix = ")" 

177 

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

179 return text 

180 

181 

182def add_prefix_to_html_from_article_title(ref_data): 

183 prefix = " " 

184 suffix = "" 

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

186 

187 if ref_jep_style: 187 ↛ 188line 187 didn't jump to line 188, because the condition on line 187 was never true

188 prefix = " - &ldquo;" 

189 suffix = "&rdquo;" 

190 

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

192 return text 

193 

194 

195def add_prefix_to_html_from_authors(ref_data): 

196 contribs = ref_data.get_authors() 

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

198 return text 

199 

200 

201def add_prefix_to_html_from_chapter_title(ref_data): 

202 prefix = " " 

203 suffix = "" 

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

205 

206 if ref_jep_style: 

207 prefix = " - &ldquo;" 

208 suffix = "&rdquo;" 

209 

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

211 return text 

212 

213 

214def add_prefix_to_html_from_comment(ref_data): 

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

216 

217 if ref_jep_style: 

218 prefix = ", " 

219 suffix = "" 

220 else: 

221 if "(" in ref_data.comment: 

222 prefix = " " 

223 suffix = "" 

224 else: 

225 prefix = " (" 

226 suffix = ")" 

227 

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

229 return text 

230 

231 

232def add_prefix_to_html_from_editors(ref_data): 

233 contribs = ref_data.get_editors() 

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

235 text = helper_decorate_text(text, " (", ")") 

236 return text 

237 

238 

239def add_prefix_to_html_from_eids(ref_data): 

240 text = "" 

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

242 

243 for extid in ref_data.extids: 

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

245 if ref_jep_style: 245 ↛ 246line 245 didn't jump to line 246, because the condition on line 245 was never true

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

247 elif REF_ALCO_STYLE: 247 ↛ 248line 247 didn't jump to line 248, because the condition on line 247 was never true

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

249 else: 

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

251 return text 

252 

253 

254def add_prefix_to_html_from_ext_links(ref_data): 

255 text = "" 

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

257 

258 for link in ref_data.ext_links: 

259 href = link["location"] 

260 

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

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

263 # We can ignore both cases 

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

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

266 text += " " + href 

267 return text 

268 

269 

270def add_prefix_to_html_from_institution(ref_data): 

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

272 return text 

273 

274 

275def add_prefix_to_html_from_label(ref_data): 

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

277 return text 

278 

279 

280def add_prefix_to_html_from_month(ref_data): 

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

282 return text 

283 

284 

285def add_prefix_to_html_from_number(ref_data): 

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

287 return text 

288 

289 

290def add_prefix_to_html_from_publisher(ref_data): 

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

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

293 return text 

294 

295 

296def add_prefix_to_html_from_series(ref_data): 

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

298 

299 if ref_data.chapter_title_tex or ref_data.article_title_tex: 

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

301 prefix = ", " 

302 suffix = "" 

303 else: 

304 prefix = " (" 

305 suffix = ")" 

306 else: 

307 prefix = ", " 

308 suffix = "" 

309 

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

311 return text 

312 

313 

314def add_prefix_to_html_from_source(ref_data): 

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

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

317 if ref_data.article_title_tex or ref_data.chapter_title_tex: 

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

319 prefix = ", in " 

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

321 prefix = " In: " 

322 else: 

323 prefix = ", " 

324 suffix = "" 

325 else: 

326 prefix = " " 

327 suffix = "" 

328 

329 if ref_jep_style: 329 ↛ 330line 329 didn't jump to line 330, because the condition on line 329 was never true

330 prefix = " - " 

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

332 prefix += "&ldquo;" 

333 suffix = "&rdquo;" 

334 

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

336 return text 

337 

338 

339def add_prefix_to_html_from_volume(ref_data): 

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

341 

342 if ref_jep_style: 

343 if ref_data.type in ["incollection", "book"]: 343 ↛ 346line 343 didn't jump to line 346, because the condition on line 343 was never false

344 prefix = ", vol. " 

345 else: 

346 prefix = " " 

347 else: 

348 if ref_data.article_title_tex or ref_data.chapter_title_tex: 

349 prefix = ", Volume " 

350 else: 

351 prefix = ", " 

352 

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

354 return text 

355 

356 

357def add_prefix_to_html_from_year(ref_data): 

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

359 

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

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

362 suffix = "" 

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

364 prefix = ", " 

365 suffix = "" 

366 else: 

367 prefix = " (" 

368 suffix = ")" 

369 

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

371 return text 

372 

373 

374def add_span_class_to_html_from_article_title(value_html, **kwargs): 

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

376 return text 

377 

378 

379def add_span_class_to_html_from_authors(value_html, **kwargs): 

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

381 return text 

382 

383 

384def add_span_class_to_html_from_chapter_title(value_html, **kwargs): 

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

386 return text 

387 

388 

389def add_span_class_to_html_from_series(value_html, **kwargs): 

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

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

392 return text 

393 

394 

395def add_span_class_to_html_from_source(value_html, **kwargs): 

396 suffix = "</span>" 

397 

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

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

400 else: 

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

402 

403 text = helper_decorate_text(value_html, prefix, suffix) 

404 return text 

405 

406 

407def add_span_class_to_html_from_volume(value_html, **kwargs): 

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

409 

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

411 text = helper_decorate_text( 

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

413 ) 

414 else: 

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

416 return text 

417 

418 

419def get_citation_for_article(ref_data): 

420 text = get_html_from("authors", ref_data) 

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

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

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

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

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

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

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

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

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

430 return text 

431 

432 

433def get_citation_for_book(ref_data): 

434 text = get_html_from("authors", ref_data) 

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

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

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

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

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

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

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

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

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

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

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

446 return text 

447 

448 

449def get_citation_for_incollection(ref_data): 

450 text = get_html_from("authors", ref_data) 

451 

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

453 # but becomes a <source> for incollection. 

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

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

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

457 

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

459 if ref_data.type != "inbook": 459 ↛ 462line 459 didn't jump to line 462, because the condition on line 459 was never false

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

461 

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

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

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

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

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

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

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

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

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

471 return text 

472 

473 

474def get_citation_for_misc(ref_data): 

475 text = get_html_from("authors", ref_data) 

476 

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

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

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

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

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

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

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

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

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

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

487 return text 

488 

489 

490def get_citation_for_thesis(ref_data): 

491 text = get_html_from("authors", ref_data) 

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

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

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

495 

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

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

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

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

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

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

502 

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

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

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

506 

507 return text 

508 

509 

510def get_citation_html(ref_data): 

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

512 

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 never false

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