rashagu / semi-design-vue

Vue3 UI components based on semi-design and Vue
https://www.kousum.asia
MIT License
62 stars 4 forks source link

[Bug] 使用theme插件引入主题会导致基础样式丢失 #11

Closed 497363983 closed 2 months ago

497363983 commented 2 months ago

具体表现为使用theme插件引入主题后出现包括但不限于form表单中select边框缺失,同时引入主题后部分scss变量处于未定义状态。 这应与semi-ui-vue下的_base/base.scss中的导入语句@import '@douyinfe/semi-foundation/base/base';缺少~有关,将其修改为@import '~@douyinfe/semi-foundation/base/base';即可修复该问题。

rashagu commented 2 months ago

请问用的是哪个主题插件,vite版本是多少?

497363983 commented 2 months ago

请问用的是哪个主题插件,vite版本是多少?

vite 版本 5.2.11,使用本仓库中的 vite-plugin-semi-theme 引入自定义主题 @semi-bot/semi-theme-feishu-dashboard

497363983 commented 2 months ago

另在解决主题问题时为了支持pnpm,修改了 vite-plugin-semi-theming 插件,会发现编译 _base/base.scss 报错,按照前面我说的修改后能够正常导入。修改后的插件代码如下:

import { readFileSync, existsSync } from 'fs';
import path from 'path';
import { platform } from 'os';
import { pathToFileURL } from 'url';
import { createRequire } from 'module';
const _require = createRequire(import.meta.url);
const isWindows = platform() === 'win32';
export function semiTheming({ theme, ...options }) {
    const include = options.include && normalizePath(options.include);
    const variables = convertMapToString(options.variables || {});
    let viteConfig;
    return {
        name: 'semi-theme',
        enforce: 'post',
        configResolved(config) {
            viteConfig = config;
        },
        async load(id) {
            const filePath = normalizePath(id);
            // https://github.com/DouyinFE/semi-design/blob/main/packages/semi-webpack/src/semi-webpack-plugin.ts#L83
            if (/@douyinfe\/semi-(ui|icons|foundation)\/lib\/.+\.css$/.test(filePath) || /@kousum\/semi-ui-vue\/dist\/.+\.css$/.test(filePath) || /_base\/base.css$/.test(filePath)) {
                const scssFilePath = filePath.replace(/\.css$/, '.scss');
                const { default: sass } = await import('sass');
                try {
                    return sass.compileString(loader(readFileSync(scssFilePath, 'utf-8'), {
                        ...options,
                        name: theme,
                        include,
                        variables,
                    }), {
                        importers: [
                            {
                                findFileUrl(url) {
                                    if (url.startsWith('~')) {
                                        // Resolve theme scss from root node_modules
                                        if (theme && url.startsWith(`~${theme}`)) {
                                            return pathToFileURL(path.resolve(viteConfig.root, 'node_modules', url.substring(1)));
                                        }
                                        return pathToFileURL(path.resolve(scssFilePath.substring(0, scssFilePath.lastIndexOf('/node_modules/') +
                                            '/node_modules/'.length), url.substring(1)));
                                    }
                                    const filePath = path.resolve(path.dirname(scssFilePath), url);
                                    if (existsSync(filePath)) {
                                        return pathToFileURL(filePath);
                                    }
                                    return null;
                                },
                            },
                        ],
                        logger: sass.Logger.silent,
                    }).css;
                } catch (error) {
                    console.log(error);
                    console.log('Error compiling SCSS file:', scssFilePath);
                }

            }
        },
    };
}
export default semiTheming;
// copy from https://github.com/DouyinFE/semi-design/blob/main/packages/semi-webpack/src/semi-theme-loader.ts
function loader(source, options) {
    const theme = options.name || '@douyinfe/semi-theme-default';
    // always inject
    const scssVarStr = `@import "~${theme}/scss/index.scss";\n`;
    // inject once
    const cssVarStr = `@import "~${theme}/scss/global.scss";\n`;
    let animationStr = `@import "~${theme}/scss/animation.scss";\n`;
    let componentVariables;
    let fileStr = source;
    try {
        _require.resolve(`${theme}/scss/animation.scss`);
    }
    catch (e) {
        animationStr = ''; // fallback to empty string
    }
    try {
        componentVariables = _require.resolve(`${theme}/scss/local.scss`);
    }
    catch (e) {
        // ignore
    }
    if (options.include || options.variables || componentVariables) {
        let localImport = '';
        if (componentVariables) {
            localImport += `\n@import "~${theme}/scss/local.scss";`;
        }
        if (options.include) {
            localImport += `\n@import "${options.include}";`;
        }
        if (options.variables) {
            localImport += `\n${options.variables}`;
        }
        try {
            const regex = /(@import '.\/variables.scss';?|@import ".\/variables.scss";?)/g;
            const fileSplit = fileStr.split(regex).filter(item => Boolean(item));
            if (fileSplit.length > 1) {
                fileSplit.splice(fileSplit.length - 1, 0, localImport);
                fileStr = fileSplit.join('');
            }
        }
        catch (error) {
            // ignore
        }
    }
    // inject prefix
    const prefixCls = options.prefixCls || 'semi';
    const prefixClsStr = `$prefix: '${prefixCls}';\n`;
    if (source.includes('semi-base')) {
        return `${animationStr}${cssVarStr}${scssVarStr}${prefixClsStr}${fileStr}`;
    }
    else {
        return `${scssVarStr}${prefixClsStr}${fileStr}`;
    }
}
// copy from https://github.com/DouyinFE/semi-design/blob/main/packages/semi-webpack/src/semi-webpack-plugin.ts#L136
function convertMapToString(map) {
    return Object.keys(map).reduce(function (res, cur) {
        return res + `${cur}: ${map[cur]};\n`;
    }, '');
}
function normalizePath(p) {
    return path.posix.normalize(isWindows ? p.replace(/\\/g, '/') : p);
}
rashagu commented 2 months ago

