Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(addon-components): supports loading components config #454

Merged
merged 1 commit into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading