mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-08 10:56:15 -08:00
fix(asr): validate generated editor declarations semantically
This commit is contained in:
1 parent
c723c70251
commit
1117107032
4 files changed
+97
-23
No files matched your search
+47
-22
@@ -1,26 +1,51 @@
|
||||
interface AudioChunk {
|
||||
pcm: ArrayBuffer
|
||||
wav: ArrayBuffer
|
||||
// Generated from the package public declaration by yarn build:ts. Do not edit.
|
||||
/* eslint-disable ts/no-redeclare -- Callable and public type namespace intentionally merge. */
|
||||
declare namespace artplayerPluginAsrDefinitions {
|
||||
export interface AudioChunk {
|
||||
pcm: ArrayBuffer
|
||||
wav: ArrayBuffer
|
||||
}
|
||||
export interface AsrPluginOption {
|
||||
length?: number
|
||||
interval?: number
|
||||
sampleRate?: number
|
||||
autoHideTimeout?: number
|
||||
onAudioChunk?: (chunk: AudioChunk) => void | Promise<void>
|
||||
}
|
||||
export interface AsrPluginInstance {
|
||||
name: 'artplayerPluginAsr'
|
||||
stop: () => void
|
||||
hide: () => void
|
||||
append: (subtitle: string) => void
|
||||
}
|
||||
/** Historical factory shape, including void stop and callback results. */
|
||||
export type Factory = (option?: AsrPluginOption) => (art: Artplayer) => AsrPluginInstance
|
||||
/** Accurate asynchronous view available through the /runtime entry. */
|
||||
export interface RuntimeOption extends Omit<AsrPluginOption, 'onAudioChunk'> {
|
||||
/** Capture the media stream without taking ownership of its playback route. */
|
||||
audioInput?: {
|
||||
type: 'capture'
|
||||
}
|
||||
onAudioChunk?: (chunk: AudioChunk) => string | void | null | Promise<string | void | null>
|
||||
}
|
||||
export interface RuntimeResult extends Omit<AsrPluginInstance, 'stop'> {
|
||||
stop: () => Promise<void>
|
||||
}
|
||||
export interface RuntimeFactory {
|
||||
(option?: RuntimeOption): (art: Artplayer) => RuntimeResult
|
||||
readonly default: RuntimeFactory
|
||||
}
|
||||
export function artplayerPluginAsr(option?: AsrPluginOption): (art: Artplayer) => AsrPluginInstance
|
||||
}
|
||||
|
||||
interface AsrPluginOption {
|
||||
length?: number
|
||||
interval?: number
|
||||
sampleRate?: number
|
||||
autoHideTimeout?: number
|
||||
onAudioChunk?: (chunk: AudioChunk) => void | Promise<void>
|
||||
declare const artplayerPluginAsr: typeof artplayerPluginAsrDefinitions.artplayerPluginAsr
|
||||
declare namespace artplayerPluginAsr {
|
||||
export type AudioChunk = artplayerPluginAsrDefinitions.AudioChunk
|
||||
export type AsrPluginOption = artplayerPluginAsrDefinitions.AsrPluginOption
|
||||
export type AsrPluginInstance = artplayerPluginAsrDefinitions.AsrPluginInstance
|
||||
export type Factory = artplayerPluginAsrDefinitions.Factory
|
||||
export type RuntimeOption = artplayerPluginAsrDefinitions.RuntimeOption
|
||||
export type RuntimeResult = artplayerPluginAsrDefinitions.RuntimeResult
|
||||
export type RuntimeFactory = artplayerPluginAsrDefinitions.RuntimeFactory
|
||||
}
|
||||
|
||||
interface AsrPluginInstance {
|
||||
name: 'artplayerPluginAsr'
|
||||
stop: () => void
|
||||
hide: () => void
|
||||
append: (subtitle: string) => void
|
||||
}
|
||||
|
||||
declare function artplayerPluginAsr(option?: AsrPluginOption): (art: Artplayer) => AsrPluginInstance
|
||||
|
||||
export default artplayerPluginAsr
|
||||
|
||||
export = artplayerPluginAsr
|
||||
export as namespace artplayerPluginAsr;
|
||||
@@ -0,0 +1,19 @@
|
||||
# PKG-ASR-05 编辑器生成修复检查点
|
||||
|
||||
完整执行 `yarn build:ts` 时发现 ASR 尚走旧文本拼接路径。新增的公开命名类型和
|
||||
原有 `export default` 被直接保留,再拼接 `export =`,在严格独立编辑器编译中
|
||||
产生 TS2309。此问题已修复,不只登记后推迟处理。
|
||||
|
||||
ASR 现在使用现有语义生成器:公共类型归入全局命名空间,默认工厂仍保持历史
|
||||
同步声明,准确 RuntimeOption/RuntimeResult/RuntimeFactory 作为独立类型可用。
|
||||
运行时源码、npm 根声明及播放器行为没有改变。
|
||||
|
||||
`test/editor-types.test.js` 重建旧文本生成结果并断言 TS2309;对新声明验证普通
|
||||
工厂替换、历史 void stop、精确异步 stop 与显式 capture 输入。TS 5.9.3 和 4.3.5
|
||||
均在 strict、skipLibCheck=false 下通过,并各拒绝三个指定反例。生成产物与
|
||||
格式化结果逐字核对。两项编辑器测试通过,日志为
|
||||
`refactor/.cache/asr-editor-tests.log`,生成日志为
|
||||
`refactor/.cache/asr-editor-generation.log`。
|
||||
|
||||
此修复作为 ASR-05 的独立本地检查点提交;ASR-05 的真实设备等剩余验证仍未完成。
|
||||
未将静态声明测试描述为新的浏览器播放证据,也未推送或发布。
|
||||
+1
-1
@@ -53,7 +53,7 @@ console.log(`✨ Built ${artplayerTSoutput}`);
|
||||
const type = pluginsTS[index]
|
||||
const { name, file } = parsePluginInfo(type)
|
||||
const source = String(fs.readFileSync(type))
|
||||
const semanticPlugin = ['artplayerPluginMultipleSubtitles', 'artplayerPluginVttThumbnail', 'artplayerPluginHlsControl', 'artplayerPluginAudioTrack', 'artplayerPluginDashControl', 'artplayerPluginAds', 'artplayerPluginAmbilight', 'artplayerProxyCanvas', 'artplayerProxyMediabunny', 'artplayerPluginDocumentPip', 'ArtplayerToolIframe', 'ArtplayerToolThumbnail'].includes(name)
|
||||
const semanticPlugin = ['artplayerPluginAsr', 'artplayerPluginMultipleSubtitles', 'artplayerPluginVttThumbnail', 'artplayerPluginHlsControl', 'artplayerPluginAudioTrack', 'artplayerPluginDashControl', 'artplayerPluginAds', 'artplayerPluginAmbilight', 'artplayerProxyCanvas', 'artplayerProxyMediabunny', 'artplayerPluginDocumentPip', 'ArtplayerToolIframe', 'ArtplayerToolThumbnail'].includes(name)
|
||||
const localTypes = name === 'artplayerProxyMediabunny' ? { './media': fs.readFileSync(path.join(path.dirname(type), 'media.d.ts'), 'utf8') } : {}
|
||||
const code = semanticPlugin
|
||||
? generatePluginEditorDeclaration(source, name, localTypes)
|
||||
|
||||
@@ -5,6 +5,7 @@ import { test } from 'node:test'
|
||||
import { ESLint } from 'eslint'
|
||||
import compat from 'typescript-compat'
|
||||
import { asGlobalDeclaration, checkCoreEditorDeclaration, generateCoreEditorDeclaration } from '../scripts/editor-types.mjs'
|
||||
import { checkPluginEditorDeclaration, generatePluginEditorDeclaration } from '../scripts/plugin-editor-types.mjs'
|
||||
|
||||
test('editor declarations are reproducible, standalone and preserve constructor/named types in both compilers', async () => {
|
||||
const generated = generateCoreEditorDeclaration()
|
||||
@@ -19,3 +20,32 @@ test('editor declarations are reproducible, standalone and preserve constructor/
|
||||
assert(checkCoreEditorDeclaration(corrupted).some(diagnostic => diagnostic.code === 2304), 'Invalid output must not be hidden by skipLibCheck')
|
||||
assert.throws(() => asGlobalDeclaration('export { default } from "./missing"', 'Artplayer'), /unresolved exports/)
|
||||
})
|
||||
|
||||
test('ASR editor generation supports named types without mixing default and export assignment', async () => {
|
||||
const source = fs.readFileSync('packages/artplayer-plugin-asr/types/artplayer-plugin-asr.d.ts', 'utf8')
|
||||
const core = fs.readFileSync('docs/assets/ts/artplayer.d.ts', 'utf8')
|
||||
const old = `${source.replace(/^import.*$/gim, '')}\nexport = artplayerPluginAsr;\nexport as namespace artplayerPluginAsr;\n`
|
||||
assert(checkPluginEditorDeclaration(old, core).some(item => item.code === 2309), 'The old textual generator must reproduce its conflicting export assignment')
|
||||
const generated = generatePluginEditorDeclaration(source, 'artplayerPluginAsr')
|
||||
const file = 'docs/assets/ts/artplayer-plugin-asr.d.ts'
|
||||
const [formatted] = await new ESLint({ fix: true, fixTypes: ['layout'] }).lintText(generated, { filePath: file })
|
||||
assert.equal(formatted.errorCount, 0)
|
||||
assert.equal(fs.readFileSync(file, 'utf8').replaceAll('\r\n', '\n'), formatted.output || generated)
|
||||
const consumer = `declare const art: Artplayer;
|
||||
const factory: typeof artplayerPluginAsr = () => () => ({ name: 'artplayerPluginAsr', stop() {}, hide() {}, append(_text: string) {} });
|
||||
const oldResult: void = factory()(art).stop();
|
||||
const option: artplayerPluginAsr.RuntimeOption = { audioInput: { type: 'capture' }, onAudioChunk: async () => 'subtitle' };
|
||||
declare const runtime: artplayerPluginAsr.RuntimeFactory;
|
||||
const stopped: Promise<void> = runtime(option)(art).stop();
|
||||
// @ts-expect-error Root stop retains historical void type.
|
||||
const rootPromise: Promise<void> = artplayerPluginAsr()(art).stop();
|
||||
// @ts-expect-error Capture input is runtime-only.
|
||||
artplayerPluginAsr({ audioInput: { type: 'capture' } });
|
||||
// @ts-expect-error Unknown capture mode.
|
||||
const invalid: artplayerPluginAsr.RuntimeOption = { audioInput: { type: 'direct' } };
|
||||
void [oldResult, stopped, rootPromise, invalid];`
|
||||
for (const compiler of [undefined, compat]) {
|
||||
assert.deepEqual(checkPluginEditorDeclaration(generated, core, consumer, compiler), [])
|
||||
assert.equal(checkPluginEditorDeclaration(generated, core, consumer.replaceAll(/\/\/ @ts-expect-error[^\n]*\n/g, ''), compiler).length, 3)
|
||||
}
|
||||
})
|
||||
Reference in new issue
Block a user