mirror of
https://github.com/lobehub/lobehub
synced 2026-04-21 17:47:27 +00:00
* ✨ feat: add hotfix workflow and script for automated hotfix management Signed-off-by: Innei <tukon479@gmail.com> * 🔧 fix: refactor PR creation command to use execFileSync for improved reliability Signed-off-by: Innei <tukon479@gmail.com> * 🔧 chore: update @lobehub/ui version and refactor dynamic import handling - Bump @lobehub/ui dependency from ^4.35.0 to ^4.36.2 in package.json. - Refactor settingsContentToStatic.mts to simplify dynamic import processing by removing business feature checks. - Add initialize.ts to enable immer's map set functionality. - Correct import path in layout.tsx from 'initiallize' to 'initialize'. Signed-off-by: Innei <tukon479@gmail.com> * 🔧 chore: update @types/react version in package.json - Bump @types/react dependency from ^19.2.9 to 19.2.14. - Add @types/react version to overrides section for consistency. Signed-off-by: Innei <tukon479@gmail.com> * 🔧 chore: enhance auto-tag-release workflow for strict semver validation - Updated regex to match strict semantic versioning format, allowing for optional prerelease and build metadata. - Added validation step to ensure the version is a valid semver before proceeding with the release process. Signed-off-by: Innei <tukon479@gmail.com> * 🗑️ chore: remove defaultSecurityBlacklist test file - Deleted the test file for DEFAULT_SECURITY_BLACKLIST as it is no longer needed. - This cleanup helps maintain a more streamlined test suite. Signed-off-by: Innei <tukon479@gmail.com> * 🔧 chore: update localization files for multiple languages - Improved translations in Arabic, Bulgarian, German, English, and Spanish for chat and tool-related strings. - Enhanced descriptions for various parameters and added new keys for file handling and security warnings. - Adjusted phrasing for clarity and consistency across languages. Signed-off-by: Innei <tukon479@gmail.com> * 🔧 chore: update PR comment script to include Actions Artifacts link - Modified the PR comment generation script to accept an additional artifactsUrl parameter. - Updated the comment format to include both Release download and Actions Artifacts links for better accessibility. Signed-off-by: Innei <tukon479@gmail.com> --------- Signed-off-by: Innei <tukon479@gmail.com>
130 lines
3.8 KiB
TypeScript
130 lines
3.8 KiB
TypeScript
/* eslint-disable no-undef */
|
|
import { Lang, parse } from '@ast-grep/napi';
|
|
import path from 'node:path';
|
|
|
|
import { invariant, isDirectRun, runStandalone, updateFile } from './utils.mjs';
|
|
|
|
interface DynamicImportInfo {
|
|
componentName: string;
|
|
end: number;
|
|
importPath: string;
|
|
key: string;
|
|
start: number;
|
|
}
|
|
|
|
const extractDynamicImportsFromMap = (code: string): DynamicImportInfo[] => {
|
|
const results: DynamicImportInfo[] = [];
|
|
|
|
const regex =
|
|
/\[SettingsTabs\.(\w+)]:\s*dynamic\(\s*\(\)\s*=>\s*import\(\s*["']([^"']+)["']\s*\)/g;
|
|
|
|
let match;
|
|
while ((match = regex.exec(code)) !== null) {
|
|
const key = match[1];
|
|
const importPath = match[2];
|
|
|
|
const componentName = key.charAt(0).toUpperCase() + key.slice(1) + 'Tab';
|
|
|
|
results.push({
|
|
componentName,
|
|
end: 0,
|
|
importPath,
|
|
key,
|
|
start: 0,
|
|
});
|
|
}
|
|
|
|
return results;
|
|
};
|
|
|
|
const generateStaticImports = (imports: DynamicImportInfo[]): string => {
|
|
return imports.map((imp) => `import ${imp.componentName} from '${imp.importPath}';`).join('\n');
|
|
};
|
|
|
|
const generateStaticComponentMap = (imports: DynamicImportInfo[]): string => {
|
|
const entries = imports.map((imp) => ` [SettingsTabs.${imp.key}]: ${imp.componentName},`);
|
|
|
|
return `const componentMap: Record<string, React.ComponentType<{ mobile?: boolean }>> = {\n${entries.join('\n')}\n}`;
|
|
};
|
|
|
|
export const convertSettingsContentToStatic = async (TEMP_DIR: string) => {
|
|
const filePath = path.join(
|
|
TEMP_DIR,
|
|
'src/app/[variants]/(main)/settings/features/SettingsContent.tsx',
|
|
);
|
|
|
|
console.log(' Processing SettingsContent.tsx dynamic imports...');
|
|
|
|
await updateFile({
|
|
assertAfter: (code) => {
|
|
const noDynamic = !/dynamic\(\s*\(\)\s*=>\s*import/.test(code);
|
|
const hasStaticMap = /componentMap:\s*Record<string,/.test(code);
|
|
return noDynamic && hasStaticMap;
|
|
},
|
|
filePath,
|
|
name: 'convertSettingsContentToStatic',
|
|
transformer: (code) => {
|
|
const imports = extractDynamicImportsFromMap(code);
|
|
|
|
invariant(
|
|
imports.length > 0,
|
|
'[convertSettingsContentToStatic] No dynamic imports found in SettingsContent.tsx',
|
|
);
|
|
|
|
console.log(` Found ${imports.length} dynamic imports in componentMap`);
|
|
|
|
const staticImports = generateStaticImports(imports);
|
|
const staticComponentMap = generateStaticComponentMap(imports);
|
|
|
|
let result = code;
|
|
|
|
result = result.replace(/import dynamic from ["']@\/libs\/next\/dynamic["'];\n?/, '');
|
|
|
|
result = result.replace(
|
|
/import Loading from ["']@\/components\/Loading\/BrandTextLoading["'];\n?/,
|
|
'',
|
|
);
|
|
|
|
const ast = parse(Lang.Tsx, result);
|
|
const root = ast.root();
|
|
|
|
const lastImport = root
|
|
.findAll({
|
|
rule: {
|
|
kind: 'import_statement',
|
|
},
|
|
})
|
|
.at(-1);
|
|
|
|
invariant(
|
|
lastImport,
|
|
'[convertSettingsContentToStatic] No import statements found in SettingsContent.tsx',
|
|
);
|
|
|
|
const insertPos = lastImport!.range().end.index;
|
|
result =
|
|
result.slice(0, insertPos) +
|
|
"\nimport type React from 'react';\n" +
|
|
staticImports +
|
|
result.slice(insertPos);
|
|
|
|
const componentMapRegex = /const componentMap = {[\S\s]*?\n};/;
|
|
invariant(
|
|
componentMapRegex.test(result),
|
|
'[convertSettingsContentToStatic] componentMap declaration not found in SettingsContent.tsx',
|
|
);
|
|
|
|
result = result.replace(componentMapRegex, staticComponentMap + ';');
|
|
|
|
result = result.replaceAll(/\n{3,}/g, '\n\n');
|
|
|
|
return result;
|
|
},
|
|
});
|
|
};
|
|
|
|
if (isDirectRun(import.meta.url)) {
|
|
await runStandalone('convertSettingsContentToStatic', convertSettingsContentToStatic, [
|
|
{ lang: Lang.Tsx, path: 'src/app/[variants]/(main)/settings/features/SettingsContent.tsx' },
|
|
]);
|
|
}
|