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/storage": "^3.5.0",
|
||||
"@solid-primitives/upload": "0.0.115",
|
||||
"@solidjs/meta": "0.29.3",
|
||||
"@thisbeyond/solid-select": "0.14.0",
|
||||
"@tiptap/core": "2.2.3",
|
||||
"@tiptap/extension-blockquote": "2.2.3",
|
||||
|
@ -4106,15 +4105,6 @@
|
|||
"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": {
|
||||
"version": "0.14.0",
|
||||
"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/storage": "^3.5.0",
|
||||
"@solid-primitives/upload": "0.0.115",
|
||||
"@solidjs/meta": "0.29.3",
|
||||
"@thisbeyond/solid-select": "0.14.0",
|
||||
"@tiptap/core": "2.2.3",
|
||||
"@tiptap/extension-blockquote": "2.2.3",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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 { 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 { createPopper } from '@popperjs/core'
|
||||
import { Link, Meta } from '@solidjs/meta'
|
||||
import { Link, Meta } from '../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
import { install } from 'ga-gtag'
|
||||
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 { Meta } from '@solidjs/meta'
|
||||
import { Meta } from '../../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
import { For, Show, createMemo, createSignal } from 'solid-js'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { Topic } from '../../../graphql/schema/core.gen'
|
||||
|
||||
import { Meta } from '@solidjs/meta'
|
||||
import { Meta } from '../../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
import { For, Show, createEffect, createMemo, createSignal } from 'solid-js'
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import type { Author, Reaction, Shout, Topic } from '../../../graphql/schema/core.gen'
|
||||
|
||||
import { getPagePath } from '@nanostores/router'
|
||||
import { Meta, Title } from '@solidjs/meta'
|
||||
import { Meta, Title } from '../../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
import { For, Match, Show, Switch, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { getPagePath } from '@nanostores/router'
|
||||
import { Meta } from '@solidjs/meta'
|
||||
import { Meta } from '../../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
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 { Meta } from '@solidjs/meta'
|
||||
import { Meta } from '../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
import { For, Show, createEffect, createMemo, createSignal, on, onMount } from 'solid-js'
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { JSX } from 'solid-js'
|
||||
|
||||
import { Link } from '@solidjs/meta'
|
||||
import { Link } from '../../../context/meta'
|
||||
import { splitProps } from 'solid-js'
|
||||
|
||||
import { getImageUrl } from '../../../utils/getImageUrl'
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import type { JSX } from 'solid-js'
|
||||
|
||||
import { Title } from '@solidjs/meta'
|
||||
import { Title } from '../../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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 { useLocalize } from '../../context/localize'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { redirectPage } from '@nanostores/router'
|
||||
import { Meta } from '@solidjs/meta'
|
||||
import { Meta } from '../context/meta'
|
||||
import { clsx } from 'clsx'
|
||||
|
||||
import { AuthGuard } from '../components/AuthGuard'
|
||||
|
|
Loading…
Reference in New Issue
Block a user