-
Notifications
You must be signed in to change notification settings - Fork 273
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
docs: Relative Issues & Component Update Logs Connected to Each Component #3027
Merged
xiaoyatong
merged 28 commits into
jdf2e:feat_v3.x
from
Alex-huxiyang:feat_issues_commits
Mar 12, 2025
Merged
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
13c69c2
docs: add issues and component logs to all docs
Alex-huxiyang c72022e
docs: add issues and component logs to all docs
Alex-huxiyang b54b51a
docs: add issues and component logs to all docs
Alex-huxiyang e3d9b1b
docs: add issues and component logs to all docs
Alex-huxiyang ee4b3d1
docs: add issues and component logs to all docs
Alex-huxiyang 1681023
docs: add issues and component logs to all docs
Alex-huxiyang eebfa67
docs: add issues and component logs to all docs
Alex-huxiyang 6435a61
docs: add issues and component logs to all docs
Alex-huxiyang bbe6ad1
chore: 文本相关性算法
Alex-huxiyang 6de2117
chore: 文本相关性算法
Alex-huxiyang a3266f0
fix: issue url map
Alex-huxiyang f205051
fix: update docs content
Alex-huxiyang e9fd914
refactor: 自定义mdx,组件化Contribution, 修改脚本生成
Alex-huxiyang 3f12670
Merge branch 'V3.0' into feat_issues_commits
Alex-huxiyang 133c9c1
fix: resolve conflicts
Alex-huxiyang 18b1369
fix: update mdx import config
Alex-huxiyang 629e971
fix: update mdx import config
Alex-huxiyang afee0b3
fix: update mdx import config
Alex-huxiyang c47c0c3
fix: update mdx import config
Alex-huxiyang 35a5893
fix: update mdx import config
Alex-huxiyang 01e0d31
fix: remove useless code
Alex-huxiyang 16edb15
fix: update component style
Alex-huxiyang 368c7bd
fix: 移除emoji
Alex-huxiyang b06e350
Merge branch 'feat_v3.x' into feat_issues_commits
Alex-huxiyang f47a0a6
fix: add desc for scripts and adjust style
Alex-huxiyang ed16a05
fix: add desc for scripts and adjust style
Alex-huxiyang 8e445f8
fix: add desc for scripts and adjust style
Alex-huxiyang a0355fe
fix: add desc for scripts and adjust style
Alex-huxiyang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
/** | ||
* @description 用于分析标题或日志与组件的相关性 | ||
*/ | ||
import config from '../src/config.json' assert { type: 'json' } | ||
|
||
// 分析标题与组件的相关性 | ||
export function analyzeTitleRelevance(title, componentName, componentNameCN) { | ||
const lowerTitle = title.toLowerCase() | ||
const lowerComponentName = componentName.toLowerCase() | ||
let relevanceScore = 0 | ||
|
||
// 1. 作者指定 (权重: 100) | ||
const commitFormatMatch = title.match(/[\w:]+\((\w+)\):?/) // 修改正则表达式,使其更灵活地匹配组件名 | ||
if ( | ||
commitFormatMatch && | ||
commitFormatMatch[1].toLowerCase() === lowerComponentName | ||
) { | ||
relevanceScore += 100 | ||
} | ||
|
||
// 2. 完全匹配 (权重: 20) - 提高权重 | ||
if (lowerTitle.includes(lowerComponentName)) { | ||
relevanceScore += 20 | ||
} | ||
if (title.includes(componentNameCN)) { | ||
relevanceScore += 20 | ||
} | ||
|
||
// 3. 检查组件列表 (权重: 15) - 提高权重,支持更多分隔符 | ||
const componentList = lowerTitle | ||
.split(/[,;\s\[\]]+/) | ||
.map((s) => s.trim()) | ||
.filter(Boolean) | ||
if (componentList.includes(lowerComponentName)) { | ||
relevanceScore += 15 | ||
} | ||
|
||
// 4. 部分匹配 (权重: 3) | ||
const componentWords = lowerComponentName | ||
.split(/(?=[A-Z])/) | ||
.map((word) => word.toLowerCase()) | ||
componentWords.forEach((word) => { | ||
if (word.length > 1 && lowerTitle.includes(word)) { | ||
relevanceScore += 3 | ||
} | ||
}) | ||
|
||
// 5. 检查中文关键词匹配 (权重: 3) | ||
const cnKeywords = componentNameCN.split(/[s,,]/).filter(Boolean) | ||
cnKeywords.forEach((keyword) => { | ||
if (title.includes(keyword)) { | ||
relevanceScore += 3 | ||
} | ||
}) | ||
|
||
// 6. 上下文语义分析 (权重: 30) | ||
// 检查是否是组件的主要功能描述 | ||
const isMainFeature = | ||
title.includes(`${componentName}组件`) || | ||
title.includes(`${componentNameCN}组件`) || | ||
(title.includes(componentName) && title.includes('组件')) | ||
if (isMainFeature) { | ||
relevanceScore += 30 | ||
} | ||
|
||
// 相关性阈值 | ||
const RELEVANCE_THRESHOLD = 3 | ||
|
||
return { | ||
score: relevanceScore, | ||
isRelevant: relevanceScore >= RELEVANCE_THRESHOLD, // 只有达到阈值才算相关 | ||
details: { | ||
commitFormat: commitFormatMatch ? commitFormatMatch[1] : null, | ||
exactMatchEn: lowerTitle.includes(lowerComponentName), | ||
exactMatchCn: title.includes(componentNameCN), | ||
partialMatches: componentWords.filter( | ||
(word) => word.length > 1 && lowerTitle.includes(word) | ||
), | ||
cnMatches: cnKeywords.filter((keyword) => title.includes(keyword)), | ||
}, | ||
} | ||
} | ||
|
||
// 分析标题与所有组件的相关性,返回相关性最高的组件们 | ||
|
||
export function findMostRelevantComponents(title) { | ||
let maxScore = -1 | ||
let mostRelevantComponents = [] | ||
let relevanceDetails = null | ||
|
||
config.nav.forEach((nav) => { | ||
nav.packages.forEach((pkg) => { | ||
const result = analyzeTitleRelevance(title, pkg.name, pkg.cName) | ||
if (result.score > maxScore) { | ||
maxScore = result.score | ||
mostRelevantComponents = [pkg] | ||
relevanceDetails = result | ||
} else if (result.score === maxScore && maxScore > 0) { | ||
mostRelevantComponents.push(pkg) | ||
} | ||
}) | ||
}) | ||
const result = { | ||
components: maxScore >= 15 ? mostRelevantComponents : [], | ||
score: maxScore, | ||
details: relevanceDetails, | ||
} | ||
|
||
if (result.components && result.components.length > 0) { | ||
return result.components.map((pkg) => pkg.name) | ||
} | ||
return [] | ||
} | ||
|
||
const testTitles = [ | ||
'fix: usecallback to fix render too many times, button,animatingnumbers,avatar,audio; and fix avatargroup when length > maxsize (#2628) ', | ||
'fix(dialog): 关闭按钮默认在底部,24px白色图标 (#2118) @irisSong', | ||
'feat(calendar): support renderBottomButton props (#2645) ', | ||
'希望Dialog组件内置的确认以及取消按钮对异步自带loading或者可以手动设置loading #1202', | ||
'[FR]: getSystemInfoSync 微信小程序从基础库 2.20.1 开始,本接口停止维护,需要兼容新老接口', | ||
] | ||
|
||
// console.log('\n相关性分析结果:') | ||
// testTitles.forEach((title) => { | ||
// console.log('\n标题:', title) | ||
// const result = findMostRelevantComponents(title) | ||
// console.log(`相关组件: ${result})}`) | ||
// console.log(`相关性得分: ${result.score}`) | ||
// console.log('详细信息:', result.details) | ||
// }) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
/** | ||
* description: 生成Contribution数据 | ||
*/ | ||
import axios from 'axios' | ||
import * as fs from 'fs' | ||
import * as path from 'path' | ||
import { findMostRelevantComponents } from './analyze-title-relevance.mjs' | ||
import { fileURLToPath } from 'url' | ||
import { dirname } from 'path' | ||
import config from '../src/config.json' assert { type: 'json' } | ||
const __filename = fileURLToPath(import.meta.url) | ||
const __dirname = dirname(__filename) | ||
|
||
const GITHUB_API = { | ||
BASE_URL: 'https://api.github.com/repos/jdf2e/nutui-react', | ||
REPO_URL: 'https://github.com/jdf2e/nutui-react/', | ||
HEADERS: { | ||
Accept: 'application/vnd.github.v3+json', | ||
Authorization: `Bearer ${TOKEN}`, | ||
}, | ||
} | ||
|
||
const headers = GITHUB_API.HEADERS | ||
const coms = config.nav | ||
.map((i) => i.packages) | ||
.flat(Infinity) | ||
.filter((i) => i.show) | ||
|
||
async function generateContribution(componentName) { | ||
try { | ||
const issuesResponse = await axios.get( | ||
'https://api.github.com/repos/jdf2e/nutui-react/issues', | ||
{ | ||
params: { | ||
state: 'closed', | ||
sort: 'updated', | ||
direction: 'desc', | ||
per_page: 1000, | ||
is: 'issue', | ||
}, | ||
headers, | ||
} | ||
) | ||
|
||
const issues = issuesResponse.data | ||
.filter( | ||
(issue) => | ||
!issue.pull_request && | ||
findMostRelevantComponents(issue.title).includes(componentName) | ||
) | ||
.slice(0, 5) | ||
.map((issue) => ({ | ||
title: issue.title, | ||
url: issue.html_url, | ||
number: issue.number, | ||
})) | ||
|
||
const releasesResponse = await axios.get( | ||
'https://api.github.com/repos/jdf2e/nutui-react/releases', | ||
{ | ||
params: { | ||
per_page: 100, | ||
}, | ||
headers, | ||
} | ||
) | ||
|
||
const releases = releasesResponse.data | ||
.reduce((acc, release) => { | ||
const buttonUpdates = release.body | ||
.split('\n') | ||
.filter((line) => { | ||
return findMostRelevantComponents(line).includes(componentName) | ||
}) | ||
.map((line) => { | ||
let processedLine = line.replace(/^[*\s-]*/, '').replace(':art') | ||
Alex-huxiyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let type = 'others' | ||
if (processedLine.includes(':bug:')) { | ||
type = 'fix' | ||
processedLine = processedLine.replace(':bug:', '') | ||
} | ||
if (processedLine.includes(':sparkles:')) { | ||
type = 'feat' | ||
processedLine = processedLine.replace(':sparkles:', '') | ||
} | ||
|
||
const symbols = { | ||
feat: '✨ ', | ||
fix: '🐛 ', | ||
docs: '📖 ', | ||
style: '🎨 ', | ||
perf: '⚡️ ', | ||
others: '💡 ', | ||
} | ||
|
||
let processedContent = processedLine | ||
.trim() | ||
.replace(/^(feat|fix|docs|style|perf):\s*/, '') | ||
|
||
const prMatch = processedContent.match(/#(\d+)/) | ||
if (prMatch) { | ||
const prNumber = prMatch[1] | ||
processedContent = processedContent.replace( | ||
Alex-huxiyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`#${prNumber}`, | ||
`[#${prNumber}](https://github.com/jdf2e/nutui-react/pull/${prNumber})` | ||
) | ||
} | ||
|
||
// 检查是否已经包含表情符号 | ||
const hasEmoji = /[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u.test(processedContent) | ||
|
||
return { | ||
version: release.tag_name, | ||
type, | ||
content: hasEmoji ? processedContent : `${symbols[type]}${processedContent}`, | ||
Alex-huxiyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
rawContent: processedContent, | ||
tagName: release.tag_name, | ||
} | ||
}) | ||
return [...acc, ...buttonUpdates] | ||
}, []) | ||
.slice(0, 5) | ||
|
||
// 生成结构化数据 | ||
const contributionData = { | ||
issues: { | ||
[componentName]: issues, | ||
}, | ||
logs: { | ||
[componentName]: releases, | ||
Alex-huxiyang marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}, | ||
} | ||
|
||
return contributionData | ||
} catch (error) { | ||
console.error(error.message) | ||
} | ||
} | ||
|
||
Promise.all(coms.map((i) => generateContribution(i.name))) | ||
.then((results) => { | ||
const allContributions = results.reduce( | ||
(acc, curr, index) => { | ||
if (curr) { | ||
const componentName = coms[index].name | ||
acc.issues[componentName] = curr.issues[componentName] | ||
acc.logs[componentName] = curr.logs[componentName] | ||
} | ||
return acc | ||
}, | ||
{ issues: {}, logs: {} } | ||
) | ||
|
||
// 将数据写入到 JSON 文件 | ||
const outputPath = path.resolve( | ||
__dirname, | ||
'../src/sites/doc/components/contribution/contribution.json' | ||
) | ||
fs.writeFileSync( | ||
outputPath, | ||
JSON.stringify(allContributions, null, 2), | ||
'utf8' | ||
) | ||
console.log('已成功写入到:', outputPath) | ||
}) | ||
.catch((error) => console.error('获取贡献数据失败:', error)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个 token 怎么弄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/settings/tokens. 在这里生成Generate new token(classic)复制进去