Skip to content

Commit

Permalink
refactor!: core providers export
Browse files Browse the repository at this point in the history
Breaking change: vanilla vite / vue setups will require modifying their configuration
  • Loading branch information
harlan-zw committed May 23, 2022
1 parent 71cc282 commit 08fdbb6
Show file tree
Hide file tree
Showing 15 changed files with 132 additions and 195 deletions.
35 changes: 22 additions & 13 deletions packages/.test/mount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ import { createApp, defineComponent, h, provide, ref, reactive } from 'vue'
import {createRouter, createWebHashHistory, RouteLocationNormalizedLoaded, useRoute} from 'vue-router'
import {createSchemaOrg} from "../schema-org/createSchemaOrg";
import { createHead } from '@vueuse/head'
import {CreateSchemaOrgInput, SchemaOrgOptions} from "@vueuse/schema-org";
import {CreateSchemaOrgInput, SchemaOrgOptions, useVueUseHead} from "@vueuse/schema-org";
import {DeepPartial} from "utility-types";

type InstanceType<V> = V extends { new (...arg: any[]): infer X } ? X : never
type VM<V> = InstanceType<V> & { unmount(): void }

let useRouteFacade = useRoute
let useCreateSchemaOrgArguments: CreateSchemaOrgInput = {
let inputArgs: DeepPartial<CreateSchemaOrgInput> = {
canonicalHost: 'https://example.com/',
useRoute: useRouteFacade,
defaultLanguage: 'en-AU'
defaultLanguage: 'en-AU',
provider: {
useRoute: useRouteFacade,
}
}

export function mount<V>(Comp: V) {
Expand All @@ -35,10 +38,13 @@ export function mount<V>(Comp: V) {
const head = createHead()
app.use(head)

const schemaOrg = createSchemaOrg({
...useCreateSchemaOrgArguments,
head
})
if (!inputArgs.provider) {
inputArgs.provider = {}
}
if (!inputArgs.provider.setupDOM) {
inputArgs.provider.setupDOM = useVueUseHead(head)
}
const schemaOrg = createSchemaOrg(inputArgs as CreateSchemaOrgInput)

app.use(schemaOrg)

Expand All @@ -52,16 +58,19 @@ export function mount<V>(Comp: V) {
}

export const mockRoute = (route: Partial<RouteLocationNormalizedLoaded>, fn: () => void) => {
const currentRoute = useCreateSchemaOrgArguments.useRoute
if (!inputArgs.provider) {
return
}
const currentRoute = inputArgs.provider?.useRoute
useRouteFacade = () => reactive(route) as RouteLocationNormalizedLoaded
useCreateSchemaOrgArguments.useRoute = useRouteFacade
inputArgs.provider.useRoute = useRouteFacade
fn()
useCreateSchemaOrgArguments.useRoute = currentRoute
inputArgs.provider.useRoute = currentRoute
}

export const mockCreateSchemaOptions = (options: Partial<SchemaOrgOptions>) => {
useCreateSchemaOrgArguments = {
...useCreateSchemaOrgArguments,
inputArgs = {
...inputArgs,
...options
}
}
Expand Down
82 changes: 0 additions & 82 deletions packages/.test/tests/breadcrumbs.test.ts

This file was deleted.

9 changes: 4 additions & 5 deletions packages/.test/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ export const mockedUseRoute = () => {
}
export const createMockClient = () => createSchemaOrg({
canonicalHost: 'example.com',
head: {
updateDOM() {},
addHeadObjs() {},
},
useRoute: mockedUseRoute,
provider: {
setupDOM() {},
useRoute: mockedUseRoute,
}
})
10 changes: 6 additions & 4 deletions packages/nuxt/src/runtime/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { createSchemaOrg } from '@vueuse/schema-org'
import { createSchemaOrg, useVueUseHead } from '@vueuse/schema-org'
import { defineNuxtPlugin } from '#app'
import { useRoute, watchEffect } from '#imports'
import meta from '#build/schemaOrg.config.mjs'

export default defineNuxtPlugin((nuxtApp) => {
const head = nuxtApp.vueApp._context.provides.usehead
const schemaOrg = createSchemaOrg({
useRoute,
head,
provider: 'nuxt',
provider: {
useRoute,
setupDOM: useVueUseHead(head),
provider: 'nuxt',
},
...meta.config,
})
nuxtApp.vueApp.use(schemaOrg)
Expand Down
44 changes: 6 additions & 38 deletions packages/schema-org/createSchemaOrg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ export const createSchemaOrg = (options: CreateSchemaOrgInput) => {
}
// if consola is missing it's not a problem
catch (e) {}
//
if (!options.useRoute)

if (!options.provider?.useRoute)
warn('Missing useRoute implementation. Provide a `useRoute` handler, usually from `vue-router`.')

if (!options.canonicalHost) {
Expand All @@ -53,8 +53,6 @@ export const createSchemaOrg = (options: CreateSchemaOrgInput) => {
options.canonicalHost = withTrailingSlash(withProtocol(options.canonicalHost, 'https://'))
}

let _domSetup = false

const client: SchemaOrgClient = {
install(app) {
app.config.globalProperties.$schemaOrg = client
Expand All @@ -67,7 +65,7 @@ export const createSchemaOrg = (options: CreateSchemaOrgInput) => {

setupRouteContext(vm: ComponentInternalInstance) {
const host = options.canonicalHost || ''
const route = options.useRoute()
const route = options.provider?.useRoute()

const ctx = reactive<SchemaOrgContext>({
meta: {},
Expand All @@ -83,7 +81,7 @@ export const createSchemaOrg = (options: CreateSchemaOrgInput) => {
watchEffect(() => {
ctx.canonicalUrl = joinURL(host, route.path)

if (options.provider === 'vitepress') {
if (options.provider.name === 'vitepress') {
const vitepressData = (route as typeof route & { data: any }).data
ctx.meta = {
...vitepressData,
Expand Down Expand Up @@ -188,38 +186,8 @@ export const createSchemaOrg = (options: CreateSchemaOrgInput) => {
},

setupDOM() {
let head: HeadClient | null = null
try {
// head may not be available in SSR (vitepress)
head = options.head || injectHead()
}
catch (e) {
debug('DOM setup failed, couldn\'t fetch injectHead')
}
if (!head)
return

// we only need to init the DOM once since we have a reactive head object and a watcher to update the DOM
if (_domSetup)
return

head.addHeadObjs(computed(() => {
return {
// Can be static or computed
script: [
{
type: 'application/ld+json',
key: 'root-schema-org-graph',
children: schemaRef.value,
},
],
}
}))
watchEffect(() => {
if (head && typeof window !== 'undefined')
head.updateDOM()
})
_domSetup = true
if (options.provider?.setupDOM)
options.provider.setupDOM(client)
},
}
return client
Expand Down
1 change: 1 addition & 0 deletions packages/schema-org/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * from './types'
export * from './utils'
export * from './meta'
export * from './components'
export * from './providers'
18 changes: 10 additions & 8 deletions packages/schema-org/nodes/Article/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,14 +339,16 @@ describe('defineArticle', () => {
mockCreateSchemaOptions({
canonicalHost: 'https://kootingalpecancompany.com/',
defaultLanguage: 'en-US',
// @ts-expect-error mock untyped
useRoute: () => reactive({
path: '/pecan-tree-kootingal',
meta: {
title: 'The pecan tree &#8220;Carya illinoinensis&#8221;',
image: 'https://res.cloudinary.com/kootingalpecancompany/images/w_1920,h_2560/f_auto,q_auto/v1648723707/IMG_0446/IMG_0446.jpg?_i=AA',
},
}),
provider: {
// @ts-expect-error mock untyped
useRoute: () => reactive({
path: '/pecan-tree-kootingal',
meta: {
title: 'The pecan tree &#8220;Carya illinoinensis&#8221;',
image: 'https://res.cloudinary.com/kootingalpecancompany/images/w_1920,h_2560/f_auto,q_auto/v1648723707/IMG_0446/IMG_0446.jpg?_i=AA',
},
}),
},
})
useSetup(() => {
useSchemaOrg([
Expand Down
12 changes: 1 addition & 11 deletions packages/schema-org/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,8 @@
"vue": ">=3",
"vue-router": "^4"
},
"peerDependenciesMeta": {
"vue": {
"optional": true
},
"vue-router": {
"optional": true
}
},
"dependencies": {
"vue-demi": "*"
},
"devDependencies": {
"@vueuse/head": "^0.7.6",
"consola": "^2.15.3",
"defu": "^6.0.0",
"ohash": "^0.1.0",
Expand Down
1 change: 1 addition & 0 deletions packages/schema-org/providers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useVueUseHead'
42 changes: 42 additions & 0 deletions packages/schema-org/providers/useVueUseHead.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { computed, watchEffect } from 'vue'
import type { HeadClient } from '@vueuse/head'
import { injectHead } from '@vueuse/head'

export function useVueUseHead(headClient?: HeadClient) {
let _domSetup = false

return ({ schemaRef, debug }: any) => {
let head: HeadClient | null = null
try {
// head may not be available in SSR (vitepress)
head = headClient || injectHead()
}
catch (e) {
debug('DOM setup failed, couldn\'t fetch injectHead')
}
if (!head)
return

// we only need to init the DOM once since we have a reactive head object and a watcher to update the DOM
if (_domSetup)
return

head.addHeadObjs(computed(() => {
return {
// Can be static or computed
script: [
{
type: 'application/ld+json',
key: 'root-schema-org-graph',
children: schemaRef.value,
},
],
}
}))
watchEffect(() => {
if (head && typeof window !== 'undefined')
head.updateDOM()
})
_domSetup = true
}
}
32 changes: 17 additions & 15 deletions packages/schema-org/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,21 +119,23 @@ export interface SchemaOrgContext {
options: CreateSchemaOrgInput
}

export type CreateSchemaOrgInput = SchemaOrgOptions & FrameworkAugmentationOptions

export interface FrameworkAugmentationOptions {
/**
* The useHead client used to insert the meta tag.
*/
head?: HeadClient | any
/**
* A function used to resolve a reactive route.
*/
useRoute: () => RouteLocationNormalizedLoaded
/**
* An ID for the integration, used for handling edge cases in specific frameworks.
*/
provider?: 'vitepress' | 'nuxt' | 'vitesse' | string
export type CreateSchemaOrgInput = SchemaOrgOptions & ProviderOption

export interface ProviderOption {
provider: {
/**
* Client used to write schema to the document.
*/
setupDOM: (client: SchemaOrgClient) => void
/**
* A function used to resolve a reactive route.
*/
useRoute: () => RouteLocationNormalizedLoaded
/**
* An ID for the integration, used for handling edge cases in specific frameworks.
*/
name?: 'vitepress' | 'nuxt' | 'vitesse' | string
}
}

export interface SchemaOrgOptions {
Expand Down
Loading

0 comments on commit 08fdbb6

Please sign in to comment.