Skip to content

Commit

Permalink
feat: support global components
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Jun 3, 2021
1 parent 965c7c2 commit de2a2bf
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 41 deletions.
8 changes: 8 additions & 0 deletions cypress/fixtures/basic/global.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<template>
<div
v-if="$slidev.nav.currentPage % 2 === 1"
class="absolute bottom-0 right-0 p-10"
>
Global Footer (appear only on odd page)
</div>
</template>
6 changes: 6 additions & 0 deletions cypress/integration/examples/basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ context('Basic', () => {
cy.url()
.should('eq', 'http://localhost:3030/1')

cy.contains('Global Footer')
.should('exist')

cy.get('#page-root > #slide-container > #slide-content')

cy.get('body')
.type('{RightArrow}')
.url()
.should('eq', 'http://localhost:3030/2')

cy.contains('Global Footer')
.should('not.exist')

cy.get('#page-root > #slide-container > #slide-content > .slidev-page-2 > div > p')
.should('have.css', 'border-color', 'rgb(0, 128, 0)')
.should('not.have.css', 'color', 'rgb(128, 0, 0)')
Expand Down
13 changes: 13 additions & 0 deletions cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"noEmit": true,
// be explicit about types included
// to avoid clashing with Jest types
"types": ["cypress"]
},
"include": [
"../node_modules/cypress",
"./**/*.ts"
]
}
2 changes: 1 addition & 1 deletion packages/client/internals/Presenter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import SlidesOverview from './SlidesOverview.vue'
import NoteEditor from './NoteEditor.vue'
import Goto from './Goto.vue'
import SlidesShow from './SlidesShow.vue'
import SlideWrapper from './SlideWrapper.vue'
import SlideWrapper from './SlideWrapper'
registerShortcuts()
Expand Down
37 changes: 37 additions & 0 deletions packages/client/internals/SlideWrapper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useVModel } from '@vueuse/core'
import { provide, defineComponent, h } from 'vue'
import { injectionClicks, injectionClicksDisabled, injectionClicksElements } from '../modules/directives'

export default defineComponent({
props: {
clicks: {
default: 0,
},
clicksElements: {
default: () => [] as Element[],
},
clicksDisabled: {
default: false,
},
is: {
type: Object,
default: undefined,
},
},
setup(props, { emit }) {
const clicks = useVModel(props, 'clicks', emit)
const clicksElements = useVModel(props, 'clicksElements', emit)
const clicksDisabled = useVModel(props, 'clicksDisabled', emit)

clicksElements.value.length = 0

provide(injectionClicks, clicks)
provide(injectionClicksDisabled, clicksDisabled)
provide(injectionClicksElements, clicksElements)
},
render() {
if (this.$props.is)
return h(this.$props.is)
return this.$slots?.default?.()
},
})
36 changes: 0 additions & 36 deletions packages/client/internals/SlideWrapper.vue

This file was deleted.

2 changes: 1 addition & 1 deletion packages/client/internals/SlidesOverview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { breakpoints, windowSize } from '../state'
import { go as goSlide, rawRoutes } from '../logic/nav'
import { getSlideClass } from '../utils'
import SlideContainer from './SlideContainer.vue'
import SlideWrapper from './SlideWrapper.vue'
import SlideWrapper from './SlideWrapper'
const emit = defineEmit()
const props = defineProps<{ modelValue: boolean }>()
Expand Down
21 changes: 20 additions & 1 deletion packages/client/internals/SlidesShow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
import { watch } from 'vue'
import { currentRoute, clicks, rawRoutes, nextRoute } from '../logic/nav'
import { getSlideClass } from '../utils'
import SlideWrapper from './SlideWrapper.vue'
import SlideWrapper from './SlideWrapper'
// @ts-ignore
import GlobalTop from '/@slidev/global-components/top'
// @ts-ignore
import GlobalBottom from '/@slidev/global-components/bottom'
// preload next route
watch(currentRoute, () => {
Expand All @@ -14,6 +18,14 @@ watch(currentRoute, () => {
</script>

<template>
<!-- Global Bottom -->
<SlideWrapper>
<div class="slidev-global-bottom -z-1 absolute top-0 left-0 bottom-0 right-0 w-full h-full">
<GlobalBottom />
</div>
</SlideWrapper>

<!-- Slides -->
<template v-for="route of rawRoutes" :key="route.path">
<SlideWrapper
:is="route?.component"
Expand All @@ -25,4 +37,11 @@ watch(currentRoute, () => {
:class="getSlideClass(route)"
/>
</template>
<!-- Global Top -->
<SlideWrapper>
<div class="slidev-global-top absolute top-0 left-0 bottom-0 right-0 w-full h-full">
<GlobalTop />
</div>
</SlideWrapper>
</template>
49 changes: 48 additions & 1 deletion packages/slidev/node/plugins/loaders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { basename, join } from 'path'
import { ModuleNode, Update, ViteDevServer, Plugin } from 'vite'
import { isString, notNullish, objectMap, range, slash } from '@antfu/utils'
import fg from 'fast-glob'
import fs, { existsSync } from 'fs-extra'
import Markdown from 'markdown-it'
import { RouteMeta } from 'vue-router'
// @ts-expect-error
import mila from 'markdown-it-link-attributes'
import { SlideInfo, SlideInfoExtended, SlidevMarkdown } from '@slidev/types'
import * as parser from '@slidev/parser/fs'
import equal from 'fast-deep-equal'
import { existsSync } from 'fs-extra'

import type { Connect } from 'vite'
import { ResolvedSlidevOptions, SlidevPluginOptions } from '../options'
import { resolveImportPath, stringifyMarkdownTokens, toAtFS } from '../utils'
Expand Down Expand Up @@ -225,6 +226,14 @@ export function createSlidesLoader(
if (id === '/@slidev/configs')
return generateConfigs()

// global component
if (id === '/@slidev/global-components/top')
return generateGlobalComponents('top')

// global component
if (id === '/@slidev/global-components/bottom')
return generateGlobalComponents('bottom')

// pages
if (id.startsWith(slidePrefix)) {
const remaning = id.slice(slidePrefix.length)
Expand Down Expand Up @@ -423,4 +432,42 @@ export function createSlidesLoader(

return `export default ${JSON.stringify(config)}`
}

async function generateGlobalComponents(layer: 'top' | 'bottom') {
const components = [
userRoot,
...themeRoots,
clientRoot,
]
.flatMap((root) => {
if (layer === 'top') {
return [
join(root, 'global.vue'),
join(root, 'Global.vue'),
join(root, 'global-top.vue'),
join(root, 'GlobalTop.vue'),
]
}
else {
return [
join(root, 'global-bottom.vue'),
join(root, 'GlobalBottom.vue'),
]
}
})
.filter(i => fs.existsSync(i))

const imports = components.map((i, idx) => `import __n${idx} from '${toAtFS(i)}'`).join('\n')
const render = components.map((i, idx) => `h(__n${idx})`).join(',')

return `
${imports}
import { h } from 'vue'
export default {
render() {
return [${render}]
}
}
`
}
}
1 change: 0 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
"vite/client",
"node",
"jest",
"cypress"
],
"paths": {
"@slidev/client/*": ["./packages/client/*"],
Expand Down

0 comments on commit de2a2bf

Please sign in to comment.