Skip to content

Commit

Permalink
Add separated tweet-url prop
Browse files Browse the repository at this point in the history
  • Loading branch information
DannyFeliz committed May 31, 2022
1 parent b83284a commit 31b13a7
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 35 deletions.
20 changes: 16 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This project was developed using Vue 3 + Typescript + Vite 🚀

[![Edit Demo vue-tweet](https://user-images.githubusercontent.com/5460365/161323040-d73231f8-db73-48ef-adab-433558502585.png)](https://stackblitz.com/edit/vitejs-vite-c5qu9k?file=src/App.vue)

[![Preview](https://user-images.githubusercontent.com/5460365/131345071-7d143b12-2d8d-4920-a231-d8b3acc21bb0.png)](https://stackblitz.com/edit/vitejs-vite-c5qu9k?file=src/App.vue)
[![Preview](https://user-images.githubusercontent.com/5460365/171073819-e6e97952-a851-48cd-80f8-d72489efd57b.png)](https://stackblitz.com/edit/vitejs-vite-c5qu9k?file=src/App.vue)

## Installation

Expand Down Expand Up @@ -44,20 +44,32 @@ import Tweet from "vue-tweet";
<template>
<Tweet
tweet-id="https://twitter.com/DannyFeliz08/status/1530240085807054848"
tweet-url="https://twitter.com/DannyFeliz08/status/1530240085807054848"
/>
</template>
```

# Props - [Embedded Tweet parameter reference](https://developer.twitter.com/en/docs/twitter-for-websites/embedded-tweets/guides/embedded-tweet-parameter-reference)

### Note: You must provide either `tweet-id` or `tweet-url`.

**tweet-id**

Type: `string`

`Required`
Default: `''`

The numerical ID of the desired Tweet.

<hr />

**tweet-url**

Type: `string`

Default: `''`

The numerical ID of the desired Tweet or the Tweet URL.
The Tweet URL.

<hr />

Expand Down
2 changes: 1 addition & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<TweetEmbed
tweetId="1530240085807054848"
tweet-url="https://twitter.com/DannyFeliz08/status/1530240085807054848"
cards="visible"
conversation="all"
lang="en"
Expand Down
138 changes: 108 additions & 30 deletions src/components/vue-tweet.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,74 @@
</template>

<script lang="ts">
import { defineComponent, ref, onMounted, PropType, nextTick, watch } from "vue";
const langs = ["ar", "bn", "cs", "da", "de", "el", "en", "es", "fa", "fi", "fil", "fr", "he", "hi", "hu", "id", "it", "ja", "ko", "msa", "nl", "no", "pl", "pt", "ro", "ru", "sv", "th", "tr", "uk", "ur", "vi", "zh-cn", "zh-tw"] as const;
const TWEET_URL_REGEX = /^(https?:\/\/)?(www\.)?twitter\.com\/.*\/status(?:es)?\/(?<tweetId>[^\/\?]\d+)$/i;
import {
defineComponent,
ref,
onMounted,
PropType,
nextTick,
watch,
} from "vue";
const langs = [
"ar",
"bn",
"cs",
"da",
"de",
"el",
"en",
"es",
"fa",
"fi",
"fil",
"fr",
"he",
"hi",
"hu",
"id",
"it",
"ja",
"ko",
"msa",
"nl",
"no",
"pl",
"pt",
"ro",
"ru",
"sv",
"th",
"tr",
"uk",
"ur",
"vi",
"zh-cn",
"zh-tw",
] as const;
const TWEET_URL_REGEX =
/^(https?:\/\/)?(www\.)?twitter\.com\/.*\/status(?:es)?\/(?<tweetId>[^\/\?]\d+)$/i;
export default defineComponent({
props: {
/**
The numerical ID of the desired Tweet or the Tweet URL.
The numerical ID of the desired Tweet.
@example
<TweetEmbed tweetId="20" />
*/
tweetId: {
type: String,
default: "",
},
/**
The Tweet URL.
@example
<TweetEmbed tweetId="https://twitter.com/jack/status/20" />
*/
tweetId: {
tweetUrl: {
type: String,
required: true
default: "",
},
/**
* When set to none, only the cited Tweet will be displayed even if it is in reply to another Tweet.
Expand All @@ -31,7 +81,7 @@ export default defineComponent({
conversation: {
type: String as PropType<"all" | "none">,
default: "all",
validator: (value: string) => ["all", "none"].includes(value)
validator: (value: string) => ["all", "none"].includes(value),
},
/**
* When set to hidden, links in a Tweet are not expanded to photo, video, or link previews.
Expand All @@ -40,7 +90,7 @@ export default defineComponent({
cards: {
type: String as PropType<"visible" | "hidden">,
default: "visible",
validator: (value: string) => ["visible", "hidden"].includes(value)
validator: (value: string) => ["visible", "hidden"].includes(value),
},
/**
* The maximum width of the rendered Tweet in whole pixels. This value should be between 250 and 550 pixels.
Expand All @@ -59,16 +109,19 @@ export default defineComponent({
}
return false;
}
},
},
/**
* Float the Tweet left, right, or center relative to its container. Typically set to allow text or other content to wrap around the Tweet.
* @default undefined
*/
align: {
type: [String, undefined] as PropType<"left" | "right" | "center" | undefined>,
type: [String, undefined] as PropType<
"left" | "right" | "center" | undefined
>,
default: undefined,
validator: (value: string | undefined) => ["left", "right", "center", undefined].includes(value)
validator: (value: string | undefined) =>
["left", "right", "center", undefined].includes(value),
},
/**
* When set to dark, displays Tweet with light text over a dark background.
Expand All @@ -77,7 +130,7 @@ export default defineComponent({
theme: {
type: String as PropType<"light" | "dark">,
default: "light",
validator: (value: string) => ["light", "dark"].includes(value)
validator: (value: string) => ["light", "dark"].includes(value),
},
/**
* A supported Twitter language code. Loads text components in the specified language. Note: does not affect the text of the cited Tweet.
Expand All @@ -86,19 +139,20 @@ export default defineComponent({
lang: {
type: String as PropType<typeof langs[number]>,
default: "en",
validator: (value: typeof langs[number]) => langs.includes(value)
validator: (value: typeof langs[number]) => langs.includes(value),
},
/**
* When set to true, the Tweet and its embedded page on your site are not used for purposes that include personalized suggestions and personalized ads.
* @default false
*/
dnt: {
type: Boolean,
default: false
}
default: false,
},
},
emits: {
"tweet-load-success": (twitterWidgetElement: HTMLDivElement) => !!twitterWidgetElement,
"tweet-load-success": (twitterWidgetElement: HTMLDivElement) =>
!!twitterWidgetElement,
"tweet-load-error": () => true,
},
setup(props, { attrs, emit }) {
Expand All @@ -108,13 +162,13 @@ export default defineComponent({
onMounted(() => {
renderTweet();
})
});
watch(props, () => {
renderTweet();
})
});
function renderTweet() {
function renderTweet(): void {
if (!(window["twttr"] && window["twttr"].ready)) {
addScript("https://platform.twitter.com/widgets.js", renderTweet);
return;
Expand All @@ -128,14 +182,10 @@ export default defineComponent({
tweetContainerRef.value.innerHTML = "";
}
let { tweetId, ...options } = props;
const match = tweetId.trim().match(TWEET_URL_REGEX);
if (match) {
tweetId = match.groups?.tweetId as string;
}
const { tweetId, tweetOptions } = getTweetParams();
widgets
.createTweet(tweetId, tweetContainerRef.value, options)
.createTweet(tweetId, tweetContainerRef.value, tweetOptions)
.then(async (twitterWidgetElement: HTMLDivElement | undefined) => {
// Since we're mutating the DOM directly with the embed we need to tell Vue wait until the DOM update
await nextTick();
Expand All @@ -149,8 +199,36 @@ export default defineComponent({
})
.finally(() => {
isLoading.value = false;
})
})
});
});
}
function getTweetParams() {
let { tweetId, tweetUrl, ...tweetOptions } = props;
if (tweetId && tweetUrl) {
throw new Error("Cannot provide both tweet-id and tweet-url.");
} else if (tweetId) {
if (!/^\d+$/.test(tweetId)) {
throw new Error(
"Invalid tweet-id, please provide a valid numerical tweet-id."
);
}
} else if (tweetUrl) {
const match = tweetUrl.trim().match(TWEET_URL_REGEX);
if (match) {
tweetId = match.groups?.tweetId as string;
} else {
throw new Error("Invalid tweet-url.");
}
} else {
throw new Error("Must provide either tweet-id or tweet-url.");
}
return {
tweetId,
tweetOptions,
};
}
function addScript(src: string, cb: () => void): void {
Expand All @@ -160,7 +238,7 @@ export default defineComponent({
document.body.appendChild(s);
}
return { tweetContainerRef, isLoading, hasError, attrs }
}
})
return { tweetContainerRef, isLoading, hasError, attrs };
},
});
</script>

0 comments on commit 31b13a7

Please sign in to comment.