my-meta
This commit is contained in:
parent
f6043ad223
commit
f992cf9377
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -36,7 +36,6 @@
|
||||||
"@solid-primitives/share": "2.0.4",
|
"@solid-primitives/share": "2.0.4",
|
||||||
"@solid-primitives/storage": "^3.5.0",
|
"@solid-primitives/storage": "^3.5.0",
|
||||||
"@solid-primitives/upload": "0.0.115",
|
"@solid-primitives/upload": "0.0.115",
|
||||||
"@solidjs/meta": "0.29.3",
|
|
||||||
"@thisbeyond/solid-select": "0.14.0",
|
"@thisbeyond/solid-select": "0.14.0",
|
||||||
"@tiptap/core": "2.2.3",
|
"@tiptap/core": "2.2.3",
|
||||||
"@tiptap/extension-blockquote": "2.2.3",
|
"@tiptap/extension-blockquote": "2.2.3",
|
||||||
|
@ -4106,15 +4105,6 @@
|
||||||
"solid-js": "^1.6.12"
|
"solid-js": "^1.6.12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@solidjs/meta": {
|
|
||||||
"version": "0.29.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/@solidjs/meta/-/meta-0.29.3.tgz",
|
|
||||||
"integrity": "sha512-R2uirgjgyh3FPFh+rb840plF701N6GvM5w81/QeI61QwjXb4QzLkyI/uzXfC5UW8favpUn9KK9ILQeoTl6pX0A==",
|
|
||||||
"dev": true,
|
|
||||||
"peerDependencies": {
|
|
||||||
"solid-js": ">=1.8.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@thisbeyond/solid-select": {
|
"node_modules/@thisbeyond/solid-select": {
|
||||||
"version": "0.14.0",
|
"version": "0.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/@thisbeyond/solid-select/-/solid-select-0.14.0.tgz",
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
"@solid-primitives/share": "2.0.4",
|
"@solid-primitives/share": "2.0.4",
|
||||||
"@solid-primitives/storage": "^3.5.0",
|
"@solid-primitives/storage": "^3.5.0",
|
||||||
"@solid-primitives/upload": "0.0.115",
|
"@solid-primitives/upload": "0.0.115",
|
||||||
"@solidjs/meta": "0.29.3",
|
|
||||||
"@thisbeyond/solid-select": "0.14.0",
|
"@thisbeyond/solid-select": "0.14.0",
|
||||||
"@tiptap/core": "2.2.3",
|
"@tiptap/core": "2.2.3",
|
||||||
"@tiptap/extension-blockquote": "2.2.3",
|
"@tiptap/extension-blockquote": "2.2.3",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { PageProps, RootSearchParams } from '../pages/types'
|
import type { PageProps, RootSearchParams } from '../pages/types'
|
||||||
|
|
||||||
import { Meta, MetaProvider } from '@solidjs/meta'
|
import { Meta, MetaProvider } from '../context/meta'
|
||||||
import { Component, createEffect, createMemo } from 'solid-js'
|
import { Component, createEffect, createMemo } from 'solid-js'
|
||||||
import { Dynamic } from 'solid-js/web'
|
import { Dynamic } from 'solid-js/web'
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type { Author, Shout, Topic } from '../../graphql/schema/core.gen'
|
||||||
|
|
||||||
import { getPagePath } from '@nanostores/router'
|
import { getPagePath } from '@nanostores/router'
|
||||||
import { createPopper } from '@popperjs/core'
|
import { createPopper } from '@popperjs/core'
|
||||||
import { Link, Meta } from '@solidjs/meta'
|
import { Link, Meta } from '../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { install } from 'ga-gtag'
|
import { install } from 'ga-gtag'
|
||||||
import { For, Show, createEffect, createMemo, createSignal, on, onCleanup, onMount } from 'solid-js'
|
import { For, Show, createEffect, createMemo, createSignal, on, onCleanup, onMount } from 'solid-js'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { Author } from '../../../graphql/schema/core.gen'
|
import type { Author } from '../../../graphql/schema/core.gen'
|
||||||
|
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, Show, createMemo, createSignal } from 'solid-js'
|
import { For, Show, createMemo, createSignal } from 'solid-js'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { Topic } from '../../../graphql/schema/core.gen'
|
import type { Topic } from '../../../graphql/schema/core.gen'
|
||||||
|
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, Show, createEffect, createMemo, createSignal } from 'solid-js'
|
import { For, Show, createEffect, createMemo, createSignal } from 'solid-js'
|
||||||
import { useLocalize } from '../../../context/localize'
|
import { useLocalize } from '../../../context/localize'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { Author, Reaction, Shout, Topic } from '../../../graphql/schema/core.gen'
|
import type { Author, Reaction, Shout, Topic } from '../../../graphql/schema/core.gen'
|
||||||
|
|
||||||
import { getPagePath } from '@nanostores/router'
|
import { getPagePath } from '@nanostores/router'
|
||||||
import { Meta, Title } from '@solidjs/meta'
|
import { Meta, Title } from '../../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { getPagePath } from '@nanostores/router'
|
import { getPagePath } from '@nanostores/router'
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { LoadShoutsOptions, Shout, Topic } from '../../graphql/schema/core.gen'
|
import { LoadShoutsOptions, Shout, Topic } from '../../graphql/schema/core.gen'
|
||||||
|
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { JSX } from 'solid-js'
|
import type { JSX } from 'solid-js'
|
||||||
|
|
||||||
import { Link } from '@solidjs/meta'
|
import { Link } from '../../../context/meta'
|
||||||
import { splitProps } from 'solid-js'
|
import { splitProps } from 'solid-js'
|
||||||
|
|
||||||
import { getImageUrl } from '../../../utils/getImageUrl'
|
import { getImageUrl } from '../../../utils/getImageUrl'
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import type { JSX } from 'solid-js'
|
import type { JSX } from 'solid-js'
|
||||||
|
|
||||||
import { Title } from '@solidjs/meta'
|
import { Title } from '../../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { Show, createEffect, createSignal } from 'solid-js'
|
import { Show, createEffect, createSignal } from 'solid-js'
|
||||||
|
|
||||||
|
|
139
src/context/meta.tsx
Normal file
139
src/context/meta.tsx
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
import {
|
||||||
|
Component,
|
||||||
|
createContext,
|
||||||
|
createRenderEffect,
|
||||||
|
createSignal,
|
||||||
|
JSX,
|
||||||
|
onCleanup,
|
||||||
|
ParentComponent,
|
||||||
|
useContext,
|
||||||
|
} from 'solid-js'
|
||||||
|
import { isServer, spread } from 'solid-js/web'
|
||||||
|
|
||||||
|
export const MetaContext = createContext<MetaContextType>()
|
||||||
|
|
||||||
|
interface TagDescription {
|
||||||
|
tag: string
|
||||||
|
props: Record<string, string>
|
||||||
|
cleanup?: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MetaContextType {
|
||||||
|
addTag: (tag: TagDescription) => void
|
||||||
|
removeTag: (tag: TagDescription) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
function initClientProvider() {
|
||||||
|
const tags = new Map<string, TagDescription>()
|
||||||
|
|
||||||
|
function addTag(tag: TagDescription) {
|
||||||
|
const key = getTagKey(tag)
|
||||||
|
tags.set(key, tag)
|
||||||
|
|
||||||
|
const el = document.createElement(tag.tag)
|
||||||
|
spread(el, tag.props)
|
||||||
|
document.head.appendChild(el)
|
||||||
|
|
||||||
|
tag.cleanup = () => {
|
||||||
|
document.head.removeChild(el)
|
||||||
|
tags.delete(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeTag(tag: TagDescription) {
|
||||||
|
const key = getTagKey(tag)
|
||||||
|
const existingTag = tags.get(key)
|
||||||
|
if (existingTag) {
|
||||||
|
if (existingTag.cleanup) existingTag.cleanup()
|
||||||
|
tags.delete(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { addTag, removeTag }
|
||||||
|
}
|
||||||
|
|
||||||
|
function initServerProvider() {
|
||||||
|
const tags: TagDescription[] = []
|
||||||
|
|
||||||
|
function addTag(tagDesc: TagDescription) {
|
||||||
|
tags.push(tagDesc)
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeTag(tag: TagDescription) {
|
||||||
|
const index = tags.findIndex((t) => getTagKey(t) === getTagKey(tag))
|
||||||
|
if (index !== -1) {
|
||||||
|
tags.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { addTag, removeTag }
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MetaProvider: ParentComponent = (props) => {
|
||||||
|
const actions = isServer ? initServerProvider() : initClientProvider()
|
||||||
|
const [tags, setTags] = createSignal<TagDescription[]>([])
|
||||||
|
|
||||||
|
const addTag = (tag: TagDescription) => {
|
||||||
|
actions.addTag(tag)
|
||||||
|
setTags([...tags(), tag])
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeTag = (tag: TagDescription) => {
|
||||||
|
actions.removeTag(tag)
|
||||||
|
setTags(tags().filter((t) => getTagKey(t) !== getTagKey(tag)))
|
||||||
|
}
|
||||||
|
|
||||||
|
onCleanup(() => {
|
||||||
|
for (const tag of tags()) {
|
||||||
|
tag.cleanup?.()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return <MetaContext.Provider value={{ addTag, removeTag }}>{props.children}</MetaContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
const getTagKey = (tag: TagDescription) => {
|
||||||
|
const props = Object.entries(tag.props)
|
||||||
|
.filter(([k]) => k !== 'children')
|
||||||
|
.sort()
|
||||||
|
|
||||||
|
return `${tag.tag}${JSON.stringify(props)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useHead(tagDesc: TagDescription) {
|
||||||
|
const c = useContext(MetaContext)
|
||||||
|
if (!c) throw new Error('<MetaProvider /> should be in the tree')
|
||||||
|
|
||||||
|
createRenderEffect(() => {
|
||||||
|
c.addTag(tagDesc)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
c.removeTag(tagDesc)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const MetaTag = (tag: string, props: Record<string, string>) => {
|
||||||
|
useHead({ tag, props })
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Title: Component<JSX.HTMLAttributes<HTMLTitleElement>> = (props) =>
|
||||||
|
MetaTag('title', props as Record<string, string>)
|
||||||
|
|
||||||
|
export const Style: Component<JSX.StyleHTMLAttributes<HTMLStyleElement>> = (props) =>
|
||||||
|
MetaTag('style', props as Record<string, string>)
|
||||||
|
|
||||||
|
export const Meta: Component<JSX.MetaHTMLAttributes<HTMLMetaElement>> = (props) =>
|
||||||
|
MetaTag('meta', props as Record<string, string>)
|
||||||
|
|
||||||
|
export const Link: Component<JSX.LinkHTMLAttributes<HTMLLinkElement>> = (props) =>
|
||||||
|
MetaTag('link', props as Record<string, string>)
|
||||||
|
|
||||||
|
export const Base: Component<JSX.BaseHTMLAttributes<HTMLBaseElement>> = (props) =>
|
||||||
|
MetaTag('base', props as Record<string, string>)
|
||||||
|
|
||||||
|
export const Stylesheet: Component<Omit<JSX.LinkHTMLAttributes<HTMLLinkElement>, 'rel'>> = (props) => (
|
||||||
|
<Link rel="stylesheet" {...props} />
|
||||||
|
)
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { Donate } from '../../components/Discours/Donate'
|
import { Donate } from '../../components/Discours/Donate'
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { Feedback } from '../../components/Discours/Feedback'
|
import { Feedback } from '../../components/Discours/Feedback'
|
||||||
import { Modal } from '../../components/Nav/Modal'
|
import { Modal } from '../../components/Nav/Modal'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../../context/meta'
|
||||||
|
|
||||||
import { StaticPage } from '../../components/Views/StaticPage'
|
import { StaticPage } from '../../components/Views/StaticPage'
|
||||||
import { useLocalize } from '../../context/localize'
|
import { useLocalize } from '../../context/localize'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { redirectPage } from '@nanostores/router'
|
import { redirectPage } from '@nanostores/router'
|
||||||
import { Meta } from '@solidjs/meta'
|
import { Meta } from '../context/meta'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
|
|
||||||
import { AuthGuard } from '../components/AuthGuard'
|
import { AuthGuard } from '../components/AuthGuard'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user