@497363983 你似乎用了vite-plugin-semi-theme这个插件,本仓库的插件包名是@kousum/vite-plugin-semi-theme

497363983 commented 2 months ago

@497363983 你似乎用了vite-plugin-semi-theme这个插件,本仓库的插件包名是@kousum/vite-plugin-semi-theme

@rashagu 我使用的的确是@kousum/vite-plugin-semi-theme,前面是我的描述不清楚。在使用这个的时候我用的主题没有被成功导入。

rashagu commented 2 months ago

@497363983 请提供一下最小化重现仓库地址

github-actions[bot] commented 2 months ago

This issue is stale because it has been open for 14 days with no activity.

497363983 commented 2 months ago

@rashagu 抱歉,前段时间忙于其他事务,没有及时回复,这是一个最小复现:https://codesandbox.io/p/devbox/p95yfh?migrateFrom=lm7g2x&layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clxphaklk00063o6plfbwk923%2522%252C%2522sizes%2522%253A%255B70%252C30%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clxphaklj00023o6pdq41hwem%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clxphaklj00043o6pwa09myvq%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clxphaklj00053o6pvsajj45a%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clxphaklj00023o6pdq41hwem%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clxphaklj00013o6p9i7t9x81%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522FILE%2522%252C%2522filepath%2522%253A%2522%252Fpackage.json%2522%257D%255D%252C%2522id%2522%253A%2522clxphaklj00023o6pdq41hwem%2522%252C%2522activeTabId%2522%253A%2522clxphaklj00013o6p9i7t9x81%2522%257D%252C%2522clxphaklj00053o6pvsajj45a%2522%253A%257B%2522id%2522%253A%2522clxphaklj00053o6pvsajj45a%2522%252C%2522activeTabId%2522%253A%2522clxphgxpq00cf3o6p6j64g64y%2522%252C%2522tabs%2522%253A%255B%257B%2522type%2522%253A%2522TASK_PORT%2522%252C%2522port%2522%253A5173%252C%2522taskId%2522%253A%2522Development%2522%252C%2522id%2522%253A%2522clxphgxpq00cf3o6p6j64g64y%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522path%2522%253A%2522%252F%2522%257D%255D%257D%252C%2522clxphaklj00043o6pwa09myvq%2522%253A%257B%2522id%2522%253A%2522clxphaklj00043o6pwa09myvq%2522%252C%2522activeTabId%2522%253A%2522clxphazv9006j3o6pedbafqma%2522%252C%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clxphaklj00033o6pdcmvqxtf%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522TERMINAL%2522%252C%2522shellId%2522%253A%2522clxphalak000adif8ac2taarg%2522%257D%252C%257B%2522type%2522%253A%2522TASK_LOG%2522%252C%2522taskId%2522%253A%2522Development%2522%252C%2522id%2522%253A%2522clxphazv9006j3o6pedbafqma%2522%252C%2522mode%2522%253A%2522permanent%2522%257D%255D%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D

497363983 commented 2 months ago

可以看到在这个里面,Select 是缺少边框的,并且部分 token 是未定义的状态(但实际上它们应该是存在的)。 image

rashagu commented 2 months ago

@497363983 这个主题背景默认就是白色 20240624152016

497363983 commented 1 month ago

@rashagu 请注意观察边框,这个主题在浅色模式下表单项的边框是存在的,但是使用现有插件引入后表单项的边框是缺失的,并不是背景的问题 这才是这个主题在浅色模式下应有的表现 image

rashagu commented 1 month ago

20240705160821

组件级变量需要额外配置。新版本不需要了