mirror of
https://github.com/kunkunsh/kunkun.git
synced 2025-04-13 02:04:34 +00:00

* feat: npm package registry API * refactor: move package registry files * refactor: move jsr and npm api to a new package * ci: add verify-package-export * test: implement tests for npm package validation as kunkun extension * chore: add missing dep for package-registry pkg * feat: make provenance an optional input for npm validation function * ci: add verify-package-export as dev dep to 2 packages that uses it * feat: add rekor log API, and return commit from jsr & npm package in validation function * feat: return github repo info from validation function of jsr and npm * feat: extend ExtPublishMetadata to include optional GitHub repository details * fix: eslint for ui package * refactor: format desktop * fix: eslint errors in desktop * format: all code * ci: add lint to CI * feat: add more info to validation function returned from package-registry npm jsr * pnpm lock * feat: add 2 more variables to supabase extension metadata model * format * feat: add provenance card * feat: add workflow path to ExtPublishMetadata and jsr/npm validation * update provenance * feat: make store extension and provenance more responsive * chore: add globals to ui package * fix: remove unnecessary any to fix eslint * fix: svg sanitize * chore: add @typescript-eslint/eslint-plugin to ui package to fix eslint * fix: update eslint dep to fix error * fix: try fixing eslint * fix: update eslint configuration for improved compatibility * chore: add globals package and update README for Discord invite * fix: update eslint rules and upgrade typescript-eslint dependency - Disabled additional eslint rules to resolve errors: - @typescript-eslint/no-unused-expressions - svelte/no-inner-declarations - Upgraded typescript-eslint from version 8.19.1 to 8.20.0 for improved compatibility. * update pnpm lock --------- Co-authored-by: Huakun Shen <huaukun.shen@huakunshen.com>
105 lines
3.2 KiB
Svelte
105 lines
3.2 KiB
Svelte
<script lang="ts">
|
|
import { cn } from "@/utils"
|
|
import { db } from "@kksh/api/commands"
|
|
import type { ExtData } from "@kksh/api/models"
|
|
import { Resizable, Separator } from "@kksh/svelte5"
|
|
import { convertFileSrc } from "@tauri-apps/api/core"
|
|
import DOMPurify from "dompurify"
|
|
|
|
function formatDate(date: Date) {
|
|
const now = new Date()
|
|
const isToday = date.toDateString() === now.toDateString()
|
|
|
|
const options: Intl.DateTimeFormatOptions = {
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
second: "2-digit",
|
|
hour12: true
|
|
} as const
|
|
const timeString = date.toLocaleTimeString("en-US", options)
|
|
|
|
if (isToday) {
|
|
return `Today at ${timeString}`
|
|
} else {
|
|
const dateOptions: Intl.DateTimeFormatOptions = {
|
|
month: "short",
|
|
day: "numeric",
|
|
year: "numeric"
|
|
} as const
|
|
const dateString = date.toLocaleDateString("en-US", dateOptions)
|
|
return `${dateString} at ${timeString}`
|
|
}
|
|
}
|
|
|
|
let { highlighted }: { highlighted: ExtData } = $props()
|
|
let imgSrc = $state<string>("")
|
|
let txtData = $state<string>("")
|
|
let createTime = $state<Date>()
|
|
let imgRef = $state<HTMLImageElement>()
|
|
|
|
$effect(() => {
|
|
;(async () => {
|
|
if (highlighted.dataType === "Image") {
|
|
const dbRecord = await db.getExtensionDataById(highlighted.dataId, []) // do not load "data" field
|
|
imgSrc = await convertFileSrc(`/?id=${highlighted.dataId}`, "cbimg")
|
|
createTime = dbRecord?.createdAt
|
|
} else {
|
|
const dbRecord = await db.getExtensionDataById(highlighted.dataId) // do not load "data" field
|
|
txtData = dbRecord?.data || ""
|
|
createTime = dbRecord?.createdAt
|
|
}
|
|
})()
|
|
})
|
|
</script>
|
|
|
|
<Resizable.PaneGroup direction="vertical">
|
|
<Resizable.Pane defaultSize={50} class="px-2 py-1">
|
|
<div
|
|
class={cn({
|
|
hidden: highlighted.dataType !== "Image",
|
|
"h-full": highlighted.dataType === "Image",
|
|
"flex justify-center": highlighted.dataType === "Image"
|
|
})}
|
|
>
|
|
<img src={imgSrc} alt="" class="h-full w-auto object-contain" bind:this={imgRef} />
|
|
</div>
|
|
{#if highlighted.dataType === "Image"}{:else if highlighted.dataType === "Text"}
|
|
<div class="text-sm">{txtData}</div>
|
|
{:else if highlighted.dataType === "Html"}
|
|
<div class="">
|
|
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
{@html DOMPurify.sanitize(txtData)}
|
|
</div>
|
|
{:else}
|
|
<div class="text-sm">No preview available</div>
|
|
{/if}
|
|
<!-- </div> -->
|
|
</Resizable.Pane>
|
|
<Resizable.Handle withHandle />
|
|
<Resizable.Pane defaultSize={50} class="space-y-1 px-4 pt-2">
|
|
<h2 class="font-mono font-bold">Information</h2>
|
|
{#if createTime}
|
|
{@render row("Copied At", formatDate(createTime))}
|
|
{/if}
|
|
<Separator />
|
|
{@render row("Content Type", highlighted.dataType || "")}
|
|
{#if highlighted.dataType === "Image"}
|
|
{#if imgRef}
|
|
<Separator />
|
|
{@render row("Dimension", `${imgRef.naturalWidth}x${imgRef.naturalHeight}`)}
|
|
{/if}
|
|
{:else}
|
|
<Separator />
|
|
{@render row("Character Count", txtData.length.toString())}
|
|
<Separator />
|
|
{@render row("Word Count", txtData.split(/\s+/).length.toString())}
|
|
{/if}
|
|
</Resizable.Pane>
|
|
</Resizable.PaneGroup>
|
|
{#snippet row(label: string, value: string)}
|
|
<div class="flex justify-between">
|
|
<span class="text-sm font-semibold">{label}</span>
|
|
<span class="text-sm">{value}</span>
|
|
</div>
|
|
{/snippet}
|