aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-08-17 14:36:52 +0200
committerGravatar Corentin Thomasset <corentin.thomasset74@gmail.com> 2022-08-19 17:40:00 +0200
commit164e32b4428b8dfaaddcefa06b767a8af94573a9 (patch)
tree104babab05662dbcb89e6f9e06ebc19a60957ecd /src
parent49755909bdaea9399e51b67fbd1a6d071acd3182 (diff)
downloadit-tools-164e32b4428b8dfaaddcefa06b767a8af94573a9.tar.gz
it-tools-164e32b4428b8dfaaddcefa06b767a8af94573a9.tar.zst
it-tools-164e32b4428b8dfaaddcefa06b767a8af94573a9.zip
feat(new-tool): meta tag generator
Diffstat (limited to 'src')
-rw-r--r--src/components/TextareaCopyable.vue2
-rw-r--r--src/plugins/naive.plugin.ts72
-rw-r--r--src/tools/index.ts3
-rw-r--r--src/tools/meta-tag-generator/OGSchemaType.type.ts27
-rw-r--r--src/tools/meta-tag-generator/index.ts25
-rw-r--r--src/tools/meta-tag-generator/meta-tag-generator.vue94
-rw-r--r--src/tools/meta-tag-generator/og-schemas/article.ts33
-rw-r--r--src/tools/meta-tag-generator/og-schemas/book.ts16
-rw-r--r--src/tools/meta-tag-generator/og-schemas/image.ts31
-rw-r--r--src/tools/meta-tag-generator/og-schemas/index.ts31
-rw-r--r--src/tools/meta-tag-generator/og-schemas/musicAlbum.ts27
-rw-r--r--src/tools/meta-tag-generator/og-schemas/musicPlaylist.ts21
-rw-r--r--src/tools/meta-tag-generator/og-schemas/musicRadioStation.ts8
-rw-r--r--src/tools/meta-tag-generator/og-schemas/musicSong.ts22
-rw-r--r--src/tools/meta-tag-generator/og-schemas/profile.ts21
-rw-r--r--src/tools/meta-tag-generator/og-schemas/twitter.ts31
-rw-r--r--src/tools/meta-tag-generator/og-schemas/videoEpisode.ts10
-rw-r--r--src/tools/meta-tag-generator/og-schemas/videoMovie.ts29
-rw-r--r--src/tools/meta-tag-generator/og-schemas/videoOther.ts7
-rw-r--r--src/tools/meta-tag-generator/og-schemas/videoTVShow.ts7
-rw-r--r--src/tools/meta-tag-generator/og-schemas/website.ts56
21 files changed, 537 insertions, 36 deletions
diff --git a/src/components/TextareaCopyable.vue b/src/components/TextareaCopyable.vue
index 49fb96d..12d189e 100644
--- a/src/components/TextareaCopyable.vue
+++ b/src/components/TextareaCopyable.vue
@@ -33,10 +33,12 @@ import { useClipboard, useElementSize } from '@vueuse/core';
import hljs from 'highlight.js/lib/core';
import jsonHljs from 'highlight.js/lib/languages/json';
import sqlHljs from 'highlight.js/lib/languages/sql';
+import xmlHljs from 'highlight.js/lib/languages/xml';
import { ref, toRefs } from 'vue';
hljs.registerLanguage('sql', sqlHljs);
hljs.registerLanguage('json', jsonHljs);
+hljs.registerLanguage('html', xmlHljs);
const props = withDefaults(
defineProps<{
diff --git a/src/plugins/naive.plugin.ts b/src/plugins/naive.plugin.ts
index 4662798..981d787 100644
--- a/src/plugins/naive.plugin.ts
+++ b/src/plugins/naive.plugin.ts
@@ -1,60 +1,62 @@
import {
create,
+ NAlert,
+ NAutoComplete,
NButton,
- NConfigProvider,
NCard,
- NInput,
+ NCode,
+ NCollapse,
+ NCollapseItem,
+ NCollapseTransition,
NColorPicker,
- NInputNumber,
- NSpace,
- NH1,
+ NConfigProvider,
+ NDatePicker,
+ NDivider,
+ NDropdown,
+ NDynamicInput,
+ NEllipsis,
+ NEmpty,
NForm,
NFormItem,
- NTimePicker,
- NText,
- NIcon,
- NSwitch,
- NCollapseTransition,
+ NGradientText,
NGrid,
NGridItem,
- NPopconfirm,
- NSlider,
- NCollapse,
- NCollapseItem,
- NProgress,
- NAutoComplete,
- NSelect,
- NUpload,
- NEmpty,
- NModal,
- NTooltip,
- NAlert,
- NP,
+ NH1,
NH2,
- NDropdown,
+ NH3,
+ NIcon,
+ NImage,
+ NInput,
+ NInputGroup,
+ NInputGroupLabel,
+ NInputNumber,
NLayout,
NLayoutSider,
NMenu,
NMessageProvider,
+ NModal,
+ NP,
NPageHeader,
+ NPopconfirm,
+ NProgress,
NResult,
- NH3,
- NEllipsis,
- NTag,
- NInputGroup,
- NInputGroupLabel,
- NDivider,
+ NScrollbar,
+ NSelect,
+ NSlider,
+ NSpace,
NStatistic,
+ NSwitch,
NTable,
+ NTag,
+ NText,
+ NTimePicker,
+ NTooltip,
+ NUpload,
NUploadDragger,
- NImage,
- NScrollbar,
- NGradientText,
- NCode,
- NDatePicker,
} from 'naive-ui';
const components = [
+ NDynamicInput,
NDatePicker,
NCode,
NGradientText,
diff --git a/src/tools/index.ts b/src/tools/index.ts
index a03f273..80f1618 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -22,6 +22,7 @@ import { tool as baseConverter } from './integer-base-converter';
import { tool as jsonViewer } from './json-viewer';
import { tool as loremIpsumGenerator } from './lorem-ipsum-generator';
import { tool as mathEvaluator } from './math-evaluator';
+import { tool as metaTagGenerator } from './meta-tag-generator';
import { tool as qrCodeGenerator } from './qr-code-generator';
import { tool as randomPortGenerator } from './random-port-generator';
import { tool as romanNumeralConverter } from './roman-numeral-converter';
@@ -55,7 +56,7 @@ export const toolsByCategory: ToolCategory[] = [
{
name: 'Web',
icon: LockOpen,
- components: [urlEncoder, htmlEntities, urlParser, deviceInformation, basicAuthGenerator],
+ components: [urlEncoder, htmlEntities, urlParser, deviceInformation, basicAuthGenerator, metaTagGenerator],
},
{
name: 'Images',
diff --git a/src/tools/meta-tag-generator/OGSchemaType.type.ts b/src/tools/meta-tag-generator/OGSchemaType.type.ts
new file mode 100644
index 0000000..8d09013
--- /dev/null
+++ b/src/tools/meta-tag-generator/OGSchemaType.type.ts
@@ -0,0 +1,27 @@
+import type { SelectGroupOption, SelectOption } from 'naive-ui';
+
+export type { OGSchemaType, OGSchemaTypeElementInput, OGSchemaTypeElementSelect, OGSchemaTypeElementInputMultiple };
+
+interface OGSchemaTypeElementBase {
+ key: string;
+ label: string;
+ placeholder: string;
+}
+
+interface OGSchemaTypeElementInput extends OGSchemaTypeElementBase {
+ type: 'input';
+}
+
+interface OGSchemaTypeElementInputMultiple extends OGSchemaTypeElementBase {
+ type: 'input-multiple';
+}
+
+interface OGSchemaTypeElementSelect extends OGSchemaTypeElementBase {
+ type: 'select';
+ options: Array<SelectOption | SelectGroupOption>;
+}
+
+interface OGSchemaType {
+ name: string;
+ elements: (OGSchemaTypeElementSelect | OGSchemaTypeElementInput | OGSchemaTypeElementInputMultiple)[];
+}
diff --git a/src/tools/meta-tag-generator/index.ts b/src/tools/meta-tag-generator/index.ts
new file mode 100644
index 0000000..c79b19f
--- /dev/null
+++ b/src/tools/meta-tag-generator/index.ts
@@ -0,0 +1,25 @@
+import { Tags } from '@vicons/tabler';
+import { defineTool } from '../tool';
+
+export const tool = defineTool({
+ name: 'Open graph meta generator',
+ path: '/og-meta-generator',
+ description: 'Generate open-graph and socials html meta tags for your website.',
+ keywords: [
+ 'meta',
+ 'tag',
+ 'generator',
+ 'social',
+ 'title',
+ 'description',
+ 'image',
+ 'share',
+ 'online',
+ 'website',
+ 'open',
+ 'graph',
+ 'og',
+ ],
+ component: () => import('./meta-tag-generator.vue'),
+ icon: Tags,
+});
diff --git a/src/tools/meta-tag-generator/meta-tag-generator.vue b/src/tools/meta-tag-generator/meta-tag-generator.vue
new file mode 100644
index 0000000..ee5d8e7
--- /dev/null
+++ b/src/tools/meta-tag-generator/meta-tag-generator.vue
@@ -0,0 +1,94 @@
+<template>
+ <div>
+ <div v-for="{ name, elements } of sections" :key="name" style="margin-bottom: 15px">
+ <n-form-item :label="name" :show-feedback="false"> </n-form-item>
+
+ <n-input-group v-for="{ key, type, label, placeholder, ...element } of elements" :key="key">
+ <n-input-group-label style="flex: 0 0 110px">{{ label }}</n-input-group-label>
+ <n-input v-if="type === 'input'" v-model:value="metadata[key]" :placeholder="placeholder" />
+ <n-dynamic-input
+ v-else-if="type === 'input-multiple'"
+ v-model:value="metadata[key]"
+ :min="1"
+ :placeholder="placeholder"
+ :default-value="['']"
+ :show-sort-button="true"
+ />
+
+ <n-select
+ v-else-if="type === 'select'"
+ v-model:value="metadata[key]"
+ :placeholder="placeholder"
+ :options="(element as OGSchemaTypeElementSelect).options"
+ />
+ </n-input-group>
+ </div>
+ </div>
+ <div>
+ <n-form-item label="Your meta tags">
+ <textarea-copyable :value="metaTags" language="html" />
+ </n-form-item>
+ </div>
+</template>
+
+<script setup lang="ts">
+import TextareaCopyable from '@/components/TextareaCopyable.vue';
+import { generateMeta } from '@it-tools/oggen';
+import _ from 'lodash';
+import { computed, ref, watch } from 'vue';
+import { image, ogSchemas, twitter, website } from './og-schemas';
+import type { OGSchemaType, OGSchemaTypeElementSelect } from './OGSchemaType.type';
+
+// Since type guards do not work in template
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const metadata = ref<{ type: string; [k: string]: any }>({
+ type: 'website',
+ 'twitter:card': 'summary_large_image',
+});
+
+watch(
+ () => ref(metadata.value.type),
+ (_ignored, prevSection) => {
+ const section = ogSchemas[prevSection.value];
+
+ if (!section) return;
+
+ section.elements.forEach(({ key }) => {
+ metadata.value[key] = '';
+ });
+ },
+);
+
+const sections = computed(() => {
+ const secs: OGSchemaType[] = [website, image, twitter];
+ const additionalSchema = ogSchemas[metadata.value.type];
+
+ if (additionalSchema) secs.push(additionalSchema);
+
+ return secs;
+});
+
+const metaTags = computed(() => {
+ const twitterMeta = _.chain(metadata.value)
+ .pickBy((_value, k) => k.startsWith('twitter:'))
+ .mapKeys((_value, k) => k.replace(/^twitter:/, ''))
+ .value();
+
+ const otherMeta = _.pickBy(metadata.value, (_value, k) => !k.startsWith('twitter:'));
+
+ return generateMeta({ ...otherMeta, twitter: twitterMeta }, { generateTwitterCompatibleMeta: true });
+});
+</script>
+
+<style lang="less" scoped>
+.n-input-group {
+ margin-bottom: 5px;
+}
+
+::v-deep(.n-form-item-blank) {
+ min-height: 0 !important;
+}
+::v-deep(.n-dynamic-input-item) {
+ margin-bottom: 5px;
+}
+</style>
diff --git a/src/tools/meta-tag-generator/og-schemas/article.ts b/src/tools/meta-tag-generator/og-schemas/article.ts
new file mode 100644
index 0000000..3d2ce92
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/article.ts
@@ -0,0 +1,33 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const article: OGSchemaType = {
+ name: 'Article',
+ elements: [
+ {
+ type: 'input',
+ label: 'Publishing date',
+ key: 'article:published_time',
+ placeholder: 'When the article was first published...',
+ },
+ {
+ type: 'input',
+ label: 'Modification date',
+ key: 'article:modified_time',
+ placeholder: 'When the article was last changed...',
+ },
+ {
+ type: 'input',
+ label: 'Expiration date',
+ key: 'article:expiration_time',
+ placeholder: 'When the article is out of date after...',
+ },
+ { type: 'input', label: 'Author', key: 'article:author', placeholder: 'Writers of the article...' },
+ {
+ type: 'input',
+ label: 'Section',
+ key: 'article:section',
+ placeholder: 'A high-level section name. E.g. Technology..',
+ },
+ { type: 'input', label: 'Tag', key: 'article:tag', placeholder: 'Tag words associated with this article...' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/book.ts b/src/tools/meta-tag-generator/og-schemas/book.ts
new file mode 100644
index 0000000..f01733f
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/book.ts
@@ -0,0 +1,16 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const book: OGSchemaType = {
+ name: 'Book',
+ elements: [
+ { type: 'input', label: 'Author', key: 'book:author', placeholder: 'Who wrote this book...' },
+ { type: 'input', label: 'ISBN', key: 'book:isbn', placeholder: 'The International Standard Book Number...' },
+ {
+ type: 'input',
+ label: 'Release date',
+ key: 'book:release_date',
+ placeholder: 'The date the book was released...',
+ },
+ { type: 'input', label: 'Tag', key: 'book:tag', placeholder: 'Tag words associated with this book...' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/image.ts b/src/tools/meta-tag-generator/og-schemas/image.ts
new file mode 100644
index 0000000..60a4c5a
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/image.ts
@@ -0,0 +1,31 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const image: OGSchemaType = {
+ name: 'Image',
+ elements: [
+ {
+ type: 'input',
+ label: 'Image url',
+ placeholder: 'The url of your website social image...',
+ key: 'image',
+ },
+ {
+ type: 'input',
+ label: 'Image alt',
+ placeholder: 'The alternative text of your website social image...',
+ key: 'image:alt',
+ },
+ {
+ type: 'input',
+ label: 'Width',
+ placeholder: 'Width in px of your website social image...',
+ key: 'image:width',
+ },
+ {
+ type: 'input',
+ label: 'Height',
+ placeholder: 'Height in px of your website social image...',
+ key: 'image:height',
+ },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/index.ts b/src/tools/meta-tag-generator/og-schemas/index.ts
new file mode 100644
index 0000000..9c3f100
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/index.ts
@@ -0,0 +1,31 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+import { article } from './article';
+import { book } from './book';
+import { musicAlbum } from './musicAlbum';
+import { musicPlaylist } from './musicPlaylist';
+import { musicRadioStation } from './musicRadioStation';
+import { musicSong } from './musicSong';
+import { profile } from './profile';
+import { videoEpisode } from './videoEpisode';
+import { videoMovie } from './videoMovie';
+import { videoOther } from './videoOther';
+import { videoTVShow } from './videoTVShow';
+
+export * from './image';
+export * from './twitter';
+export * from './website';
+
+export const ogSchemas: Record<string, OGSchemaType> = {
+ 'music.song': musicSong,
+ 'music.album': musicAlbum,
+ 'music.playlist': musicPlaylist,
+ 'music.radio_station': musicRadioStation,
+ 'video.movie': videoMovie,
+ 'video.episode': videoEpisode,
+ 'video.tv_show': videoTVShow,
+ 'video.other': videoOther,
+ profile,
+ article,
+ book,
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/musicAlbum.ts b/src/tools/meta-tag-generator/og-schemas/musicAlbum.ts
new file mode 100644
index 0000000..225423c
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/musicAlbum.ts
@@ -0,0 +1,27 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const musicAlbum: OGSchemaType = {
+ name: 'Album details',
+ elements: [
+ { type: 'input', label: 'Song', key: 'music:song', placeholder: 'The song on this album...' },
+ {
+ type: 'input',
+ label: 'Disc',
+ key: 'music:song:disc',
+ placeholder: 'The same as music:album:disc but in reverse...',
+ },
+ {
+ type: 'input',
+ label: 'Track',
+ key: 'music:song:track',
+ placeholder: 'The same as music:album:track but in reverse...',
+ },
+ { type: 'input', label: 'Musician', key: 'music:musician', placeholder: 'The musician that made this song...' },
+ {
+ type: 'input',
+ label: 'Release date',
+ key: 'music:release_date',
+ placeholder: 'The date the album was released...',
+ },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/musicPlaylist.ts b/src/tools/meta-tag-generator/og-schemas/musicPlaylist.ts
new file mode 100644
index 0000000..610dd8e
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/musicPlaylist.ts
@@ -0,0 +1,21 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const musicPlaylist: OGSchemaType = {
+ name: 'Playlist details',
+ elements: [
+ { type: 'input', label: 'Song', key: 'music:song', placeholder: 'The song on this album...' },
+ {
+ type: 'input',
+ label: 'Disc',
+ key: 'music:song:disc',
+ placeholder: 'The same as music:album:disc but in reverse...',
+ },
+ {
+ type: 'input',
+ label: 'Track',
+ key: 'music:song:track',
+ placeholder: 'The same as music:album:track but in reverse...',
+ },
+ { type: 'input', label: 'Creator', key: 'music:creator', placeholder: 'The creator of this playlist...' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/musicRadioStation.ts b/src/tools/meta-tag-generator/og-schemas/musicRadioStation.ts
new file mode 100644
index 0000000..d4c1126
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/musicRadioStation.ts
@@ -0,0 +1,8 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const musicRadioStation: OGSchemaType = {
+ name: 'Radio station details',
+ elements: [
+ { type: 'input', label: 'Creator', key: 'music:creator', placeholder: 'The creator of this radio station...' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/musicSong.ts b/src/tools/meta-tag-generator/og-schemas/musicSong.ts
new file mode 100644
index 0000000..018ce17
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/musicSong.ts
@@ -0,0 +1,22 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const musicSong: OGSchemaType = {
+ name: 'Song details',
+ elements: [
+ { type: 'input', label: 'Duration', placeholder: 'The duration of the song...', key: 'music:duration' },
+ { type: 'input', label: 'Album', placeholder: 'The album this song is from...', key: 'music:album' },
+ {
+ type: 'input',
+ label: 'Disc',
+ placeholder: 'Which disc of the album this song is on...',
+ key: 'music:album:disk',
+ },
+ { type: 'input', label: 'Track', placeholder: ' Which track this song is...', key: 'music:album:track' },
+ {
+ type: 'input-multiple',
+ label: 'Musician',
+ placeholder: 'The musician that made this song...',
+ key: 'music:musician',
+ },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/profile.ts b/src/tools/meta-tag-generator/og-schemas/profile.ts
new file mode 100644
index 0000000..b0bc189
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/profile.ts
@@ -0,0 +1,21 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const profile: OGSchemaType = {
+ name: 'Profile',
+ elements: [
+ {
+ type: 'input',
+ label: 'First name',
+ placeholder: 'Enter the first name of the person...',
+ key: 'profile:first_name',
+ },
+ {
+ type: 'input',
+ label: 'Last name',
+ placeholder: 'Enter the last name of the person...',
+ key: 'profile:last_name',
+ },
+ { type: 'input', label: 'Username', placeholder: 'Enter the username of the person...', key: 'profile:username' },
+ { type: 'input', label: 'Gender', placeholder: 'Enter the gender of the person...', key: 'profile:gender' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/twitter.ts b/src/tools/meta-tag-generator/og-schemas/twitter.ts
new file mode 100644
index 0000000..94a9834
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/twitter.ts
@@ -0,0 +1,31 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const twitter: OGSchemaType = {
+ name: 'Twitter',
+ elements: [
+ {
+ type: 'select',
+ options: [
+ { label: 'Summary', value: 'summary' },
+ { label: 'Summary with large image', value: 'summary_large_image' },
+ { label: 'Application', value: 'app' },
+ { label: 'Player', value: 'player' },
+ ],
+ label: 'Card type',
+ placeholder: 'The twitter card type...',
+ key: 'twitter:card',
+ },
+ {
+ type: 'input',
+ label: 'Site account',
+ placeholder: 'The name of the twitter account of the site (ex: @ittoolsdottech)...',
+ key: 'twitter:site',
+ },
+ {
+ type: 'input',
+ label: 'Creator acc.',
+ placeholder: 'The name of the twitter account of the creator (ex: @cthmsst)...',
+ key: 'twitter:creator',
+ },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/videoEpisode.ts b/src/tools/meta-tag-generator/og-schemas/videoEpisode.ts
new file mode 100644
index 0000000..b8a036e
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/videoEpisode.ts
@@ -0,0 +1,10 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+import { videoMovie } from './videoMovie';
+
+export const videoEpisode: OGSchemaType = {
+ name: 'Video episode details',
+ elements: [
+ ...videoMovie.elements,
+ { type: 'input', label: 'Series', key: 'video:series', placeholder: 'Which series this episode belongs to...' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/videoMovie.ts b/src/tools/meta-tag-generator/og-schemas/videoMovie.ts
new file mode 100644
index 0000000..6d5b02d
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/videoMovie.ts
@@ -0,0 +1,29 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+export const videoMovie: OGSchemaType = {
+ name: 'Movie details',
+ elements: [
+ {
+ type: 'input-multiple',
+ label: 'Actor',
+ key: 'video:actor',
+ placeholder: 'Name of the actress/actor...',
+ },
+ // { type: 'input', label: 'Actor role', key: 'video:actor:role', placeholder: 'The role they played...' },
+ {
+ type: 'input-multiple',
+ label: 'Director',
+ key: 'video:director',
+ placeholder: 'Name of the director...',
+ },
+ { type: 'input-multiple', label: 'Writer', key: 'video:writer', placeholder: 'Writers of the movie...' },
+ { type: 'input', label: 'Duration', key: 'video:duration', placeholder: "The movie's length in seconds..." },
+ {
+ type: 'input',
+ label: 'Release date',
+ key: 'video:release_date',
+ placeholder: 'The date the movie was released...',
+ },
+ { type: 'input', label: 'Tag', key: 'video:tag', placeholder: 'Tag words associated with this movie...' },
+ ],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/videoOther.ts b/src/tools/meta-tag-generator/og-schemas/videoOther.ts
new file mode 100644
index 0000000..5bc9679
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/videoOther.ts
@@ -0,0 +1,7 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+import { videoMovie } from './videoMovie';
+
+export const videoOther: OGSchemaType = {
+ name: 'Other video details',
+ elements: [...videoMovie.elements],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/videoTVShow.ts b/src/tools/meta-tag-generator/og-schemas/videoTVShow.ts
new file mode 100644
index 0000000..5180c03
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/videoTVShow.ts
@@ -0,0 +1,7 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+import { videoMovie } from './videoMovie';
+
+export const videoTVShow: OGSchemaType = {
+ name: 'TV show details',
+ elements: [...videoMovie.elements],
+};
diff --git a/src/tools/meta-tag-generator/og-schemas/website.ts b/src/tools/meta-tag-generator/og-schemas/website.ts
new file mode 100644
index 0000000..15053e3
--- /dev/null
+++ b/src/tools/meta-tag-generator/og-schemas/website.ts
@@ -0,0 +1,56 @@
+import type { OGSchemaType } from '../OGSchemaType.type';
+
+const typeOptions = [
+ { label: 'Website', value: 'website' },
+ { label: 'Article', value: 'article' },
+ { label: 'Book', value: 'book' },
+ { label: 'Profile', value: 'profile' },
+ {
+ type: 'group',
+ label: 'Music',
+ key: 'Music',
+ children: [
+ { label: 'Song', value: 'music.song' },
+ { label: 'Music album', value: 'music.album' },
+ { label: 'Playlist', value: 'music.playlist' },
+ { label: 'Radio station', value: 'music.radio_station' },
+ ],
+ },
+ {
+ type: 'group',
+ label: 'Video',
+ key: 'Video',
+ children: [
+ { label: 'Movie', value: 'video.movie' },
+ { label: 'Episode', value: 'video.episode' },
+ { label: 'TV show', value: 'video.tv_show' },
+ { label: 'Other video', value: 'video.other' },
+ ],
+ },
+];
+
+export const website: OGSchemaType = {
+ name: 'General information',
+ elements: [
+ {
+ type: 'select',
+ label: 'Page type',
+ placeholder: 'Select the type of your website...',
+ key: 'type',
+ options: typeOptions,
+ },
+ { type: 'input', label: 'Title', placeholder: 'Enter the title of your website...', key: 'title' },
+ {
+ type: 'input',
+ label: 'Description',
+ placeholder: 'Enter the description of your website...',
+ key: 'description',
+ },
+ {
+ type: 'input',
+ label: 'Page URL',
+ placeholder: 'Enter the url of your website...',
+ key: 'url',
+ },
+ ],
+};