Skip to content

Commit

Permalink
feat: Add image serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
kiosion committed Aug 16, 2023
1 parent 7ac0f05 commit 3e7bec1
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 3 deletions.
2 changes: 2 additions & 0 deletions web/info/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
"@bufbuild/connect-web": "^0.11.0",
"@bufbuild/protobuf": "~1.2.0",
"@portabletext/svelte": "^2.0.0",
"@portabletext/types": "^2.0.5",
"@rgossiaux/svelte-headlessui": "^2.0.0",
"@sanity/client": "^6.4.6",
"@sanity/image-url": "^1.0.2",
"@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/adapter-node": "^1.3.1",
"@sveltejs/adapter-vercel": "^3.0.1",
Expand Down
4 changes: 3 additions & 1 deletion web/info/src/components/portable-text/portable-text.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import CodeSerializer from '$components/portable-text/serializers/code.svelte';
import FeedsSerializer from '$components/portable-text/serializers/feeds.svelte';
import HeadingSerializer from '$components/portable-text/serializers/heading.svelte';
import ImageSerializer from '$components/portable-text/serializers/image.svelte';
import LinkSerializer from '$components/portable-text/serializers/link.svelte';
import OlSerializer from '$components/portable-text/serializers/ordered-list.svelte';
import OlItemSerializer from '$components/portable-text/serializers/ordered-list-item.svelte';
Expand All @@ -22,7 +23,8 @@
value={content}
components={{
types: {
feeds: FeedsSerializer
feeds: FeedsSerializer,
image: ImageSerializer
},
marks: {
link: LinkSerializer,
Expand Down
35 changes: 35 additions & 0 deletions web/info/src/components/portable-text/serializers/image.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script lang="ts">
import { getCrop, urlFor } from '$lib/sanity';
import type { CustomBlockComponentProps } from '@portabletext/svelte';
import type { ArbitraryTypedObject } from '@portabletext/types';
import type { ImageCrop } from '$lib/sanity';
import type { SanityImageObject } from '$types';
export let portableText: Omit<CustomBlockComponentProps, 'value'> & {
value: ArbitraryTypedObject & {
asset: SanityImageObject['asset'];
};
};
let imageCrop: ImageCrop;
$: ({ value } = portableText);
$: ({ _key } = value);
$: ({ _ref } = value.asset);
$: (imageCrop = getCrop(value as unknown as SanityImageObject)), value;
</script>

<div class="h-fit w-full">
<img
src={urlFor(_ref)
.width(800)
.rect(imageCrop.left, imageCrop.top, imageCrop.width, imageCrop.height)
.fit('crop')
.auto('format')
.url()}
class="select-none rounded-sm"
alt={_key}
draggable="false"
/>
</div>
44 changes: 44 additions & 0 deletions web/info/src/lib/sanity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { SANITY_API_VERSION, SANITY_DATASET, SANITY_PROJECT_ID } from '$lib/constants';

import { createClient } from '@sanity/client';
import imageUrlBuilder from '@sanity/image-url';

import type {
SanityImageObject,
SanityImageSource
} from '@sanity/image-url/lib/types/types';
import type { DocumentRegistry } from '$types';

const client = createClient({
Expand All @@ -27,3 +32,42 @@ export const getPageDocument = async <T extends string>(id: T) => {

return document;
};

export interface ImageCrop {
top: number;
left: number;
bottom: number;
right: number;
width: number;
height: number;
}

const builder = imageUrlBuilder(client);

export const urlFor = (source: SanityImageSource) => builder.image(source);

export const getCrop = (image: SanityImageObject | undefined) => {
if (!image || !image?.asset) {
return {
top: 0,
left: 0,
bottom: 0,
right: 0,
width: 0,
height: 0
};
}
const ref = image.asset._ref,
dimensions = ref?.split('-')?.[2]?.split('x'),
crop: ImageCrop = {
top: Math.floor(dimensions[1] * (image?.crop?.top ?? 0)),
left: Math.floor(dimensions[0] * (image?.crop?.left ?? 0)),
bottom: Math.floor(dimensions[1] * (image?.crop?.bottom ?? 0)),
right: Math.floor(dimensions[0] * (image?.crop?.right ?? 0))
} as ImageCrop;

crop.width = Math.floor(dimensions[0] - (crop.left + crop.right));
crop.height = Math.floor(dimensions[1] - (crop.top + crop.bottom));

return crop;
};
2 changes: 1 addition & 1 deletion web/info/src/routes/[page=valid_doc_route]/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const load = (async ({ parent, params }) => {
const pageName = DOC_ROUTES_NAMES[params.page] as keyof typeof DOC_ROUTES_NAMES;

if (!pageName) {
throw error(404, 'Page not found');
throw error(404, 'Not Found');
}

const { feeds, featuredFeeds } = await parent();
Expand Down
35 changes: 35 additions & 0 deletions web/info/types/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,38 @@ export type DocumentRegistry = {
} & {
home: BaseDocument<'home'>;
};

export interface SanityAsset {
_id: string;
_type?: string;
_createdAt?: string;
_rev?: string;
_updatedAt?: string;
url?: string;
path?: string;
assetId?: string;
extension?: string;
}
export interface SanityReference {
_ref: string;
_type: string;
}
export interface SanityImageObject extends Pick<SanityAsset, '_id' | '_type'> {
asset: SanityReference;
crop?: SanityImageCrop;
hotspot?: SanityImageHotspot;
}
export interface SanityImageCrop {
_type?: string;
left: number;
bottom: number;
right: number;
top: number;
}
export interface SanityImageHotspot {
_type?: string;
width: number;
height: number;
x: number;
y: number;
}
7 changes: 6 additions & 1 deletion web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 3e7bec1

Please sign in to comment.