✨ feat(vscode): 代码阅读的块种类只画图标(lucide,种类色),种类名放进鼠标停上去的提示和读屏文字;库规则给自己的图标

This commit is contained in:
cruldra committed 2026-09-27 20:02:32 +08:00
1 parent 33a1b5d57c
commit 1dfc0c7b1e
19 files changed
+185 -56

No files matched your search

+2 -2
View File
@@ -46,7 +46,7 @@ function segmentsOf(rows: PropertyRow[]): Segment[] {
describe('celery 库规则:应用', () => {
it('luffy 的 celery_app:名称 / 应用名 / 消息队列 / 结果存储', async () => {
const app = await card(SNAPSHOT, 'celery.app')
expect(app.badge).toEqual({ label: 'Celery 应用', color: { dark: '#98c379', light: '#4d7f17' } })
expect(app.badge).toEqual({ label: 'Celery 应用', color: { dark: '#98c379', light: '#4d7f17' }, icon: 'server-cog' })
expect(propertyLines(properties(app))).toEqual([
'名称: celery_app',
'应用名: "luffy_agent"',
@@ -90,7 +90,7 @@ describe('celery 库规则:应用', () => {
describe('celery 库规则:定时任务', () => {
it('luffy 的 beat_schedule:应用、任务表,频率换算成人话,说明取注释,展开另起一行', async () => {
const beat = await card(SNAPSHOT, 'celery.beat')
expect(beat.badge).toEqual({ label: '定时任务', color: { dark: '#56b6c2', light: '#127f8c' } })
expect(beat.badge).toEqual({ label: '定时任务', color: { dark: '#56b6c2', light: '#127f8c' }, icon: 'calendar-clock' })
expect(propertyLines(properties(beat))).toEqual([
'应用: celery_app',
'任务: 12 条,另有展开 1 处',
+4 -2
View File
@@ -21,6 +21,8 @@ const APP_KIND = 'celery.app'
const BEAT_KIND = 'celery.beat'
const APP_COLOR: ThemeColor = { dark: '#98c379', light: '#4d7f17' }
const BEAT_COLOR: ThemeColor = { dark: '#56b6c2', light: '#127f8c' }
const APP_ICON = 'server-cog'
const BEAT_ICON = 'calendar-clock'
/** `Celery(...)` 的位置参数依次是哪个参数(celery.app.base.Celery.__init__)。 */
const APP_PARAMETERS = ['main', 'loader', 'backend', 'amqp', 'events', 'log', 'control', 'set_as_current', 'tasks', 'broker', 'include', 'changes', 'config_source', 'fixups', 'task_cls', 'autofinalize', 'namespace', 'strict_typing']
@@ -500,7 +502,7 @@ function beatBlock(app: Node, schedule: Node, settings: [string, Node][], doc: N
items: entries.map(entry => entryItem(entry, withOptions, env)),
},
]
return { kind: BEAT_KIND, badge: { label: words.beatKind, color: BEAT_COLOR }, rows, absorbs: [] }
return { kind: BEAT_KIND, badge: { label: words.beatKind, color: BEAT_COLOR, icon: BEAT_ICON }, rows, absorbs: [] }
}
// ─── Celery 应用 ──────────────────────────────────────────────────────────────
@@ -527,7 +529,7 @@ function appBlock(target: Node, call: Call, doc: Node | undefined, env: Env): Ru
]
return {
kind: APP_KIND,
badge: { label: words.appKind, color: APP_COLOR },
badge: { label: words.appKind, color: APP_COLOR, icon: APP_ICON },
rows,
...(target.type === 'identifier' && { defines: range(target) }),
absorbs: [],
@@ -128,11 +128,11 @@ describe('dataclasses 库规则(Python)', () => {
expect(sandbox.children.map(child => [child.kind, child.startLine])).toEqual([['function', 52]])
})
it('筛选:种类是 dataclasses.dataclass、叫「数据类」,访问级别同原来的类;种类标签有自己的颜色,默认收起子块', async () => {
it('筛选:种类是 dataclasses.dataclass、叫「数据类」,访问级别同原来的类;种类有自己的颜色和图标,默认收起子块', async () => {
const list = await views(SNAPSHOT)
const sandbox = named(list, 'SandboxAccess')
expect(sandbox.attributes).toEqual({ kind: 'dataclasses.dataclass', access: 'public' })
expect(sandbox.badge).toEqual({ label: '数据类', color: { dark: '#ef7fb0', light: '#b3306c' } })
expect(sandbox.badge).toEqual({ label: '数据类', color: { dark: '#ef7fb0', light: '#b3306c' }, icon: 'package' })
expect(fileAttributes(list, pythonZhTranslator.attributeNames).find(attribute => attribute.id === 'kind')?.values)
.toContainEqual({ id: 'dataclasses.dataclass', name: '数据类', count: 4 })
})
+2 -1
View File
@@ -16,6 +16,7 @@ const LIBRARY = 'dataclasses'
const TYPE_LIBRARIES = ['dataclasses', 'typing', 'typing_extensions']
const KIND = 'dataclasses.dataclass'
const COLOR: ThemeColor = { dark: '#ef7fb0', light: '#b3306c' }
const ICON = 'package'
/** `@dataclass(...)` 各参数不写时的值:写成这个值等于没写,「选项」里不讲。 */
const OPTION_DEFAULTS: Record<string, boolean> = {
@@ -261,7 +262,7 @@ function dataclassCard(block: ClassBlock, decorator: Node, call: Call | undefine
]
return {
kind: KIND,
badge: { label: words.kind, color: COLOR },
badge: { label: words.kind, color: COLOR, icon: ICON },
rows,
...(facts.name && { defines: range(facts.name) }),
absorbs: withLeadingComments(children, [...fields.map(field => field.block), ...markers]),
@@ -47,7 +47,7 @@ describe('sqlAlchemy 库规则', () => {
it('referralRelation:和原型一样的数据表卡片', async () => {
const table = await model(SNAPSHOT, 'ReferralRelation')
expect(table.kind).toBe('sqlalchemy.table')
expect(table.badge).toEqual({ label: '数据表', color: { dark: '#e8a860', light: '#a3590d' } })
expect(table.badge).toEqual({ label: '数据表', color: { dark: '#e8a860', light: '#a3590d' }, icon: 'database' })
expect(propertyLines(properties(table))).toEqual([
'名称: ReferralRelation',
'表名: referral_relations',
+2 -1
View File
@@ -20,6 +20,7 @@ const SCHEMA_ITEMS = new Set(['ForeignKey', 'Sequence', 'Identity', 'Computed',
const SIZE_KEYWORDS = ['length', 'precision', 'scale']
const TABLE_KIND = 'sqlalchemy.table'
const TABLE_COLOR: ThemeColor = { dark: '#e8a860', light: '#a3590d' }
const TABLE_ICON = 'database'
/** 一种显示语言的用词。 */
interface Words {
@@ -435,7 +436,7 @@ function tableBlock(block: ClassBlock, model: Model, env: Env): RuleCard {
const members = [model.table, model.args, ...model.columns.map(column => column.member), ...model.relationships.map(relationship => relationship.member)]
return {
kind: TABLE_KIND,
badge: { label: words.kind, color: TABLE_COLOR },
badge: { label: words.kind, color: TABLE_COLOR, icon: TABLE_ICON },
rows,
...(facts.name && { defines: range(facts.name) }),
absorbs: withLeadingComments(block.children, members.filter((member): member is Member => member !== undefined).map(member => member.block)),