Skip to content

Commit

Permalink
feat: support definePage macro
Browse files Browse the repository at this point in the history
  • Loading branch information
edwinhuish committed Mar 21, 2024
1 parent fa093d0 commit 218af7d
Show file tree
Hide file tree
Showing 16 changed files with 435 additions and 190 deletions.
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,31 @@ export default defineUniPages({

现在所有的 page 都会被自动发现!

### SFC 自定义块用于路由数据
### 页面调用方式(1): `definePage` 宏定义路由数据
```html
<!-- index.vue -->
<script setup>
// 参数为对象
definePage({
type: 'home',
style: { navigationBarTitleText: 'index page' }
})
</script>

<!-- other.vue -->
<script setup>
// 参数为函数
// 注意:暂未支持外部 import
definePage(() => {
const hello = ['hello', 'world']
return {
style: { navigationBarTitleText: hello.join(' ') }
}
})
</script>
```

### 页面调用方式(2):SFC 自定义块用于路由数据

通过添加一个 `<route>` 块到 SFC 中来添加路由元数据。这将会在路由生成后直接添加到路由中,并且会覆盖。

Expand Down
26 changes: 25 additions & 1 deletion packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,31 @@ export default defineUniPages({

Now all pages will be found automatically!

### SFC custom block for Route Data
### Page usage (1): `definePage` macro define page options
```html
<!-- index.vue -->
<script setup>
// object argument
definePage({
type: 'home',
style: { navigationBarTitleText: 'index page' }
})
</script>

<!-- other.vue -->
<script setup>
// function argument
// Note: import is not supported yet
definePage(() => {
const hello = ['hello', 'world']
return {
style: { navigationBarTitleText: hello.join(' ') }
}
})
</script>
```

### Page usage (2): SFC custom block for Route Data

Add route meta to the route by adding a `<route>` block to the SFC. This will be
directly added to the route after it is generated, and will override it.
Expand Down
4 changes: 4 additions & 0 deletions packages/core/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ declare module 'virtual:uni-pages' {
export const pages: PageMetaDatum[]
export const subPackages: SubPackage[]
}

declare module globalThis {
export const definePage: import('./src/types').DefinePage
}
5 changes: 5 additions & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@
"stub": "unbuild --stub"
},
"dependencies": {
"@babel/generator": "^7.24.1",
"@babel/types": "^7.24.0",
"@uni-helper/uni-env": "^0.1.1",
"@vue/compiler-sfc": "^3.4.21",
"ast-kit": "^0.12.1",
"chokidar": "^3.6.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
Expand All @@ -53,6 +56,8 @@
},
"devDependencies": {
"@antfu/utils": "^0.7.7",
"@babel/parser": "^7.24.1",
"@types/babel__generator": "^7.6.8",
"@types/debug": "^4.1.12",
"@types/node": "^20.11.24"
}
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ export const RESOLVED_MODULE_ID_VIRTUAL = `\0${MODULE_ID_VIRTUAL}`
export const OUTPUT_NAME = 'pages.json'

export const FILE_EXTENSIONS = ['vue', 'nvue', 'uvue']

export const DEFINE_PAGE = 'definePage'
71 changes: 36 additions & 35 deletions packages/core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,32 @@ import path from 'node:path'
import process from 'node:process'
import type { FSWatcher } from 'chokidar'
import type { Logger, ViteDevServer } from 'vite'
import { normalizePath } from 'vite'
import { loadConfig } from 'unconfig'
import { slash } from '@antfu/utils'
import dbg from 'debug'
import { platform } from '@uni-helper/uni-env'
import type { PagesConfig } from './config/types'
import type { PageMetaDatum, PagePath, ResolvedOptions, SubPageMetaDatum, UserOptions } from './types'
import { writeDeclaration } from './declaration'

import {
debug,
invalidatePagesModule,
isTargetFile,
mergePageMetaDataArray,
useCachedPages,
} from './utils'
import { resolveOptions } from './options'
import { checkPagesJsonFile, getPageFiles, writeFileSync } from './files'
import { getRouteBlock, getRouteSfcBlock } from './customBlock'
import { OUTPUT_NAME } from './constant'
import { Page } from './page'

let lsatPagesJson = ''

const { setCache, hasChanged } = useCachedPages()
export class PageContext {
private _server: ViteDevServer | undefined

pagesGlobConfig: PagesConfig | undefined
pagesConfigSourcePaths: string[] = []

pagesPath: PagePath[] = []
subPagesPath: Record<string, PagePath[]> = {}
pageMetaData: PageMetaDatum[] = []
subPageMetaData: SubPageMetaDatum[] = []

Expand All @@ -46,6 +40,9 @@ export class PageContext {

withUniPlatform = false

pages: Page[] = []
subPages: Record<string, Page[]> = {}

constructor(userOptions: UserOptions, viteRoot: string = process.cwd()) {
this.rawOptions = userOptions
this.root = slash(viteRoot)
Expand Down Expand Up @@ -79,18 +76,24 @@ export class PageContext {
return { dir, files: getPagePaths(dir, this.options) }
})

this.pagesPath = pageDirFiles.map(page => page.files).flat()
debug.pages(this.pagesPath)
const paths = pageDirFiles.map(page => page.files).flat()
debug.pages(paths)

this.pages = paths.map(path => new Page(this, path))
}

async scanSubPages() {
const subPagesPath: Record<string, PagePath[]> = {}
const paths: Record<string, PagePath[]> = {}
const subPages: Record<string, Page[]> = {}
for (const dir of this.options.subPackages) {
const pagePaths = getPagePaths(dir, this.options)
subPagesPath[dir] = pagePaths
paths[dir] = pagePaths

subPages[dir] = pagePaths.map(path => new Page(this, path))
}
this.subPagesPath = subPagesPath
debug.subPages(this.subPagesPath)
debug.subPages(JSON.stringify(paths, null, 2))

this.subPages = subPages
}

setupViteServer(server: ViteDevServer) {
Expand Down Expand Up @@ -167,32 +170,15 @@ export class PageContext {
})
}

async parsePage(page: PagePath): Promise<PageMetaDatum> {
const { relativePath, absolutePath } = page
const routeSfcBlock = await getRouteSfcBlock(absolutePath)
const routeBlock = await getRouteBlock(absolutePath, routeSfcBlock, this.options)
setCache(absolutePath, routeSfcBlock)
const relativePathWithFileName = relativePath.replace(path.extname(relativePath), '')
const pageMetaDatum: PageMetaDatum = {
path: normalizePath(relativePathWithFileName),
type: routeBlock?.attr.type ?? 'page',
}

if (routeBlock)
Object.assign(pageMetaDatum, routeBlock.content)

return pageMetaDatum
}

/**
* parse pages rules && set page type
* @param pages page path array
* @param type page type
* @param overrides custom page config
* @returns pages rules
*/
async parsePages(pages: PagePath[], type: 'main' | 'sub', overrides?: PageMetaDatum[]) {
const generatedPageMetaData = await Promise.all(pages.map(async page => await this.parsePage(page)))
async parsePages(pages: Page[], type: 'main' | 'sub', overrides?: PageMetaDatum[]) {
const generatedPageMetaData = await Promise.all(pages.map(async page => await page.getOptions()))
const customPageMetaData = overrides || []

const result = customPageMetaData.length
Expand Down Expand Up @@ -231,7 +217,7 @@ export class PageContext {
}

async mergePageMetaData() {
const pageMetaData = await this.parsePages(this.pagesPath, 'main', this.pagesGlobConfig?.pages)
const pageMetaData = await this.parsePages(this.pages, 'main', this.pagesGlobConfig?.pages)
this.pageMetaData = pageMetaData
debug.pages(this.pageMetaData)
}
Expand All @@ -240,7 +226,7 @@ export class PageContext {
const subPageMaps: Record<string, PageMetaDatum[]> = {}
const subPackages = this.pagesGlobConfig?.subPackages || []

for (const [dir, pages] of Object.entries(this.subPagesPath)) {
for (const [dir, pages] of Object.entries(this.subPages)) {
const root = path.basename(dir)

const globPackage = subPackages?.find(v => v.root === root)
Expand All @@ -260,9 +246,24 @@ export class PageContext {
debug.subPages(this.subPageMetaData)
}

private getPageByPath(absolutePath: string) {
const page = this.pages.find(page => page.file.absolutePath === absolutePath)
if (page)
return page

for (const pages of Object.values(this.subPages)) {
const subPage = pages.find(page => page.file.absolutePath === absolutePath)
if (subPage)
return subPage
}

return undefined
}

async updatePagesJSON(filepath?: string) {
if (filepath) {
if (!await hasChanged(filepath)) {
const page = this.getPageByPath(filepath)
if (page && !await page.hasChanged()) {
debug.cache(`The route block on page ${filepath} did not send any changes, skipping`)
return false
}
Expand Down
88 changes: 0 additions & 88 deletions packages/core/src/customBlock.ts

This file was deleted.

Loading

0 comments on commit 218af7d

Please # to comment.