Skip to content

Commit

Permalink
feat(addon-components): supports loading components config (#454)
Browse files Browse the repository at this point in the history
  • Loading branch information
WRXinYue authored Sep 18, 2024
1 parent 1e766e7 commit 695c88c
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
9 changes: 9 additions & 0 deletions packages/valaxy-addon-components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ export default defineValaxyConfig({
| ---- | ---- | ---- | ---- |
| themes | `string[]` | --- | Third-party themes to import components from |

> [!TIP]
> By default, the system will automatically recognize components under the `components` folder. To manually specify the component path relationships, theme support is required. Create a `components.json` file in the root directory of the theme, and specify the component names and their paths relative to the `components` folder, as shown below:
```json
{
"YunCollectionItem": "collection/YunCollectionItem.vue"
}
```

<br></details>

## Usage
Expand Down
9 changes: 9 additions & 0 deletions packages/valaxy-addon-components/README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ export default defineValaxyConfig({
| ---- | ---- | ---- | ---- |
| themes | `string[]` | --- | 需要导入 components 的第三方主题 |

> [!TIP]
> 通常情况下,系统会自动识别 `components` 文件夹下的组件。如果需要手动指定组件路径关系,必须在主题中支持此功能。在主题根目录下新建 `components.json` 文件,并在文件中指定组件名和组件相对于 `components` 文件夹的路径,如下示例:
```json
{
"YunCollectionItem": "collection/YunCollectionItem.vue"
}
```

<br></details>

## 使用
Expand Down
60 changes: 55 additions & 5 deletions packages/valaxy-addon-components/core/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,71 @@
import { promises as fs } from 'node:fs'
import type { ComponentResolver } from 'unplugin-vue-components'
import { resolveModule } from 'local-pkg'

export interface ValaxyThemesResolverOptions {
themes: string[]
}

export interface ComponentInfo {
path: string
theme: string
}

const components: { [key: string]: ComponentInfo } = {}

// Helper function to format the component name
function formatComponentName(name: string) {
return name[0].toUpperCase() + name.slice(1)
}

// Function to load components from all themes
async function loadComponents(themes: string[]) {
if (Object.keys(components).length === 0) {
for (const theme of themes) {
try {
const path = resolveModule(`valaxy-theme-${theme}/components.json`)
if (path) {
const indexesJson = JSON.parse(await fs.readFile(path, 'utf-8'))

for (const [componentName, componentPath] of Object.entries(indexesJson)) {
components[componentName] = {
path: componentPath as string,
theme,
}
}
}
}
catch (error) {
console.error(`Error loading components for theme ${theme}:`, error)
}
}
}
}

export function ValaxyThemesResolver(options: ValaxyThemesResolverOptions): ComponentResolver {
const { themes } = options

return {
type: 'component',
resolve: (name: string) => {
resolve: async (name: string) => {
const componentName = formatComponentName(name)

await loadComponents(themes)

// Check for existing component path
const component = components[componentName]
if (component) {
const { theme, path } = component
return {
from: `valaxy-theme-${theme}/components/${path}`,
}
}

// Fallback to dynamic resolution based on theme prefix
for (const theme of themes) {
if (name.toLowerCase().startsWith(theme.toLowerCase())) {
const formattedName = name.charAt(0).toUpperCase() + name.slice(1)
return {
name: formattedName,
path: `valaxy-theme-${theme}/components/${name.toLowerCase()}`,
from: `valaxy-theme-${theme}`,
from: `valaxy-theme-${theme}/components/${componentName}.vue`,
}
}
}
Expand Down

1 comment on commit 695c88c

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 Published on https://yun.valaxy.site as production
🚀 Deployed on https://66ea3999df191bdc73c17809--valaxy.netlify.app

Please sign in to comment.