@sweet-player/core 0.2.0
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/LICENSE +21 -0
- package/dist/index.cjs +1551 -0
- package/dist/index.d.cts +211 -0
- package/dist/index.d.ts +211 -0
- package/dist/index.js +1513 -0
- package/dist/sweet-player.global.js +540 -0
- package/package.json +52 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
interface QualityLevel {
|
|
2
|
+
/** 显示名称,如 "1080P" */
|
|
3
|
+
label: string;
|
|
4
|
+
/** 业务自定义值,切换时原样回传给 onQualityChange */
|
|
5
|
+
value: string | number;
|
|
6
|
+
/** 可选:该画质对应的播放地址(传入时切换会自动 load) */
|
|
7
|
+
src?: string;
|
|
8
|
+
}
|
|
9
|
+
interface AudioTrackInfo {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string | number;
|
|
12
|
+
}
|
|
13
|
+
type AspectRatio = 'original' | '21:9' | '16:9' | '4:3' | (string & {});
|
|
14
|
+
interface LongSeekOptions {
|
|
15
|
+
/** 长按阶梯步长(秒),按住时逐级升档,默认 [10, 30, 60] */
|
|
16
|
+
steps?: number[];
|
|
17
|
+
/** 每隔多少毫秒升一档,默认 2000 */
|
|
18
|
+
stepUpInterval?: number;
|
|
19
|
+
}
|
|
20
|
+
/** 播放器插件:apply 在实例化末尾调用,可返回清理函数(destroy 时执行) */
|
|
21
|
+
interface SweetPlayerPlugin {
|
|
22
|
+
name: string;
|
|
23
|
+
apply(player: SweetPlayerLike): void | (() => void);
|
|
24
|
+
}
|
|
25
|
+
/** 插件拿到的最小接口(即 SweetPlayer 实例,避免类型循环引用) */
|
|
26
|
+
interface SweetPlayerLike {
|
|
27
|
+
container: HTMLElement;
|
|
28
|
+
video: HTMLVideoElement;
|
|
29
|
+
on<K extends keyof PlayerEventMap>(event: K, fn: (payload: PlayerEventMap[K]) => void): () => void;
|
|
30
|
+
}
|
|
31
|
+
interface SweetPlayerOptions {
|
|
32
|
+
/** 挂载容器,元素或选择器 */
|
|
33
|
+
container: HTMLElement | string;
|
|
34
|
+
/** 视频地址,.m3u8 走 hls.js,其余直接赋给 video */
|
|
35
|
+
src: string;
|
|
36
|
+
/** 左上角标题 */
|
|
37
|
+
title?: string;
|
|
38
|
+
/** 视频唯一 ID:传入后自动记忆/恢复播放进度(断点续播) */
|
|
39
|
+
id?: string;
|
|
40
|
+
autoplay?: boolean;
|
|
41
|
+
muted?: boolean;
|
|
42
|
+
/** 初始音量 0-100,默认 100 */
|
|
43
|
+
volume?: number;
|
|
44
|
+
/** 快进快退步长(秒),默认 10 */
|
|
45
|
+
seekStep?: number;
|
|
46
|
+
/** 长按快进快退配置 */
|
|
47
|
+
longSeek?: LongSeekOptions;
|
|
48
|
+
/** 倍速档位,默认 [0.5, 1, 1.5, 2] */
|
|
49
|
+
playbackRates?: number[];
|
|
50
|
+
/** 画面比例档位,默认 ['original', '21:9', '16:9', '4:3'] */
|
|
51
|
+
aspectRatios?: AspectRatio[];
|
|
52
|
+
/** 画质列表(预留),传入后画质菜单可选 */
|
|
53
|
+
qualities?: QualityLevel[];
|
|
54
|
+
/** 音轨列表(预留) */
|
|
55
|
+
audioTracks?: AudioTrackInfo[];
|
|
56
|
+
/**
|
|
57
|
+
* 自动从 hls.js 读取画质/音轨填充菜单(默认 true)。
|
|
58
|
+
* 业务传入 qualities/audioTracks 时以业务列表为准。
|
|
59
|
+
*/
|
|
60
|
+
autoQuality?: boolean;
|
|
61
|
+
/** 记忆音量/静音/倍速到 localStorage(默认 true) */
|
|
62
|
+
persist?: boolean;
|
|
63
|
+
/** 播放结束后自动播放下一个:true = 5 秒倒计时,数字 = 自定义秒数(需配合 onNext) */
|
|
64
|
+
autoNext?: boolean | number;
|
|
65
|
+
/** UI 语言,默认 'zh-CN',内置 'en';可用 registerLocale 注册其他语言 */
|
|
66
|
+
locale?: string;
|
|
67
|
+
/** 覆盖部分 UI 文案 */
|
|
68
|
+
localeStrings?: Record<string, string>;
|
|
69
|
+
/** 插件列表,实例化末尾依次 apply */
|
|
70
|
+
plugins?: SweetPlayerPlugin[];
|
|
71
|
+
/** 透传给 hls.js 的配置 */
|
|
72
|
+
hlsConfig?: Record<string, unknown>;
|
|
73
|
+
/** 点击"上一个"回调(预留) */
|
|
74
|
+
onPrev?: () => void;
|
|
75
|
+
/** 点击"下一个"回调(预留) */
|
|
76
|
+
onNext?: () => void;
|
|
77
|
+
/** 画质切换回调(预留) */
|
|
78
|
+
onQualityChange?: (quality: QualityLevel) => void;
|
|
79
|
+
/** 音轨切换回调(预留) */
|
|
80
|
+
onAudioTrackChange?: (track: AudioTrackInfo) => void;
|
|
81
|
+
}
|
|
82
|
+
interface PlayerEventMap {
|
|
83
|
+
ready: void;
|
|
84
|
+
play: void;
|
|
85
|
+
pause: void;
|
|
86
|
+
ended: void;
|
|
87
|
+
timeupdate: {
|
|
88
|
+
currentTime: number;
|
|
89
|
+
duration: number;
|
|
90
|
+
};
|
|
91
|
+
ratechange: number;
|
|
92
|
+
volumechange: {
|
|
93
|
+
volume: number;
|
|
94
|
+
muted: boolean;
|
|
95
|
+
};
|
|
96
|
+
fullscreenchange: boolean;
|
|
97
|
+
pipchange: boolean;
|
|
98
|
+
aspectratiochange: AspectRatio;
|
|
99
|
+
qualitychange: QualityLevel;
|
|
100
|
+
audiotrackchange: AudioTrackInfo;
|
|
101
|
+
error: {
|
|
102
|
+
type: string;
|
|
103
|
+
detail?: unknown;
|
|
104
|
+
};
|
|
105
|
+
destroy: void;
|
|
106
|
+
}
|
|
107
|
+
type PlayerEventName = keyof PlayerEventMap;
|
|
108
|
+
|
|
109
|
+
declare class SweetPlayer {
|
|
110
|
+
readonly container: HTMLElement;
|
|
111
|
+
readonly video: HTMLVideoElement;
|
|
112
|
+
private emitter;
|
|
113
|
+
private media;
|
|
114
|
+
private keyboard;
|
|
115
|
+
private gestures;
|
|
116
|
+
private controls;
|
|
117
|
+
private osd;
|
|
118
|
+
private stats;
|
|
119
|
+
private state;
|
|
120
|
+
private i18n;
|
|
121
|
+
private options;
|
|
122
|
+
private hideTimer;
|
|
123
|
+
private clickTimer;
|
|
124
|
+
private progressTimer;
|
|
125
|
+
private titleClicks;
|
|
126
|
+
private lastTitleClick;
|
|
127
|
+
private currentRatio;
|
|
128
|
+
/** 画质/音轨菜单当前是否由 hls.js 自动接管(业务 setQualities 会关闭) */
|
|
129
|
+
private hlsManagedQuality;
|
|
130
|
+
private hlsManagedAudio;
|
|
131
|
+
private disposers;
|
|
132
|
+
private pluginCleanups;
|
|
133
|
+
private destroyed;
|
|
134
|
+
constructor(options: SweetPlayerOptions);
|
|
135
|
+
play(): Promise<void>;
|
|
136
|
+
pause(): void;
|
|
137
|
+
toggle(): void;
|
|
138
|
+
seek(time: number): void;
|
|
139
|
+
/** 相对跳转;showOsd 为 false 时不显示中央提示 */
|
|
140
|
+
seekBy(delta: number, showOsd?: boolean): void;
|
|
141
|
+
setRate(rate: number): void;
|
|
142
|
+
/** 0-100 */
|
|
143
|
+
setVolume(volume: number): void;
|
|
144
|
+
setMuted(muted: boolean): void;
|
|
145
|
+
setAspectRatio(ratio: AspectRatio): void;
|
|
146
|
+
get aspectRatio(): AspectRatio;
|
|
147
|
+
/** 运行时更新画质列表 */
|
|
148
|
+
setQualities(qualities: QualityLevel[], active?: QualityLevel): void;
|
|
149
|
+
/** 运行时更新音轨列表 */
|
|
150
|
+
setAudioTracks(tracks: AudioTrackInfo[], active?: AudioTrackInfo): void;
|
|
151
|
+
toggleFullscreen(): Promise<void>;
|
|
152
|
+
get fullscreen(): boolean;
|
|
153
|
+
togglePip(): Promise<void>;
|
|
154
|
+
load(src: string): void;
|
|
155
|
+
setTitle(title: string): void;
|
|
156
|
+
/** 安装插件;返回本次插件的卸载函数 */
|
|
157
|
+
use(plugin: SweetPlayerPlugin): () => void;
|
|
158
|
+
on<K extends keyof PlayerEventMap>(event: K, fn: (payload: PlayerEventMap[K]) => void): () => void;
|
|
159
|
+
off<K extends keyof PlayerEventMap>(event: K, fn: (payload: PlayerEventMap[K]) => void): void;
|
|
160
|
+
destroy(): void;
|
|
161
|
+
private applyHlsLevels;
|
|
162
|
+
private applyHlsAudioTracks;
|
|
163
|
+
private handleQualitySelect;
|
|
164
|
+
private handleAudioTrackSelect;
|
|
165
|
+
private bindPersistence;
|
|
166
|
+
private bindProgressMemory;
|
|
167
|
+
private saveProgressNow;
|
|
168
|
+
private handleTitleClick;
|
|
169
|
+
private bindMediaEvents;
|
|
170
|
+
private showErrorState;
|
|
171
|
+
private showErrorStateUi;
|
|
172
|
+
private showControls;
|
|
173
|
+
private hideControlsNow;
|
|
174
|
+
private scheduleHide;
|
|
175
|
+
private bindActivityTracking;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface LocaleStrings {
|
|
179
|
+
play: string;
|
|
180
|
+
pause: string;
|
|
181
|
+
playPause: string;
|
|
182
|
+
prev: string;
|
|
183
|
+
next: string;
|
|
184
|
+
seekBack: string;
|
|
185
|
+
seekForward: string;
|
|
186
|
+
speed: string;
|
|
187
|
+
quality: string;
|
|
188
|
+
qualityAuto: string;
|
|
189
|
+
aspectRatio: string;
|
|
190
|
+
ratioOriginal: string;
|
|
191
|
+
audioTrack: string;
|
|
192
|
+
mute: string;
|
|
193
|
+
fullscreen: string;
|
|
194
|
+
pip: string;
|
|
195
|
+
empty: string;
|
|
196
|
+
closeStats: string;
|
|
197
|
+
seconds: string;
|
|
198
|
+
volume: string;
|
|
199
|
+
muted: string;
|
|
200
|
+
replay: string;
|
|
201
|
+
playNext: string;
|
|
202
|
+
autoNextIn: string;
|
|
203
|
+
cancel: string;
|
|
204
|
+
loadError: string;
|
|
205
|
+
retry: string;
|
|
206
|
+
}
|
|
207
|
+
type LocaleName = 'zh-CN' | 'en' | (string & {});
|
|
208
|
+
/** 注册自定义语言包(全局) */
|
|
209
|
+
declare function registerLocale(name: string, strings: LocaleStrings): void;
|
|
210
|
+
|
|
211
|
+
export { type AspectRatio, type AudioTrackInfo, type LocaleName, type LocaleStrings, type LongSeekOptions, type PlayerEventMap, type PlayerEventName, type QualityLevel, SweetPlayer, type SweetPlayerLike, type SweetPlayerOptions, type SweetPlayerPlugin, registerLocale };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
interface QualityLevel {
|
|
2
|
+
/** 显示名称,如 "1080P" */
|
|
3
|
+
label: string;
|
|
4
|
+
/** 业务自定义值,切换时原样回传给 onQualityChange */
|
|
5
|
+
value: string | number;
|
|
6
|
+
/** 可选:该画质对应的播放地址(传入时切换会自动 load) */
|
|
7
|
+
src?: string;
|
|
8
|
+
}
|
|
9
|
+
interface AudioTrackInfo {
|
|
10
|
+
label: string;
|
|
11
|
+
value: string | number;
|
|
12
|
+
}
|
|
13
|
+
type AspectRatio = 'original' | '21:9' | '16:9' | '4:3' | (string & {});
|
|
14
|
+
interface LongSeekOptions {
|
|
15
|
+
/** 长按阶梯步长(秒),按住时逐级升档,默认 [10, 30, 60] */
|
|
16
|
+
steps?: number[];
|
|
17
|
+
/** 每隔多少毫秒升一档,默认 2000 */
|
|
18
|
+
stepUpInterval?: number;
|
|
19
|
+
}
|
|
20
|
+
/** 播放器插件:apply 在实例化末尾调用,可返回清理函数(destroy 时执行) */
|
|
21
|
+
interface SweetPlayerPlugin {
|
|
22
|
+
name: string;
|
|
23
|
+
apply(player: SweetPlayerLike): void | (() => void);
|
|
24
|
+
}
|
|
25
|
+
/** 插件拿到的最小接口(即 SweetPlayer 实例,避免类型循环引用) */
|
|
26
|
+
interface SweetPlayerLike {
|
|
27
|
+
container: HTMLElement;
|
|
28
|
+
video: HTMLVideoElement;
|
|
29
|
+
on<K extends keyof PlayerEventMap>(event: K, fn: (payload: PlayerEventMap[K]) => void): () => void;
|
|
30
|
+
}
|
|
31
|
+
interface SweetPlayerOptions {
|
|
32
|
+
/** 挂载容器,元素或选择器 */
|
|
33
|
+
container: HTMLElement | string;
|
|
34
|
+
/** 视频地址,.m3u8 走 hls.js,其余直接赋给 video */
|
|
35
|
+
src: string;
|
|
36
|
+
/** 左上角标题 */
|
|
37
|
+
title?: string;
|
|
38
|
+
/** 视频唯一 ID:传入后自动记忆/恢复播放进度(断点续播) */
|
|
39
|
+
id?: string;
|
|
40
|
+
autoplay?: boolean;
|
|
41
|
+
muted?: boolean;
|
|
42
|
+
/** 初始音量 0-100,默认 100 */
|
|
43
|
+
volume?: number;
|
|
44
|
+
/** 快进快退步长(秒),默认 10 */
|
|
45
|
+
seekStep?: number;
|
|
46
|
+
/** 长按快进快退配置 */
|
|
47
|
+
longSeek?: LongSeekOptions;
|
|
48
|
+
/** 倍速档位,默认 [0.5, 1, 1.5, 2] */
|
|
49
|
+
playbackRates?: number[];
|
|
50
|
+
/** 画面比例档位,默认 ['original', '21:9', '16:9', '4:3'] */
|
|
51
|
+
aspectRatios?: AspectRatio[];
|
|
52
|
+
/** 画质列表(预留),传入后画质菜单可选 */
|
|
53
|
+
qualities?: QualityLevel[];
|
|
54
|
+
/** 音轨列表(预留) */
|
|
55
|
+
audioTracks?: AudioTrackInfo[];
|
|
56
|
+
/**
|
|
57
|
+
* 自动从 hls.js 读取画质/音轨填充菜单(默认 true)。
|
|
58
|
+
* 业务传入 qualities/audioTracks 时以业务列表为准。
|
|
59
|
+
*/
|
|
60
|
+
autoQuality?: boolean;
|
|
61
|
+
/** 记忆音量/静音/倍速到 localStorage(默认 true) */
|
|
62
|
+
persist?: boolean;
|
|
63
|
+
/** 播放结束后自动播放下一个:true = 5 秒倒计时,数字 = 自定义秒数(需配合 onNext) */
|
|
64
|
+
autoNext?: boolean | number;
|
|
65
|
+
/** UI 语言,默认 'zh-CN',内置 'en';可用 registerLocale 注册其他语言 */
|
|
66
|
+
locale?: string;
|
|
67
|
+
/** 覆盖部分 UI 文案 */
|
|
68
|
+
localeStrings?: Record<string, string>;
|
|
69
|
+
/** 插件列表,实例化末尾依次 apply */
|
|
70
|
+
plugins?: SweetPlayerPlugin[];
|
|
71
|
+
/** 透传给 hls.js 的配置 */
|
|
72
|
+
hlsConfig?: Record<string, unknown>;
|
|
73
|
+
/** 点击"上一个"回调(预留) */
|
|
74
|
+
onPrev?: () => void;
|
|
75
|
+
/** 点击"下一个"回调(预留) */
|
|
76
|
+
onNext?: () => void;
|
|
77
|
+
/** 画质切换回调(预留) */
|
|
78
|
+
onQualityChange?: (quality: QualityLevel) => void;
|
|
79
|
+
/** 音轨切换回调(预留) */
|
|
80
|
+
onAudioTrackChange?: (track: AudioTrackInfo) => void;
|
|
81
|
+
}
|
|
82
|
+
interface PlayerEventMap {
|
|
83
|
+
ready: void;
|
|
84
|
+
play: void;
|
|
85
|
+
pause: void;
|
|
86
|
+
ended: void;
|
|
87
|
+
timeupdate: {
|
|
88
|
+
currentTime: number;
|
|
89
|
+
duration: number;
|
|
90
|
+
};
|
|
91
|
+
ratechange: number;
|
|
92
|
+
volumechange: {
|
|
93
|
+
volume: number;
|
|
94
|
+
muted: boolean;
|
|
95
|
+
};
|
|
96
|
+
fullscreenchange: boolean;
|
|
97
|
+
pipchange: boolean;
|
|
98
|
+
aspectratiochange: AspectRatio;
|
|
99
|
+
qualitychange: QualityLevel;
|
|
100
|
+
audiotrackchange: AudioTrackInfo;
|
|
101
|
+
error: {
|
|
102
|
+
type: string;
|
|
103
|
+
detail?: unknown;
|
|
104
|
+
};
|
|
105
|
+
destroy: void;
|
|
106
|
+
}
|
|
107
|
+
type PlayerEventName = keyof PlayerEventMap;
|
|
108
|
+
|
|
109
|
+
declare class SweetPlayer {
|
|
110
|
+
readonly container: HTMLElement;
|
|
111
|
+
readonly video: HTMLVideoElement;
|
|
112
|
+
private emitter;
|
|
113
|
+
private media;
|
|
114
|
+
private keyboard;
|
|
115
|
+
private gestures;
|
|
116
|
+
private controls;
|
|
117
|
+
private osd;
|
|
118
|
+
private stats;
|
|
119
|
+
private state;
|
|
120
|
+
private i18n;
|
|
121
|
+
private options;
|
|
122
|
+
private hideTimer;
|
|
123
|
+
private clickTimer;
|
|
124
|
+
private progressTimer;
|
|
125
|
+
private titleClicks;
|
|
126
|
+
private lastTitleClick;
|
|
127
|
+
private currentRatio;
|
|
128
|
+
/** 画质/音轨菜单当前是否由 hls.js 自动接管(业务 setQualities 会关闭) */
|
|
129
|
+
private hlsManagedQuality;
|
|
130
|
+
private hlsManagedAudio;
|
|
131
|
+
private disposers;
|
|
132
|
+
private pluginCleanups;
|
|
133
|
+
private destroyed;
|
|
134
|
+
constructor(options: SweetPlayerOptions);
|
|
135
|
+
play(): Promise<void>;
|
|
136
|
+
pause(): void;
|
|
137
|
+
toggle(): void;
|
|
138
|
+
seek(time: number): void;
|
|
139
|
+
/** 相对跳转;showOsd 为 false 时不显示中央提示 */
|
|
140
|
+
seekBy(delta: number, showOsd?: boolean): void;
|
|
141
|
+
setRate(rate: number): void;
|
|
142
|
+
/** 0-100 */
|
|
143
|
+
setVolume(volume: number): void;
|
|
144
|
+
setMuted(muted: boolean): void;
|
|
145
|
+
setAspectRatio(ratio: AspectRatio): void;
|
|
146
|
+
get aspectRatio(): AspectRatio;
|
|
147
|
+
/** 运行时更新画质列表 */
|
|
148
|
+
setQualities(qualities: QualityLevel[], active?: QualityLevel): void;
|
|
149
|
+
/** 运行时更新音轨列表 */
|
|
150
|
+
setAudioTracks(tracks: AudioTrackInfo[], active?: AudioTrackInfo): void;
|
|
151
|
+
toggleFullscreen(): Promise<void>;
|
|
152
|
+
get fullscreen(): boolean;
|
|
153
|
+
togglePip(): Promise<void>;
|
|
154
|
+
load(src: string): void;
|
|
155
|
+
setTitle(title: string): void;
|
|
156
|
+
/** 安装插件;返回本次插件的卸载函数 */
|
|
157
|
+
use(plugin: SweetPlayerPlugin): () => void;
|
|
158
|
+
on<K extends keyof PlayerEventMap>(event: K, fn: (payload: PlayerEventMap[K]) => void): () => void;
|
|
159
|
+
off<K extends keyof PlayerEventMap>(event: K, fn: (payload: PlayerEventMap[K]) => void): void;
|
|
160
|
+
destroy(): void;
|
|
161
|
+
private applyHlsLevels;
|
|
162
|
+
private applyHlsAudioTracks;
|
|
163
|
+
private handleQualitySelect;
|
|
164
|
+
private handleAudioTrackSelect;
|
|
165
|
+
private bindPersistence;
|
|
166
|
+
private bindProgressMemory;
|
|
167
|
+
private saveProgressNow;
|
|
168
|
+
private handleTitleClick;
|
|
169
|
+
private bindMediaEvents;
|
|
170
|
+
private showErrorState;
|
|
171
|
+
private showErrorStateUi;
|
|
172
|
+
private showControls;
|
|
173
|
+
private hideControlsNow;
|
|
174
|
+
private scheduleHide;
|
|
175
|
+
private bindActivityTracking;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
interface LocaleStrings {
|
|
179
|
+
play: string;
|
|
180
|
+
pause: string;
|
|
181
|
+
playPause: string;
|
|
182
|
+
prev: string;
|
|
183
|
+
next: string;
|
|
184
|
+
seekBack: string;
|
|
185
|
+
seekForward: string;
|
|
186
|
+
speed: string;
|
|
187
|
+
quality: string;
|
|
188
|
+
qualityAuto: string;
|
|
189
|
+
aspectRatio: string;
|
|
190
|
+
ratioOriginal: string;
|
|
191
|
+
audioTrack: string;
|
|
192
|
+
mute: string;
|
|
193
|
+
fullscreen: string;
|
|
194
|
+
pip: string;
|
|
195
|
+
empty: string;
|
|
196
|
+
closeStats: string;
|
|
197
|
+
seconds: string;
|
|
198
|
+
volume: string;
|
|
199
|
+
muted: string;
|
|
200
|
+
replay: string;
|
|
201
|
+
playNext: string;
|
|
202
|
+
autoNextIn: string;
|
|
203
|
+
cancel: string;
|
|
204
|
+
loadError: string;
|
|
205
|
+
retry: string;
|
|
206
|
+
}
|
|
207
|
+
type LocaleName = 'zh-CN' | 'en' | (string & {});
|
|
208
|
+
/** 注册自定义语言包(全局) */
|
|
209
|
+
declare function registerLocale(name: string, strings: LocaleStrings): void;
|
|
210
|
+
|
|
211
|
+
export { type AspectRatio, type AudioTrackInfo, type LocaleName, type LocaleStrings, type LongSeekOptions, type PlayerEventMap, type PlayerEventName, type QualityLevel, SweetPlayer, type SweetPlayerLike, type SweetPlayerOptions, type SweetPlayerPlugin, registerLocale };
|