mirror of
https://github.com/jzillmann/pdf-to-markdown.git
synced 2025-01-03 20:28:54 +01:00
Page selection
This commit is contained in:
parent
8783e3cf9e
commit
93d067b346
@ -5,7 +5,7 @@
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="description" content="Web site created using create-snowpack-app" />
|
||||
<title>Snowpack App</title>
|
||||
<title>PDF to Markdown</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script>
|
||||
import type ParseResult from 'pdf-to-markdown-core/lib/src/ParseResult';
|
||||
import type Item from '@core/Item';
|
||||
import Table from './Table.svelte';
|
||||
|
||||
export let parseResult: ParseResult;
|
||||
|
@ -1,11 +1,74 @@
|
||||
<script>
|
||||
import type Item from '@core/Item';
|
||||
import { Collection, BookOpen, Support, ArrowLeft, ArrowRight } from 'svelte-hero-icons';
|
||||
|
||||
export let columns: string[];
|
||||
export let items: Item[];
|
||||
const pages = [...new Set(items.map((item) => item.page))];
|
||||
const maxPage = Math.max(...pages);
|
||||
let focusedPage: number;
|
||||
$: focused = typeof focusedPage === 'number';
|
||||
let openedPageIndex = false;
|
||||
|
||||
const itemsGroupedByPage = items.reduce((map, item) => {
|
||||
if (!map.has(item.page)) {
|
||||
map.set(item.page, []);
|
||||
}
|
||||
map.get(item.page).push(item);
|
||||
return map;
|
||||
}, new Map<number, Item[]>());
|
||||
|
||||
function focusOnPage(pageNumber: number) {
|
||||
openedPageIndex = false;
|
||||
focusedPage = pageNumber;
|
||||
}
|
||||
|
||||
function showAllPages() {
|
||||
openedPageIndex = false;
|
||||
focusedPage = undefined;
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Sticky Controls -->
|
||||
<div class="controls pb-3">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>
|
||||
<span on:click={() => (openedPageIndex = !openedPageIndex)}>
|
||||
<BookOpen size="1x" class="hover:text-green-700 cursor-pointer" />
|
||||
</span>
|
||||
|
||||
<!-- Page selection popup-->
|
||||
{#if openedPageIndex}
|
||||
<div class="absolute mt-2 p-2 flex bg-gray-200 shadow-lg rounded-sm overflow-auto max-h-96">
|
||||
<span class="mt-1 pr-2" on:click={showAllPages}>
|
||||
<Collection size="1x" class="hover:text-green-700 cursor-pointer" />
|
||||
</span>
|
||||
<div
|
||||
class="grid gap-3"
|
||||
style="grid-template-columns: repeat({Math.min(20, maxPage + 1)}, minmax(0, 1fr));">
|
||||
{#each new Array(maxPage + 1) as _, idx}
|
||||
<div
|
||||
on:click={() => itemsGroupedByPage.has(idx) && focusOnPage(idx)}
|
||||
class="px-2 border border-gray-300 rounded-full text-center {itemsGroupedByPage.has(idx) ? 'hover:text-green-700 hover:border-green-700 cursor-pointer' : 'opacity-50'}">
|
||||
{idx}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</span>
|
||||
|
||||
<div>|</div>
|
||||
<div>Transformation:</div>
|
||||
<ArrowLeft size="1x" class="hover:text-green-700 cursor-pointer opacity-50" />
|
||||
<div>Parse Result</div>
|
||||
<ArrowRight size="1x" class="hover:text-green-700 cursor-pointer" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Item table -->
|
||||
<table class="w-full text-left">
|
||||
<!-- Sticky header -->
|
||||
<thead class=" ">
|
||||
<th />
|
||||
<th>#</th>
|
||||
@ -14,31 +77,67 @@
|
||||
{/each}
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each items as item, idx}
|
||||
{#if idx > 0 && item.page !== items[idx - 1].page}
|
||||
<tr class="h-5 bg-blue-200" />
|
||||
{#each [...itemsGroupedByPage].filter(([page]) => !focused || page === focusedPage) as [pageNumber, items], pageIdx}
|
||||
<!-- Separator between pages -->
|
||||
{#if pageIdx > 0}
|
||||
<tr class="h-5" />
|
||||
{/if}
|
||||
<tr class="">
|
||||
{#if idx === 0 || item.page !== items[idx - 1].page}
|
||||
<td class="page bg-gray-50">Page {item.page}</td>
|
||||
{:else}
|
||||
<td />
|
||||
{/if}
|
||||
<td class="">{idx}</td>
|
||||
{#each columns as column}
|
||||
<td class="borde2r">{item.data[column]}</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{#each items as item, itemIdx}
|
||||
<tr>
|
||||
<!-- Page number in first page item row -->
|
||||
{#if itemIdx === 0}
|
||||
<td class="page bg-gray-50">
|
||||
<div>Page {pageNumber} {focused ? '' : ' / ' + maxPage}</div>
|
||||
<div class="absolute flex">
|
||||
{#if !focused}
|
||||
<span on:click={() => focusOnPage(pageNumber)}>
|
||||
<Support size="1x" class="hover:text-green-700 cursor-pointer" />
|
||||
</span>
|
||||
{:else}
|
||||
<span on:click={showAllPages}>
|
||||
<Collection size="1x" class="hover:text-green-700 cursor-pointer" />
|
||||
</span>
|
||||
{/if}
|
||||
</div>
|
||||
</td>
|
||||
{:else}
|
||||
<td />
|
||||
{/if}
|
||||
<td class="">{itemIdx}</td>
|
||||
{#each columns as column}
|
||||
<td class="borde2r">{item.data[column]}</td>
|
||||
{/each}
|
||||
</tr>
|
||||
{/each}
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<style>
|
||||
.controls {
|
||||
@apply bg-gray-50;
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 3;
|
||||
}
|
||||
|
||||
.page {
|
||||
@apply text-lg;
|
||||
@apply font-semibold;
|
||||
@apply pr-4;
|
||||
@apply whitespace-nowrap;
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 1.7em;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
th {
|
||||
@apply px-1;
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
top: 2.1em;
|
||||
z-index: 2;
|
||||
}
|
||||
th:not(:first-child) {
|
||||
@ -53,15 +152,4 @@
|
||||
tr:hover td:not(:first-child) {
|
||||
@apply bg-gray-200;
|
||||
}
|
||||
|
||||
.page {
|
||||
@apply text-lg;
|
||||
@apply font-semibold;
|
||||
@apply pr-4;
|
||||
@apply whitespace-nowrap;
|
||||
position: -webkit-sticky;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user