Skip to content

Commit e6743df

Browse files
authored
Merge pull request #24 from zernonia/18-add-embeds
18 add embeds
2 parents da705f6 + 1a90808 commit e6743df

File tree

10 files changed

+137
-20
lines changed

10 files changed

+137
-20
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
},
4949
"dependencies": {
5050
"@nuxt/kit": "^3.0.0-rc.1",
51+
"@vueuse/core": "^8.7.5",
5152
"fragment-for-vue": "^1.0.1",
5253
"katex": "^0.15.1",
5354
"pathe": "^0.2.0",

src/blocks/helpers/asset.vue

+18-7
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,28 @@ import { computed, StyleValue } from "vue"
44
55
const props = defineProps({ ...defineNotionProps })
66
//@ts-ignore
7-
const { type, properties, f } = useNotionBlock(props)
7+
const { properties, f, format } = useNotionBlock(props)
88
99
const src = computed(() => {
10-
return type.value === "figma" ? properties.value?.source[0][0] : f.value.display_source
10+
return f.value.display_source ?? properties.value?.source?.[0]
1111
})
1212
13-
const style = computed(() => {
14-
const aspectRatio = f.value.block_aspect_ratio || f.value.block_height / f.value.block_width
13+
const aspectRatioStyle = computed(() => {
14+
let aspectRatio =
15+
f.value.block_width == 1 || f.value.block_height == 1
16+
? 1 / f.value.block_aspect_ratio
17+
: `${f.value.block_width} / ${f.value.block_height} `
18+
1519
return {
16-
paddingBottom: `${aspectRatio * 100}%`,
20+
width: format.value.block_full_width
21+
? "calc(100vw - 46px)"
22+
: format.value.block_page_width
23+
? "100%"
24+
: `${f.value.block_width}px`,
25+
height: f.value.block_height == 1 ? `auto` : `${f.value.block_height}px`,
26+
maxWidth: "100%",
1727
position: "relative",
28+
aspectRatio: f.value.block_height == 1 ? aspectRatio : undefined,
1829
} as StyleValue
1930
})
2031
</script>
@@ -26,7 +37,7 @@ export default {
2637
</script>
2738

2839
<template>
29-
<div :style="style" v-if="src">
30-
<iframe class="notion-image-inset" style="width: 100%" :src="src" :allow="props.embedAllow" />
40+
<div :style="aspectRatioStyle" v-if="src">
41+
<iframe class="notion-asset-object-fit" :src="src" :allow="props.embedAllow" />
3142
</div>
3243
</template>

src/blocks/helpers/figure.vue

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { useNotionBlock, defineNotionProps } from "@/lib/blockable"
33
import NotionAsset from "@/blocks/helpers/asset.vue"
44
import NotionImage from "@/blocks/helpers/image.vue"
5+
import NotionGoogleDrive from "@/blocks/helpers/google-drive.vue"
56
import NotionTextRenderer from "@/blocks/helpers/text-renderer.vue"
67
78
const props = defineProps({ ...defineNotionProps })
@@ -15,9 +16,10 @@ export default {
1516
}
1617
</script>
1718
<template>
18-
<figure class="notion-asset-wrapper" :style="width">
19+
<figure class="notion-asset-wrapper" :style="[isType('image') ? 'width:100%' : '']">
1920
<NotionImage v-if="isType('image')" v-bind="pass" />
20-
<NotionAsset v-else-if="isType(['embed', 'video', 'figma'])" v-bind="pass" />
21+
<NotionAsset v-else-if="isType(['embed', 'video', 'figma', 'maps'])" v-bind="pass" />
22+
<NotionGoogleDrive v-else-if="isType('drive')" v-bind="pass" />
2123
<figcaption v-if="caption" class="notion-image-caption">
2224
<NotionTextRenderer :text="caption" v-bind="pass" />
2325
</figcaption>

src/blocks/helpers/google-drive.vue

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<script setup lang="ts">
2+
import { useNotionBlock, defineNotionProps } from "@/lib/blockable"
3+
import { computed } from "vue"
4+
import { useTimeAgo } from "@vueuse/core"
5+
6+
const props = defineProps({ ...defineNotionProps })
7+
//@ts-ignore
8+
const { format, block, hasPageLinkOptions, pageLinkProps } = useNotionBlock(props)
9+
10+
const properties = computed(() => format.value.drive_properties)
11+
12+
const constructThumbnail = (src?: string) => {
13+
if (!src) return
14+
const q = new URLSearchParams({
15+
table: "block",
16+
id: block.value.value.id,
17+
cache: "v2",
18+
})
19+
return "https://www.notion.so/image/" + encodeURIComponent(src) + "?" + q
20+
}
21+
const constructDomain = (src?: string) => {
22+
if (!src) return
23+
return new URL(src).hostname
24+
}
25+
</script>
26+
27+
<script lang="ts">
28+
export default {
29+
name: "NotionGoogleDrive",
30+
}
31+
</script>
32+
33+
<template>
34+
<div class="notion-google-drive">
35+
<a rel="noopener noreferrer" target="_blank" :href="properties.url" class="notion-google-drive-link">
36+
<div class="notion-google-drive-preview">
37+
<img :src="constructThumbnail(properties.thumbnail)" :alt="properties.title" />
38+
</div>
39+
40+
<div className="notion-google-drive-body">
41+
<div className="notion-google-drive-body-title">
42+
{{ properties.title }}
43+
</div>
44+
45+
<div className="notion-google-drive-body-modified-time">
46+
Last modified
47+
{{ properties.user_name ? `by ${properties.user_name} ` : "" }}
48+
{{ useTimeAgo(properties.modified_time).value }}
49+
</div>
50+
51+
<div className="notion-google-drive-body-source">
52+
<div
53+
className="notion-google-drive-body-source-icon"
54+
:style="{ backgroundImage: 'url(' + properties.icon + ')' }"
55+
/>
56+
<div className="notion-google-drive-body-source-domain">{{ constructDomain(properties.url) }}</div>
57+
</div>
58+
</div>
59+
</a>
60+
</div>
61+
</template>

src/blocks/tweet.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const props = defineProps({ ...defineNotionProps })
77
//@ts-ignore
88
const { properties } = useNotionBlock(props)
99
10-
const tweetId = computed(() => properties.value?.source?.[0]?.[0].split("status/")?.[1])
10+
const tweetId = computed(() => properties.value?.source?.[0]?.[0].split("status/")?.[1].split("?")[0])
1111
const el = ref<HTMLElement>()
1212
const error = ref()
1313

src/components/block.vue

+2-3
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@ const props = defineProps({ ...defineNotionProps })
2727
//@ts-ignore
2828
const { pass, type, format, isType } = useNotionBlock(props)
2929
if (!availableType.includes(type.value)) console.warn(`${type.value.toUpperCase()} is not implemented yet`)
30-
// console.log(type.value)
3130
</script>
3231

3332
<template>
3433
<div style="width: 100%" v-if="isType('page')">
35-
<NotionPage v-bind="pass">
34+
<NotionPage class="notion-page-content" v-bind="pass">
3635
<slot />
3736
</NotionPage>
3837
</div>
@@ -56,7 +55,7 @@ if (!availableType.includes(type.value)) console.warn(`${type.value.toUpperCase(
5655
<NotionList v-else-if="isType(['bulleted_list', 'numbered_list'])" v-bind="pass">
5756
<slot />
5857
</NotionList>
59-
<NotionFigure v-else-if="isType(['image', 'embed', 'figma', 'video', 'audio'])" v-bind="pass" />
58+
<NotionFigure v-else-if="isType(['image', 'embed', 'figma', 'video', 'audio', 'drive', 'maps'])" v-bind="pass" />
6059
<NotionTable v-else-if="isType('table')" v-bind="pass"><slot /></NotionTable>
6160
<NotionTableRow v-else-if="isType('table_row')" v-bind="pass" />
6261
<NotionTableOfContents v-else-if="isType('table_of_contents')" v-bind="pass"></NotionTableOfContents>

src/lib/types.ts

+13
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,22 @@ export interface Format {
3131
domain?: string
3232
original_url?: string
3333
page_icon?: string
34+
drive_properties: GoogleDriveProperties
3435
[key: string]: any
3536
}
3637

38+
export interface GoogleDriveProperties {
39+
file_id: string
40+
icon: string
41+
modified_time: number
42+
thumbnail: string
43+
title: string
44+
trashed: boolean
45+
url: string
46+
user_name: string
47+
version: string
48+
}
49+
3750
export interface Permission {
3851
role: Role
3952
type: string

src/style.css

+4-6
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,6 @@
156156

157157
.notion-page-content {
158158
width: 100%;
159-
display: flex;
160-
flex-direction: column;
161159
}
162160

163161
@media (min-width: 1300px) and (min-height: 300px) {
@@ -604,10 +602,10 @@ img.notion-page-icon-offset {
604602
padding-left: calc(min(12px, 8vw));
605603
padding-right: calc(min(12px, 8vw));
606604
}
607-
.notion-page > * {
605+
/* .notion-page > * {
608606
box-sizing: border-box;
609607
width: 100%;
610-
}
608+
} */
611609

612610
.notion-full-width {
613611
--notion-max-width: calc(min(1920px, 98vw));
@@ -782,7 +780,6 @@ svg.notion-page-icon {
782780
.notion-asset-wrapper {
783781
margin: 0.5rem 0;
784782
max-width: 100vw;
785-
width: 100%;
786783
min-width: 100%;
787784
align-self: center;
788785
display: flex;
@@ -1723,7 +1720,7 @@ svg.notion-page-icon {
17231720
border-radius: 3px;
17241721

17251722
user-select: none;
1726-
transition: background 20ms ease-in 0s;
1723+
transition: background 100ms ease-in 0s;
17271724
cursor: pointer;
17281725
}
17291726

@@ -2473,6 +2470,7 @@ svg.notion-page-icon {
24732470
.notion-tweet {
24742471
display: flex;
24752472
justify-content: center;
2473+
width: 100%;
24762474
}
24772475
.notion-tweet-error {
24782476
font-size: 0.8rem;

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"esModuleInterop": true,
1212
"declaration": true,
1313
"lib": ["esnext", "dom"],
14-
"types": ["vite/client"],
14+
"types": ["vite/client", "web-bluetooth"],
1515
"baseUrl": ".",
1616
"outDir": "dist",
1717
"paths": {

yarn.lock

+32
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@
377377
dependencies:
378378
"@types/node" "*"
379379

380+
"@types/web-bluetooth@^0.0.14":
381+
version "0.0.14"
382+
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.14.tgz#94e175b53623384bff1f354cdb3197a8d63cdbe5"
383+
integrity sha512-5d2RhCard1nQUC3aHcq/gHzWYO6K0WJmAbjO7mQJgCQKtZpgXxv1rOM6O/dBDhDYYVutk1sciOgNSe+5YyfM8A==
384+
380385
"@vitejs/plugin-vue@^2.0.0":
381386
version "2.3.3"
382387
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-2.3.3.tgz#fbf80cc039b82ac21a1acb0f0478de8f61fbf600"
@@ -576,6 +581,28 @@
576581
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.2.33.tgz#69a8c99ceb37c1b031d5cc4aec2ff1dc77e1161e"
577582
integrity sha512-UBc1Pg1T3yZ97vsA2ueER0F6GbJebLHYlEi4ou1H5YL4KWvMOOWwpYo9/QpWq93wxKG6Wo13IY74Hcn/f7c7Bg==
578583

584+
"@vueuse/core@^8.7.5":
585+
version "8.7.5"
586+
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-8.7.5.tgz#e74a888251ea11a9d432068ce18cbdfc4f810251"
587+
integrity sha512-tqgzeZGoZcXzoit4kOGLWJibDMLp0vdm6ZO41SSUQhkhtrPhAg6dbIEPiahhUu6sZAmSYvVrZgEr5aKD51nrLA==
588+
dependencies:
589+
"@types/web-bluetooth" "^0.0.14"
590+
"@vueuse/metadata" "8.7.5"
591+
"@vueuse/shared" "8.7.5"
592+
vue-demi "*"
593+
594+
595+
version "8.7.5"
596+
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-8.7.5.tgz#c7f2b21d873d1604a8860ed9c5728d8f3295f00a"
597+
integrity sha512-emJZKRQSaEnVqmlu39NpNp8iaW+bPC2kWykWoWOZMSlO/0QVEmO/rt8A5VhOEJTKLX3vwTevqbiRy9WJRwVOQg==
598+
599+
600+
version "8.7.5"
601+
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-8.7.5.tgz#06fb08f6f8fc9e90be9d1e033fa443de927172b0"
602+
integrity sha512-THXPvMBFmg6Gf6AwRn/EdTh2mhqwjGsB2Yfp374LNQSQVKRHtnJ0I42bsZTn7nuEliBxqUrGQm/lN6qUHmhJLw==
603+
dependencies:
604+
vue-demi "*"
605+
579606
acorn@^8.7.0:
580607
version "8.7.0"
581608
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
@@ -2412,6 +2439,11 @@ vite@^2.9.7:
24122439
optionalDependencies:
24132440
fsevents "~2.3.2"
24142441

2442+
vue-demi@*:
2443+
version "0.13.2"
2444+
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.13.2.tgz#f6081c2feb5b698549729a81683ce029b8da289e"
2445+
integrity sha512-41ukrclEbMddAyP7PvxMSYqnOSzPV6r7GNnyTSKSCNTaz19GehxmTiXyP9kwHSUv2+Dr6hHqiUiF7L1VAw2KdQ==
2446+
24152447
vue-router@4:
24162448
version "4.0.14"
24172449
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.14.tgz#ce2028c1c5c33e30c7287950c973f397fce1bd65"

0 commit comments

Comments
 (0)