Skip to content

Commit

Permalink
feat: directives and function component support
Browse files Browse the repository at this point in the history
  • Loading branch information
zhangmo8 authored and jiahengz committed Apr 4, 2023
1 parent b3028ed commit a53e534
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 57 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,25 @@ Varlet Module for Nuxt3

## Quick Setup

1. Add `varlet-nuxt` dependency to your project
1. Add `@varlet/nuxt` dependency to your project

```bash
# Using pnpm
pnpm add -D varlet-nuxt
pnpm add -D @varlet/nuxt

# Using yarn
yarn add --dev varlet-nuxt
yarn add --dev @varlet/nuxt

# Using npm
npm install --save-dev varlet-nuxt
npm install --save-dev @varlet/nuxt
```

2. Add `varlet-nuxt` to the `modules` section of `nuxt.config.ts`
2. Add `@varlet/nuxt` to the `modules` section of `nuxt.config.ts`

```js
export default defineNuxtConfig({
modules: [
'varlet-nuxt'
'@varlet/nuxt'
],
varlet: {
...
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "varlet-nuxt",
"name": "@varlet/nuxt",
"version": "1.0.0",
"description": "varlet module for nuxt",
"license": "MIT",
Expand Down
54 changes: 32 additions & 22 deletions playground/app.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,41 @@
<script setup lang="ts">
const show = ref(false)
// const showSnackBar = () => {
// Snackbar({
// content: '这是一个消息条!!',
// duration: 1000
// })
// }
</script>

<template>
<div>
<var-button>qfqw</var-button>
<var-skeleton :loading="true">
<div v-ripple class="ripple-example-block">点击</div>
<!-- <var-skeleton :loading="show">
加载的数据
</var-skeleton>
<var-space>
<var-button>Button1</var-button>
<var-button>Button2</var-button>
</var-skeleton> -->

<!-- <var-button @click="showSnackBar">
Button2
</var-button> -->
<!-- <var-space>
<var-button>Button3</var-button>
</var-space>
<var-progress :value="20" :track="false" />
<var-card
title="本草纲目"
description="如果华佗再世,崇洋都被医治,外邦来学汉字,激发我民族意识。马钱子、决明子、苍耳子,还有莲子;黄药子、苦豆子、川楝子,我要面子。用我的方式,改写一部历史。没什么别的事,跟着我念几个字。山药当归枸杞 GO,山药 当归 枸杞 GO,看我抓一把中药,服下一帖骄傲~"
/>
<var-result type="success" title="Success" description="Hi, I'm a result description.">
<template #footer>
<var-button type="success">
OK
</var-button>
</template>
</var-result>
</div>
</var-space> -->
<!-- <var-progress :value="20" :track="false" />
<var-card title="本草纲目"
description="如果华佗再世,崇洋都被医治,外邦来学汉字,激发我民族意识。马钱子、决明子、苍耳子,还有莲子;黄药子、苦豆子、川楝子,我要面子。用我的方式,改写一部历史。没什么别的事,跟着我念几个字。山药当归枸杞 GO,山药 当归 枸杞 GO,看我抓一把中药,服下一帖骄傲~" /> -->
</template>

<style>
</style>
.ripple-example-block {
display: flex;
justify-content: center;
align-items: center;
height: 100px;
user-select: none;
cursor: pointer;
color: #888;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
transition: background-color 0.25s;
}
</style>
24 changes: 21 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import * as varletComponents from '@varlet/ui'

import type { ModuleOptions } from './types'
import type { ModuleOptions, PresetDirectives, PresetImport } from './types'

export const moduleName = 'varlet'
export const moduleName = '@varlet/ui'

export const components = Object.keys(varletComponents).filter(key =>
/^[A-Z][A-Za-z]*[^_][A-Za-z]*$/.test(key)
)

export const functionComponents: string[] = [
'Snackbar',
'ActionSheet',
'Dialog',
'LoadingBar'
]

const allDirectives: PresetDirectives = {
Ripple: ['ripple', 'VRipple'],
Lazy: ['lazy', 'VLazy'],
Hover: ['hover', 'VHover']
}

const allComponents: PresetImport[] = [
...functionComponents
]

const defaultInclude: RegExp[] = [
/\.vue$/,
/\.vue\?vue/,
Expand All @@ -26,5 +43,6 @@ export const defaults: ModuleOptions = {
components,
include: defaultInclude,
exclude: defaultExclude,
imports: []
imports: allComponents,
directives: allDirectives
}
14 changes: 9 additions & 5 deletions src/core/components.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { addComponent } from '@nuxt/kit'
import { kebabCase } from '@varlet/shared'

import { moduleName } from '../config'
import { moduleName, functionComponents } from '../config'
import { ModuleOptions } from '../types'

export function resolveComponents (config: ModuleOptions) {
export function resolveComponents(config: ModuleOptions) {
const { components } = config

components.forEach((item) => {
const [name, alias, from] = Array.isArray(item) ? item : [item]

const filePath =
!from || from === moduleName
? `@${moduleName}/ui/es/${kebabCase(name)}/${name}`
? `${moduleName}/es/${kebabCase(name)}/index`
: from

addComponent({
Expand All @@ -22,11 +22,15 @@ export function resolveComponents (config: ModuleOptions) {
})
}

export function resolveStyles (config: ModuleOptions, name: string) {
export function resolveStyles(config: ModuleOptions, name: string) {
const { components } = config

if (functionComponents.includes(name)) {
return `${moduleName}/es/${kebabCase(name)}/style`
}

if (/^Var[A-Z]/.test(name) && components.includes(name.slice(3))) {
return `@${moduleName.toLocaleLowerCase()}/ui/es/${kebabCase(name.slice(3))}/style`
return `${moduleName}/es/${kebabCase(name.slice(3))}/style`
}

return undefined
Expand Down
19 changes: 19 additions & 0 deletions src/core/directives.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { kebabCase } from '@varlet/shared'
import { moduleName } from '../config'
import type { ModuleOptions } from '../types'

export function resolveDirectives(
config: ModuleOptions,
name: string
): undefined | [name: string, styles?: string] {
const { directives } = config

if (directives[name]) {
const [directive, styleName] = Array.isArray(directives[name]) ? directives[name] : [directives[name]] as any
if (styleName) {
return [directive, `${moduleName}/es/${kebabCase(name)}/style`]
}

return [directive, styleName]
}
}
1 change: 1 addition & 0 deletions src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './components'
export * from './options'
export * from './transformPlugin'
export * from './imports'
export * from './directives'
2 changes: 1 addition & 1 deletion src/core/options.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useNuxt } from '@nuxt/kit'
import { moduleName } from '../config'

export function resolveOptions () {
export function resolveOptions() {
const nuxt = useNuxt()

nuxt.options.build.transpile.push(moduleName)
Expand Down
50 changes: 35 additions & 15 deletions src/core/transformPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,41 @@ import { createUnplugin } from 'unplugin'
import MagicString from 'magic-string'
import { bigCamelize } from '@varlet/shared'

import { moduleName } from '../config'
import { genSideEffectsImport } from '../gen'
import { moduleName, functionComponents } from '../config'
import { genLibraryImport, genSideEffectsImport } from '../gen'

import type { PresetImport, TransformOptions } from '../types'

interface PluginOptions extends TransformOptions {
sourcemap?: boolean
transformStyles: (name: string) => undefined | string
transformDirectives: (name: string) => undefined | [name: string, styles?: string]
}
// transformDirectives: (name: string) => undefined | [name: string, styles?: string]

const componentsRegExp = /(?<=[ (])_?resolveComponent\(\s*["'](lazy-|Lazy)?([^'"]*?)["'][\s,]*[^)]*\)/g
// const importsRegExp = new RegExp(`\\b(${[].join('|')})\\b`, 'g')
// const directivesRegExp = /(?<=[ (])_?resolveDirective\(\s*["']([^'"]*?)["'][\s,]*[^)]*\)/g
const importsRegExp = new RegExp(`\\b(${functionComponents.join('|')})\\b`, 'g')
const directivesRegExp = /(?<=[ (])_?resolveDirective\(\s*["']([^'"]*?)["'][\s,]*[^)]*\)/g

export const transformPlugin = createUnplugin((options: PluginOptions) => {
const { include, exclude, transformStyles } = options
const { include, exclude, transformStyles, transformDirectives } = options

return {
name: `${moduleName}:transform`,
enforce: 'post',
transformInclude (id) {
transformInclude(id) {
if (exclude.some(pattern => id.match(pattern))) {
return false
}
if (include.some(pattern => id.match(pattern))) {
return true
}
},
transform (code, id) {
transform(code, id) {
const imports = new Set<string>()
// const directives: PresetImport[] = []
const directives: PresetImport[] = []
const s = new MagicString(code)
let no = 0

const addStyles = (styles?: string) => {
styles && imports.add(genSideEffectsImport(styles))
Expand All @@ -45,14 +47,32 @@ export const transformPlugin = createUnplugin((options: PluginOptions) => {
return full
})

// s.replace(importsRegExp, (full, name) => {
// addStyles(transformStyles(name))
// return full
// })
s.replace(importsRegExp, (full, name) => {
addStyles(transformStyles(name))
return full
})

s.replace(directivesRegExp, (full, name) => {
const directiveConfig = transformDirectives(bigCamelize(name))

if (directiveConfig) {
const [directive, styles] = directiveConfig
const aliasName = `__v_directive_${no}`

no += 1

addStyles(styles)
directives.push([directive, aliasName])

// if (directives.length) {
// imports.add(genLibraryImport(directives))
// }
return aliasName
}

return full
})

if (directives.length) {
imports.add(genLibraryImport(directives))
}

if (imports.size) {
s.prepend([...imports, ''].join('\n'))
Expand Down
17 changes: 16 additions & 1 deletion src/gen.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
import { moduleName } from './config'
import { PresetImport } from './types'

export function genSideEffectsImport (value: string): string {
export function genSideEffectsImport(value: string): string {
return `import '${value}';`
}

export function genLibraryImport(list: PresetImport[]): string {
const values = list.map((item) => {
if (Array.isArray(item)) {
const [name, as] = item
return `${name} as ${as}`
}

return item
})

return `import {${values.join(',')}} from '${moduleName}';`
}
8 changes: 5 additions & 3 deletions src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import { defineNuxtModule } from '@nuxt/kit'

import type { ModuleOptions } from './types'
import { defaults, moduleName } from './config'
import { resolveOptions, resolveComponents, resolveStyles, resolveImports, transformPlugin } from './core'
import { resolveOptions, resolveComponents, resolveStyles, resolveDirectives, resolveImports, transformPlugin } from './core'

export default defineNuxtModule<ModuleOptions>({
meta: {
name: moduleName,
configKey: moduleName
},
defaults,
setup (_options: ModuleOptions, nuxt) {
setup(_options: ModuleOptions, nuxt) {
const _configs = _options
resolveOptions()

Expand All @@ -26,7 +26,9 @@ export default defineNuxtModule<ModuleOptions>({
include: _configs.include,
exclude: _configs.exclude,
sourcemap: nuxt.options.sourcemap[mode],
transformStyles: name => resolveStyles(_configs, name)
transformStyles: name => resolveStyles(_configs, name),
transformDirectives: name => resolveDirectives(_configs, name)

})
)
})
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/** name: export name from the library, as: the name you want to use in your project, from: the name of library */
export type PresetImport = string | [name: string, as?: string, from?: string]

export type PresetDirectives = Record<string, string | [directive: string, name?: string]>

/** Used to filter files that need to automatically import styles and other functions */
export interface TransformOptions {
include: RegExp[]
Expand Down Expand Up @@ -29,6 +31,10 @@ export interface ModuleOptions extends TransformOptions {
* If you wish to add automatically import content from varlet, you can add it here.
*/
imports: PresetImport[]
/**
* If you wish to add automatically directive content from varlet, you can add it here.
*/
directives: PresetDirectives
}

declare module '@nuxt/schema' {
Expand Down

0 comments on commit a53e534

Please sign in to comment.