@sunshj/vscode-ab5x-utils 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "@sunshj/vscode-ab5x-utils",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "AB5X VSCode Utils",
5
5
  "type": "module",
6
6
  "keywords": [],
7
7
  "license": "ISC",
8
8
  "author": "sunshj",
9
+ "files": [
10
+ "dist"
11
+ ],
9
12
  "main": "dist/index.cjs",
10
13
  "module": "dist/index.mjs",
11
14
  "types": "dist/index.d.mts",
@@ -22,6 +25,6 @@
22
25
  "scripts": {
23
26
  "build": "tsdown",
24
27
  "prepublishOnly": "pnpm build",
25
- "release": "bumpp && npm publish"
28
+ "release": "bumpp --tag \"vscode-ab5x-utils-v%s\" --commit \"release @sunshj/vscode-ab5x-utils v%s\" && npm publish"
26
29
  }
27
30
  }
package/src/index.ts DELETED
@@ -1,388 +0,0 @@
1
- import {
2
- commands,
3
- DocumentLink,
4
- languages,
5
- Range,
6
- window,
7
- workspace,
8
- type CodeLens,
9
- type CodeLensProvider,
10
- type CompletionItem,
11
- type CompletionItemProvider,
12
- type CompletionList,
13
- type DecorationOptions,
14
- type Disposable,
15
- type DocumentLinkProvider,
16
- type DocumentSelector,
17
- type Hover,
18
- type HoverProvider,
19
- type Position,
20
- type ProviderResult,
21
- type TextDocument,
22
- type TextEditor,
23
- type TextEditorDecorationType,
24
- type Uri
25
- } from 'vscode'
26
-
27
- /** 匹配结果项 */
28
- export interface MatchItem<TExtra = unknown> {
29
- /** 匹配的文本 */
30
- text: string
31
- /** 匹配开始索引 */
32
- startIndex: number
33
- /** 匹配结束索引 */
34
- endIndex: number
35
- /** 额外数据,用于 Hover/Completion/Decoration */
36
- extra?: TExtra
37
- }
38
-
39
- /** 收集函数类型 */
40
- export type CollectFn<TExtra = unknown> = (
41
- document: TextDocument,
42
- skipCache?: boolean
43
- ) => Array<MatchItem<TExtra>>
44
-
45
- /** DocumentLink 配置 */
46
- export interface DocumentLinkConfig<TExtra = unknown> {
47
- /** 是否启用 */
48
- enabled?: boolean
49
- /** 生成链接目标 URI */
50
- target?: (item: MatchItem<TExtra>, document: TextDocument) => Uri | undefined
51
- /** 生成 tooltip */
52
- tooltip?: (item: MatchItem<TExtra>, document: TextDocument) => string | undefined
53
- }
54
-
55
- /** Hover 配置 */
56
- export interface HoverConfig<TExtra = unknown> {
57
- /** 是否启用 */
58
- enabled?: boolean
59
- /** 生成 Hover 内容 */
60
- content: (item: MatchItem<TExtra>, document: TextDocument) => Hover | undefined
61
- }
62
-
63
- /** Completion 配置 */
64
- export interface CompletionConfig {
65
- /** 是否启用 */
66
- enabled?: boolean
67
- /** 触发字符 */
68
- triggerCharacters?: string[]
69
- /** 判断当前位置是否应该触发补全 */
70
- shouldTrigger?: (document: TextDocument, position: Position) => boolean
71
- /** 生成补全项列表 */
72
- items: (document: TextDocument, position: Position) => CompletionItem[] | undefined
73
- }
74
-
75
- /** Decoration 配置 */
76
- export interface DecorationConfig<TExtra = unknown> {
77
- /** 是否启用 */
78
- enabled?: boolean
79
- /** 装饰器类型样式 */
80
- style?: Parameters<typeof window.createTextEditorDecorationType>[0]
81
- /** 生成装饰器选项 */
82
- render: (item: MatchItem<TExtra>, document: TextDocument) => DecorationOptions | undefined
83
- }
84
-
85
- /** CodeLens 配置 */
86
- export interface CodeLensConfig<TExtra = unknown> {
87
- /** 是否启用 */
88
- enabled?: boolean
89
- /** 生成 CodeLens 列表 */
90
- lenses: (item: MatchItem<TExtra>, document: TextDocument) => CodeLens[] | undefined
91
- }
92
-
93
- /** 命令配置 */
94
- export interface CommandConfig {
95
- /** 命令 ID */
96
- id: string
97
- /** 命令处理函数 */
98
- handler: (...args: any[]) => any
99
- }
100
-
101
- /** 配置选项 */
102
- export interface PatternProviderOptions<TExtra = unknown> {
103
- /** 文档选择器 */
104
- selector?: DocumentSelector
105
- /** 文件过滤器,返回 false 则跳过该文档 */
106
- fileFilter?: (document: TextDocument) => boolean
107
- /** 收集匹配项的函数 */
108
- collect: CollectFn<TExtra>
109
- /** DocumentLink 配置 */
110
- documentLink?: DocumentLinkConfig<TExtra>
111
- /** Hover 配置 */
112
- hover?: HoverConfig<TExtra>
113
- /** Completion 配置 */
114
- completion?: CompletionConfig
115
- /** Decoration 配置 */
116
- decoration?: DecorationConfig<TExtra>
117
- /** CodeLens 配置 */
118
- codeLens?: CodeLensConfig<TExtra>
119
- /** 注册的命令 */
120
- commands?: CommandConfig[]
121
- }
122
-
123
- /** 返回值 */
124
- export interface PatternProviderReturn<TExtra = unknown> {
125
- /** 缓存的链接 */
126
- cache: WeakMap<Uri, Array<MatchItem<TExtra>>>
127
- /** 收集匹配项 */
128
- collect: (document: TextDocument, skipCache?: boolean) => Array<MatchItem<TExtra>>
129
- /** 装饰器类型(如果启用) */
130
- decorationType?: TextEditorDecorationType
131
- /** 注册所有 Provider,返回 disposables */
132
- register: () => Disposable[]
133
- }
134
-
135
- /** 创建基于正则的收集函数 - 无 context */
136
- export function createRegexCollector<TExtra = unknown>(
137
- regex: RegExp,
138
- transform?: (match: RegExpExecArray) => MatchItem<TExtra> | undefined
139
- ): CollectFn<TExtra>
140
-
141
- /** 创建基于正则的收集函数 - 带 context */
142
- export function createRegexCollector<TContext, TExtra = unknown>(
143
- regex: RegExp,
144
- setupContext: () => TContext,
145
- transform: (match: RegExpExecArray, context: TContext) => MatchItem<TExtra> | undefined
146
- ): CollectFn<TExtra>
147
-
148
- /** 创建基于正则的收集函数 */
149
- export function createRegexCollector<TContext = undefined, TExtra = unknown>(
150
- regex: RegExp,
151
- setupContextOrTransform?:
152
- | (() => TContext)
153
- | ((match: RegExpExecArray) => MatchItem<TExtra> | undefined),
154
- transform?: (match: RegExpExecArray, context: TContext) => MatchItem<TExtra> | undefined
155
- ): CollectFn<TExtra> {
156
- // 判断第二个参数是 setupContext 还是 transform
157
- const hasSetupContext = transform !== undefined
158
- const setupContext = hasSetupContext ? (setupContextOrTransform as () => TContext) : undefined
159
- const transformFn = hasSetupContext
160
- ? transform
161
- : (setupContextOrTransform as
162
- | ((match: RegExpExecArray) => MatchItem<TExtra> | undefined)
163
- | undefined)
164
-
165
- const context = setupContext?.()
166
-
167
- return (document: TextDocument) => {
168
- const items: Array<MatchItem<TExtra>> = []
169
- const text = document.getText()
170
- // 确保正则有 g 标志
171
- const globalRegex = new RegExp(
172
- regex.source,
173
- regex.flags.includes('g') ? regex.flags : `${regex.flags}g`
174
- )
175
-
176
- let match: RegExpExecArray | null
177
- while ((match = globalRegex.exec(text)) !== null) {
178
- if (transformFn) {
179
- const item = hasSetupContext
180
- ? (transformFn as (m: RegExpExecArray, c: TContext) => MatchItem<TExtra> | undefined)(
181
- match,
182
- context!
183
- )
184
- : (transformFn as (m: RegExpExecArray) => MatchItem<TExtra> | undefined)(match)
185
- if (item) items.push(item)
186
- } else {
187
- items.push({
188
- text: match[0],
189
- startIndex: match.index,
190
- endIndex: match.index + match[0].length
191
- })
192
- }
193
- }
194
- return items
195
- }
196
- }
197
-
198
- /** 从匹配项创建 Range */
199
- export function createRange(document: TextDocument, item: MatchItem): Range {
200
- return new Range(document.positionAt(item.startIndex), document.positionAt(item.endIndex))
201
- }
202
-
203
- /** 获取匹配项的 extra 数据 */
204
- export function getItemExtra<TExtra>(link: DocumentLink): TExtra | undefined {
205
- return (link as any).__extra as TExtra
206
- }
207
-
208
- /** 设置匹配项的 extra 数据到 DocumentLink */
209
- function setItemExtra<TExtra>(link: DocumentLink, extra: TExtra): void {
210
- ;(link as any).__extra = extra
211
- }
212
-
213
- /**
214
- * 定义模式匹配 Provider,统一管理 DocumentLink、Hover、Completion、Decoration、CodeLens 等功能
215
- */
216
- export function definePatternProvider<TExtra = unknown>(
217
- options: PatternProviderOptions<TExtra>
218
- ): PatternProviderReturn<TExtra> {
219
- const {
220
- selector = { scheme: 'file' },
221
- fileFilter = () => true,
222
- collect: collectFn,
223
- documentLink,
224
- hover,
225
- completion,
226
- decoration,
227
- codeLens,
228
- commands: commandsConfig
229
- } = options
230
-
231
- const cache = new WeakMap<Uri, Array<MatchItem<TExtra>>>()
232
-
233
- // 带缓存的收集函数
234
- function collect(document: TextDocument, skipCache = false): Array<MatchItem<TExtra>> {
235
- if (!skipCache && cache.has(document.uri)) {
236
- return cache.get(document.uri)!
237
- }
238
- const items = collectFn(document, skipCache)
239
- cache.set(document.uri, items)
240
- return items
241
- }
242
-
243
- // 创建装饰器类型(如果启用)
244
- const decorationType =
245
- decoration?.enabled && decoration.style
246
- ? window.createTextEditorDecorationType(decoration.style)
247
- : undefined
248
-
249
- // DocumentLink Provider
250
- function createDocumentLinkProvider(): DocumentLinkProvider {
251
- return {
252
- provideDocumentLinks(document: TextDocument): ProviderResult<DocumentLink[]> {
253
- if (!fileFilter(document)) return
254
- const items = collect(document)
255
- return items.map(function (item) {
256
- const range = createRange(document, item)
257
- const target = documentLink?.target?.(item, document)
258
- const link = new DocumentLink(range, target)
259
- link.tooltip = documentLink?.tooltip?.(item, document)
260
- setItemExtra(link, item.extra)
261
- return link
262
- })
263
- }
264
- }
265
- }
266
-
267
- // Hover Provider
268
- function createHoverProvider(): HoverProvider {
269
- return {
270
- provideHover(document: TextDocument, position: Position): ProviderResult<Hover> {
271
- if (!fileFilter(document)) return
272
- const items = collect(document)
273
-
274
- for (const item of items) {
275
- const range = createRange(document, item)
276
- if (!range.contains(position)) continue
277
- return hover?.content(item, document)
278
- }
279
- }
280
- }
281
- }
282
-
283
- // Completion Provider
284
- function createCompletionProvider(): CompletionItemProvider {
285
- return {
286
- provideCompletionItems(
287
- document: TextDocument,
288
- position: Position
289
- ): ProviderResult<CompletionItem[] | CompletionList<CompletionItem>> {
290
- if (!fileFilter(document)) return
291
- if (completion?.shouldTrigger && !completion.shouldTrigger(document, position)) return
292
- return completion?.items(document, position)
293
- }
294
- }
295
- }
296
-
297
- // CodeLens Provider
298
- function createCodeLensProvider(): CodeLensProvider {
299
- return {
300
- provideCodeLenses(document: TextDocument): ProviderResult<CodeLens[]> {
301
- if (!fileFilter(document)) return
302
- const items = collect(document)
303
- return items.flatMap(item => codeLens?.lenses(item, document) ?? [])
304
- }
305
- }
306
- }
307
-
308
- // 注册函数
309
- function register(): Disposable[] {
310
- const disposables: Disposable[] = []
311
-
312
- // 注册命令
313
- if (commandsConfig?.length) {
314
- for (const cmd of commandsConfig) {
315
- disposables.push(commands.registerCommand(cmd.id, cmd.handler))
316
- }
317
- }
318
-
319
- // 注册 DocumentLink Provider
320
- if (documentLink?.enabled !== false) {
321
- disposables.push(
322
- languages.registerDocumentLinkProvider(selector, createDocumentLinkProvider())
323
- )
324
- }
325
-
326
- // 注册 Hover Provider
327
- if (hover?.enabled) {
328
- disposables.push(languages.registerHoverProvider(selector, createHoverProvider()))
329
- }
330
-
331
- // 注册 Completion Provider
332
- if (completion?.enabled) {
333
- disposables.push(
334
- languages.registerCompletionItemProvider(
335
- selector,
336
- createCompletionProvider(),
337
- ...(completion.triggerCharacters ?? [])
338
- )
339
- )
340
- }
341
-
342
- // 注册 CodeLens Provider
343
- if (codeLens?.enabled) {
344
- disposables.push(languages.registerCodeLensProvider(selector, createCodeLensProvider()))
345
- }
346
-
347
- // 注册 Decoration
348
- if (decoration?.enabled && decorationType) {
349
- const updateDecorations = (editor: TextEditor | undefined) => {
350
- if (!editor || !fileFilter(editor.document)) return
351
- const items = collect(editor.document, true)
352
- const decorations = items
353
- .map(item => decoration.render(item, editor.document))
354
- .filter((opt): opt is DecorationOptions => opt !== undefined)
355
- editor.setDecorations(decorationType, decorations)
356
- }
357
-
358
- // 初始更新
359
- updateDecorations(window.activeTextEditor)
360
-
361
- disposables.push(
362
- // 监听编辑器切换
363
- window.onDidChangeActiveTextEditor(updateDecorations),
364
- // 监听文档变化
365
- workspace.onDidChangeTextDocument(e => {
366
- if (window.activeTextEditor?.document === e.document) {
367
- updateDecorations(window.activeTextEditor)
368
- }
369
- })
370
- )
371
- }
372
-
373
- return disposables
374
- }
375
-
376
- return {
377
- cache,
378
- collect,
379
- decorationType,
380
- register
381
- }
382
- }
383
-
384
- /** Vue 文件过滤器 */
385
- export const vueFileFilter = (document: TextDocument) => document.fileName.endsWith('.vue')
386
- export function createExtFilter(...exts: string[]) {
387
- return (document: TextDocument) => exts.some(ext => document.fileName.endsWith(ext))
388
- }
package/tsdown.config.ts DELETED
@@ -1,22 +0,0 @@
1
- import { defineConfig, type UserConfig } from 'tsdown'
2
-
3
- const sharedConfig: UserConfig = {
4
- entry: ['src/index.ts'],
5
- platform: 'node',
6
- external: ['vscode']
7
- }
8
-
9
- export default defineConfig([
10
- {
11
- ...sharedConfig,
12
- name: 'lib-bundle:esm',
13
- format: 'esm',
14
- dts: true
15
- },
16
- {
17
- ...sharedConfig,
18
- name: 'lib-bundle:cjs',
19
- format: 'cjs',
20
- dts: false
21
- }
22
- ])