Store and publish annotations on the web, as described in the Web Annotation Discovery proposal.

web-annotation-discovery-se.../routes/render/ renderAnnotation.ts
60 lines
1.8 KiB

  1. import type { Request, Response } from 'express';
  2. import { getTargetQuotes, getTargetUrls } from 'web-annotation-utils';
  3. import { escapeHtml } from '../util.js';
  4. export function renderAnnotation(
  5. req: Request,
  6. res: Response,
  7. { annotation, ...params },
  8. ) {
  9. res.render('annotation', {
  10. title: `Annotation`,
  11. ...annotationHbsParams(annotation, true),
  12. ...params,
  13. });
  14. }
  15. export function annotationHbsParams(annotation, verbose?: boolean) {
  16. const targetUrls = getTargetUrls(annotation.target);
  17. return {
  18. verbose,
  19. annotation,
  20. json: JSON.stringify(annotation, null, 2),
  21. created: annotation.created
  22. ? new Date(annotation.created).toDateString()
  23. : '<i>?</i>',
  24. modified:
  25. annotation.modified && new Date(annotation.modified).toDateString(),
  26. bodyHtml: annotation.bodyValue ?? annotationBodyToHtml(annotation.body),
  27. targetUrl: targetUrls.length === 1 ? targetUrls[0] : undefined,
  28. targetUrls: targetUrls.length > 1 ? targetUrls : undefined,
  29. targetQuotes: getTargetQuotes(annotation.target),
  30. };
  31. }
  32. function annotationBodyToHtml(body) {
  33. const iframe = (bodyUrl: string) =>
  34. `<iframe sandbox="" src=${bodyUrl}></iframe>`;
  35. try {
  36. if (body === undefined || body === null) {
  37. return '';
  38. }
  39. if (Array.isArray(body)) {
  40. return body.map(annotationBodyToHtml).join('\n<br/>\n');
  41. }
  42. if (typeof body === 'string') {
  43. return iframe(body);
  44. }
  45. if (body.type === 'Choice') {
  46. return annotationBodyToHtml(body.items[0]);
  47. }
  48. if (body.type === 'TextualBody') {
  49. if (body.format === 'text/html')
  50. return `<iframe sandbox="" csp="default-src: data: unsafe-inline;" srcdoc="${body.value}"></iframe>`;
  51. else return `<p>${escapeHtml(body.value)}</p>`;
  52. }
  53. } catch (err: any) {
  54. return '<i>Error while rendering annotation body.</i>';
  55. }
  56. }