Skip to content

Commit

Permalink
Render note excerpt using a page image
Browse files Browse the repository at this point in the history
  • Loading branch information
eyeseast committed May 23, 2024
1 parent 3973d05 commit 34c659d
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 20 deletions.
112 changes: 95 additions & 17 deletions src/lib/components/documents/Note.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
@component
A single note, either overlaid on a document or on its own.
It has two states, focused and normal.
It can use *either* a loaded PDF or a document image to render
a document excerpt.
-->
<script lang="ts">
import type { Writable } from "svelte/store";
import type { User } from "@/api/types/orgAndUser";
import type { Note, ViewerMode } from "$lib/api/types";
import type { Document, Note, Sizes, ViewerMode } from "$lib/api/types";
import DOMPurify from "isomorphic-dompurify";
import { getContext } from "svelte";
import { getContext, onMount } from "svelte";
import { _ } from "svelte-i18n";
import {
Globe16,
Expand All @@ -22,13 +24,17 @@
import Action from "../common/Action.svelte";
import { noteHashUrl, width, height } from "$lib/api/notes";
import { pageHashUrl } from "$lib/api/documents";
import { pageImageUrl } from "$lib/api/documents";
import { getPrivateAsset } from "$lib/utils/api";
export let note: Note;
export let focused = false;
export let pdf = null; // PDFDocumentProxy
const ALLOWED_TAGS = ["a", "strong", "em", "b", "i"];
const ALLOWED_ATTR = ["href"];
const SIZE: Sizes = "large";
const BUFFER = 20; // padding around image excerpt
const access = {
private: {
Expand All @@ -50,11 +56,62 @@
const mode: Writable<ViewerMode> = getContext("mode");
let document: Document = getContext("document");
let canvas: HTMLCanvasElement;
$: id = noteHashUrl(note).replace("#", "");
$: href = noteHashUrl(note);
$: page_number = note.page_number + 1; // note pages are 0-indexed
$: user = typeof note.user === "object" ? (note.user as User) : null;
onMount(() => {
render(canvas, document, pdf);
});
async function render(canvas: HTMLCanvasElement, document: Document, pdf) {
if (pdf) {
return renderPDF(canvas, pdf);
}
if (document) {
return renderImage(canvas, document);
}
// we don't have a pdf or a document, for some reason
console.error(`Can't render note ${note.id} on page ${page_number}.`);
}
async function renderImage(canvas: HTMLCanvasElement, document: Document) {
const context = canvas.getContext("2d");
const image = new Image();
let src = pageImageUrl(document, page_number, SIZE);
/*
if (document.access !== "public") {
src = await getPrivateAsset(src);
}
*/
image.src = src.href;
image.addEventListener("load", (e) => {
canvas.width = width(note) * image.width;
canvas.height = height(note) * image.height;
context.drawImage(
image,
note.x1 * image.width,
note.y1 * image.height,
width(note) * image.width,
height(note) * image.height,
0,
0,
width(note) * image.width,
height(note) * image.height,
);
});
}
async function renderPDF(canvas: HTMLCanvasElement, pdf) {}
function clean(html: string) {
return DOMPurify.sanitize(html, {
USE_PROFILES: { html: true },
Expand All @@ -72,8 +129,8 @@
style:--x2={note.x2}
style:--y1={note.y1}
style:--y2={note.y2}
style:--width={width(note)}
style:--height={height(note)}
style:--note-width={width(note)}
style:--note-height={height(note)}
>
<header>
<h3>{note.title}</h3>
Expand All @@ -88,13 +145,15 @@
</header>
<div class="excerpt">
<h4 {id}>
<a href={pageHashUrl(page_number)}>
<a href={noteHashUrl(note)}>
{$_("documents.pageAbbrev")}
{page_number}
</a>
</h4>

<div class="highlight"></div>
<div class="highlight">
<canvas width="0" height="0" bind:this={canvas}></canvas>
</div>
</div>
<div class="content">
<p>{@html clean(note.content)}</p>
Expand Down Expand Up @@ -203,6 +262,17 @@
gap: var(--font-md, 1rem);
}
h4,
h4 a {
color: var(--gray-4, #5c717c);
text-decoration: none;
font-weight: var(--font-regular);
}
h4 a:hover {
text-decoration: underline;
}
.excerpt {
display: flex;
flex-direction: column;
Expand All @@ -212,22 +282,30 @@
}
.highlight {
height: 4.25rem;
align-self: stretch;
border-radius: 0.5rem;
border: 1px solid var(--gray-2, #d8dee2);
border: 2px solid var(--gray-2, #d8dee2);
background: var(--gray-1, #f5f6f7);
display: flex;
align-items: center;
justify-content: center;
}
h4,
h4 a {
color: var(--gray-4, #5c717c);
text-decoration: none;
font-weight: var(--font-regular);
.public .highlight {
border-color: var(--note-public);
}
h4 a:hover {
text-decoration: underline;
.private .highlight {
border-color: var(--note-private);
}
.organization .highlight {
border-color: var(--note-org);
}
canvas {
max-width: 100%;
padding: 0.25rem;
}
footer {
Expand Down
5 changes: 5 additions & 0 deletions src/lib/components/documents/stories/Note.stories.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import type { Note as NoteType } from "$lib/api/types";
import { Story } from "@storybook/addon-svelte-csf";
import { setContext } from "svelte";
import Note from "../Note.svelte";
import document from "$lib/api/fixtures/documents/document-expanded.json";
Expand All @@ -19,6 +20,10 @@
};
</script>

<script lang="ts">
setContext("document", document);
</script>

<Story name="default">
<Note focused note={notes[0]} />
</Story>
Expand Down
10 changes: 7 additions & 3 deletions src/routes/documents/[id]-[slug]/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import "@/style/kit.css";
import type { Project } from "$lib/api/types";
import type { Document, Project } from "$lib/api/types";
// load this here to get the worker started early
import * as pdfjs from "pdfjs-dist/build/pdf.mjs";
Expand All @@ -10,6 +10,8 @@
import.meta.url,
).href;
import { setContext } from "svelte";
import MainLayout from "$lib/components/layouts/MainLayout.svelte";
import SignedIn from "$lib/components/common/SignedIn.svelte";
Expand All @@ -26,14 +28,16 @@
export let data;
setContext<Document>("document", data.document);
$: document = data.document;
$: projects = document.projects as Project[];
$: canonical_url = canonicalUrl(document).toString();
$: canonical_url = canonicalUrl(document).href;
</script>

<svelte:head>
<!-- Insert canonical URL -->
<link rel="canonical" href={document.canonical_url.toString()} />
<link rel="canonical" href={canonical_url} />

{#if document.noindex || document.admin_noindex}
<meta name="robots" content="noindex" />
Expand Down

0 comments on commit 34c659d

Please sign in to comment.