w-dwload-dlp 1.0.1
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/.editorconfig +9 -0
- package/.eslintignore +3 -0
- package/.eslintrc.js +55 -0
- package/.jsdoc +25 -0
- package/LICENSE +21 -0
- package/README.md +63 -0
- package/SECURITY.md +5 -0
- package/babel.config.js +15 -0
- package/dist/w-dwload-dlp.umd.js +7 -0
- package/dist/w-dwload-dlp.umd.js.map +1 -0
- package/docs/WDwloadDlp.mjs.html +417 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/global.html +484 -0
- package/docs/index.html +84 -0
- package/docs/scripts/collapse.js +39 -0
- package/docs/scripts/commonNav.js +28 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/nav.js +12 -0
- package/docs/scripts/polyfill.js +4 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/scripts/prettify/lang-css.js +2 -0
- package/docs/scripts/prettify/prettify.js +28 -0
- package/docs/scripts/search.js +99 -0
- package/docs/styles/jsdoc.css +776 -0
- package/docs/styles/prettify.css +80 -0
- package/g.mjs +38 -0
- package/package.json +32 -0
- package/script.txt +18 -0
- package/src/WDwloadDlp.mjs +345 -0
- package/test/all.test.mjs +16 -0
- package/toolg/addVersion.mjs +4 -0
- package/toolg/cleanFolder.mjs +4 -0
- package/toolg/gDistRollup.mjs +30 -0
- package/toolg/modifyReadme.mjs +4 -0
- package/yt-dlp-2024.04.09/ffmpeg.exe +0 -0
- package/yt-dlp-2024.04.09/yt-dlp.exe +0 -0
- package/yt-dlp.md +15 -0
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>WDwloadDlp.mjs - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#WDwloadDlp">WDwloadDlp</a></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">WDwloadDlp.mjs</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import path from 'path'
|
|
49
|
+
import process from 'process'
|
|
50
|
+
import get from 'lodash-es/get.js'
|
|
51
|
+
import genID from 'wsemi/src/genID.mjs'
|
|
52
|
+
import now2strp from 'wsemi/src/now2strp.mjs'
|
|
53
|
+
import sep from 'wsemi/src/sep.mjs'
|
|
54
|
+
import strright from 'wsemi/src/strright.mjs'
|
|
55
|
+
import strdelright from 'wsemi/src/strdelright.mjs'
|
|
56
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
57
|
+
import isfun from 'wsemi/src/isfun.mjs'
|
|
58
|
+
import cdbl from 'wsemi/src/cdbl.mjs'
|
|
59
|
+
import execProcess from 'wsemi/src/execProcess.mjs'
|
|
60
|
+
import fsIsFile from 'wsemi/src/fsIsFile.mjs'
|
|
61
|
+
import fsIsFolder from 'wsemi/src/fsIsFolder.mjs'
|
|
62
|
+
import fsCopyFile from 'wsemi/src/fsCopyFile.mjs'
|
|
63
|
+
import fsDeleteFile from 'wsemi/src/fsDeleteFile.mjs'
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
let fdSrv = path.resolve()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
function isWindows() {
|
|
70
|
+
return process.platform === 'win32'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 下載video檔案,預設轉mp4,核心調用yt-dlp,只能用於Windows作業系統
|
|
76
|
+
*
|
|
77
|
+
* yt-dlp: https://github.com/yt-dlp/yt-dlp
|
|
78
|
+
*
|
|
79
|
+
* @param {String} url 輸入網址字串,支援網站種類詳見yt-dlp
|
|
80
|
+
* @param {String} fp 輸入儲存video(*.mp4)檔案路徑字串
|
|
81
|
+
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
82
|
+
* @param {Function} [opt.funProg=null] 輸入回傳進度函數,傳入參數為prog代表進度百分比、nn代表當前已下載ts檔案數量、na代表全部須下載ts檔案數量,預設null
|
|
83
|
+
* @returns {Promise} 回傳Promise,resolve回傳成功訊息,reject回傳錯誤訊息
|
|
84
|
+
* @example
|
|
85
|
+
* // import WDwloadDlp from 'w-dwload-dlp'
|
|
86
|
+
* import WDwloadDlp from './src/WDwloadDlp.mjs'
|
|
87
|
+
*
|
|
88
|
+
* async function test() {
|
|
89
|
+
*
|
|
90
|
+
* //url
|
|
91
|
+
* let url = `https://www.youtube.com/watch?v=uj8hjLyEBmU&ab_channel=%E7%A0%81%E5%86%9C%E9%AB%98%E5%A4%A9` //youtube
|
|
92
|
+
* // let url = `https://www.bilibili.com/video/BV1JZ421x7q8/?spm_id_from=333.1073.channel.secondary_floor_video.click` //bilibili
|
|
93
|
+
*
|
|
94
|
+
* //fp
|
|
95
|
+
* let fp = './test.mp4'
|
|
96
|
+
*
|
|
97
|
+
* //funProg
|
|
98
|
+
* let funProg = (prog, nn, na) => {
|
|
99
|
+
* console.log('prog', `${prog.toFixed(2)}%`, nn, na)
|
|
100
|
+
* }
|
|
101
|
+
*
|
|
102
|
+
* //WDwloadDlp
|
|
103
|
+
* await WDwloadDlp(url, fp, {
|
|
104
|
+
* clean: true, //單一程序執行時, 事先清除之前暫存檔, 減少浪費硬碟空間
|
|
105
|
+
* funProg,
|
|
106
|
+
* })
|
|
107
|
+
*
|
|
108
|
+
* console.log('done:', fp)
|
|
109
|
+
* }
|
|
110
|
+
* test()
|
|
111
|
+
* .catch((err) => {
|
|
112
|
+
* console.log('catch', err)
|
|
113
|
+
* })
|
|
114
|
+
* // prog 0.49% 1 99
|
|
115
|
+
* // prog 5.05% 4 99
|
|
116
|
+
* // ...
|
|
117
|
+
* // prog 99.00% 98 99
|
|
118
|
+
* // prog 100.00% 99 99
|
|
119
|
+
* // done: ./test.mp4
|
|
120
|
+
*
|
|
121
|
+
*/
|
|
122
|
+
async function WDwloadDlp(url, fp, opt = {}) {
|
|
123
|
+
let errTemp = null
|
|
124
|
+
|
|
125
|
+
//funProg
|
|
126
|
+
let funProg = get(opt, 'funProg')
|
|
127
|
+
|
|
128
|
+
//isWindows
|
|
129
|
+
if (!isWindows()) {
|
|
130
|
+
return Promise.reject('operating system is not windows')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
//check
|
|
134
|
+
if (!isestr(url)) {
|
|
135
|
+
return Promise.reject('url is not a file')
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//fdExe
|
|
139
|
+
let fdms = 'yt-dlp-2024.04.09'
|
|
140
|
+
let fdExeSelf = `${fdSrv}/${fdms}/`
|
|
141
|
+
let fdExeDist = `${fdSrv}/node_modules/w-dwload-dlp/${fdms}/`
|
|
142
|
+
let fdExe = fdExeSelf
|
|
143
|
+
if (fsIsFolder(fdExeDist)) {
|
|
144
|
+
fdExe = fdExeDist
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
//exeDl
|
|
148
|
+
let exeDl = path.resolve(fdExe, 'yt-dlp.exe')
|
|
149
|
+
exeDl = `"${exeDl}"` //用雙引號包住避免路徑有空格
|
|
150
|
+
// console.log('exeDl', exeDl)
|
|
151
|
+
|
|
152
|
+
//cwdOri, cwdTar
|
|
153
|
+
let cwdOri = process.cwd()
|
|
154
|
+
let cwdTar = fdExe
|
|
155
|
+
// console.log('process.cwd1', process.cwd())
|
|
156
|
+
|
|
157
|
+
//chdir, 若不切換mseed2ascii預設輸出檔案是在工作路徑, 輸出檔變成會出現在專案下
|
|
158
|
+
process.chdir(cwdTar)
|
|
159
|
+
// console.log('process.cwd2', process.cwd())
|
|
160
|
+
|
|
161
|
+
//id
|
|
162
|
+
let id = `${now2strp()}-${genID(6)}`
|
|
163
|
+
|
|
164
|
+
//fnAny
|
|
165
|
+
let fnAny = `${id}` //無副檔名
|
|
166
|
+
|
|
167
|
+
//fdDownloads
|
|
168
|
+
let fdDownloads = path.resolve(fdExe, 'Downloads')
|
|
169
|
+
// console.log('fdDownloads', fdDownloads)
|
|
170
|
+
|
|
171
|
+
//fpInAny
|
|
172
|
+
let fpInAny = path.resolve(fdDownloads, fnAny)
|
|
173
|
+
// console.log('fpInAny', fpInAny)
|
|
174
|
+
|
|
175
|
+
//fpInMp4
|
|
176
|
+
let fpInMp4 = path.resolve(fdDownloads, `${id}.mp4`)
|
|
177
|
+
// console.log('fpInMp4', fpInMp4)
|
|
178
|
+
|
|
179
|
+
let bdl = false
|
|
180
|
+
let nnPre = 0
|
|
181
|
+
let nn = 0
|
|
182
|
+
let na = 0
|
|
183
|
+
let prog = 0
|
|
184
|
+
let bFunProg = isfun(funProg)
|
|
185
|
+
let cbStdout = (msg) => {
|
|
186
|
+
// console.log('cbStdout', msg)
|
|
187
|
+
|
|
188
|
+
//s
|
|
189
|
+
let s = sep(msg, ' ')
|
|
190
|
+
// console.log('s', s)
|
|
191
|
+
|
|
192
|
+
//s1
|
|
193
|
+
let s1 = get(s, 1, '')
|
|
194
|
+
|
|
195
|
+
//bp
|
|
196
|
+
let bp = strright(s1, 1) === '%'
|
|
197
|
+
|
|
198
|
+
//check
|
|
199
|
+
if (!bp) {
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
//prog
|
|
204
|
+
let _prog = strdelright(s1, 1)
|
|
205
|
+
_prog = cdbl(_prog)
|
|
206
|
+
// console.log('_prog(ori)', _prog)
|
|
207
|
+
|
|
208
|
+
//bdl
|
|
209
|
+
if (!bdl && _prog === 100) {
|
|
210
|
+
bdl = true
|
|
211
|
+
return //當第1次達100%先跳出, 不處理之後檔案下載進度
|
|
212
|
+
}
|
|
213
|
+
// console.log('bdl', bdl)
|
|
214
|
+
|
|
215
|
+
//check, 若bdl=false, 代表尚未完成下載清單100%, 不處理之後檔案下載進度
|
|
216
|
+
if (!bdl) {
|
|
217
|
+
return
|
|
218
|
+
}
|
|
219
|
+
// console.log('eff. download')
|
|
220
|
+
|
|
221
|
+
_prog *= 0.99 //最高99%, 因可能還有轉檔(例如webm轉mp4), 故最後100%改由最後完成階段觸發
|
|
222
|
+
// console.log('_prog(99%)', _prog)
|
|
223
|
+
|
|
224
|
+
//update
|
|
225
|
+
if (prog < _prog) {
|
|
226
|
+
prog = _prog
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
// console.log('prog', prog)
|
|
232
|
+
|
|
233
|
+
//nna
|
|
234
|
+
let s10 = get(s, 10)
|
|
235
|
+
s10 = strdelright(s10, 1)
|
|
236
|
+
let nna = sep(s10, '/')
|
|
237
|
+
|
|
238
|
+
//nn
|
|
239
|
+
nn = get(nna, 0, '')
|
|
240
|
+
nn = cdbl(nn)
|
|
241
|
+
// console.log('nn', nn)
|
|
242
|
+
|
|
243
|
+
//check, 若nn沒有>nnPre則視為不需要觸發funProg, 減少切太細導致高頻觸發
|
|
244
|
+
if (nn <= nnPre) {
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
//na
|
|
249
|
+
na = get(nna, 1, '')
|
|
250
|
+
na = cdbl(na)
|
|
251
|
+
// console.log('na', na)
|
|
252
|
+
|
|
253
|
+
//call
|
|
254
|
+
if (bFunProg) {
|
|
255
|
+
// console.log('prog', nn, na, prog)
|
|
256
|
+
funProg(prog, nn, na)
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
//update
|
|
260
|
+
nnPre = nn
|
|
261
|
+
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//cmdDl
|
|
265
|
+
let cmdDl = `"${url}" -o "${fpInAny}" --newline --merge-output-format "mp4"`
|
|
266
|
+
// console.log('cmdDl', cmdDl)
|
|
267
|
+
|
|
268
|
+
//execProcess
|
|
269
|
+
await execProcess(exeDl, cmdDl, { cbStdout })
|
|
270
|
+
// .then(function(res) {
|
|
271
|
+
// console.log('execProcess then', res)
|
|
272
|
+
// })
|
|
273
|
+
.catch((err) => {
|
|
274
|
+
console.log('execProcess catch', err)
|
|
275
|
+
errTemp = 'execProcess error'
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
//call
|
|
279
|
+
if (bFunProg) {
|
|
280
|
+
prog = 100
|
|
281
|
+
// console.log('prog', prog)
|
|
282
|
+
funProg(prog, na, na) //因是強制100%, 故nn要直接給na
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
// //clearInterval
|
|
287
|
+
// clearInterval(t)
|
|
288
|
+
|
|
289
|
+
//chdir, 不論正常或錯誤皆需還原工作路徑
|
|
290
|
+
process.chdir(cwdOri)
|
|
291
|
+
|
|
292
|
+
//check
|
|
293
|
+
if (isestr(errTemp)) {
|
|
294
|
+
return Promise.reject(errTemp)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// //check, 若因m3u8內method給NONE無法被N_m3u8DL-CLI識別處理, 故會採取僅合併ts不轉檔方式產生ts
|
|
298
|
+
// if (!fsIsFile(fpInAny) && fsIsFile(fpInTs)) {
|
|
299
|
+
|
|
300
|
+
// //cmdFfmpeg
|
|
301
|
+
// let cmdFfmpeg = `-i "${fpInTs}" -vcodec copy -acodec copy "${fpInAny}"`
|
|
302
|
+
// // console.log('cmdFfmpeg', cmdFfmpeg)
|
|
303
|
+
|
|
304
|
+
// //execProcess
|
|
305
|
+
// await execProcess(exeFfmpeg, cmdFfmpeg)
|
|
306
|
+
// // .then(function(res) {
|
|
307
|
+
// // console.log('execProcess then', res)
|
|
308
|
+
// // })
|
|
309
|
+
// .catch(() => {
|
|
310
|
+
// //console.log('execProcess catch', err)
|
|
311
|
+
// //特殊偵測處理, 不再提供報錯訊尋
|
|
312
|
+
// })
|
|
313
|
+
|
|
314
|
+
// }
|
|
315
|
+
|
|
316
|
+
// //check, 若下載檔案為webm, 則再轉為mp4
|
|
317
|
+
// if (fsIsFile(fpInWebm) && !fsIsFile(fpInMp4)) {
|
|
318
|
+
|
|
319
|
+
// //cmdFfmpeg
|
|
320
|
+
// let cmdFfmpeg = `-i -k "${fpInWebm}" "${fpInMp4}"`
|
|
321
|
+
// // console.log('cmdFfmpeg', cmdFfmpeg)
|
|
322
|
+
|
|
323
|
+
// //execProcess
|
|
324
|
+
// await execProcess(exeFfmpeg, cmdFfmpeg)
|
|
325
|
+
// .then(function(res) {
|
|
326
|
+
// console.log('execProcess then', res)
|
|
327
|
+
// })
|
|
328
|
+
// .catch((err) => {
|
|
329
|
+
// console.log('execProcess catch', err)
|
|
330
|
+
// //特殊偵測處理, 不再提供報錯訊尋
|
|
331
|
+
// })
|
|
332
|
+
|
|
333
|
+
// }
|
|
334
|
+
|
|
335
|
+
//check
|
|
336
|
+
if (!fsIsFile(fpInMp4)) {
|
|
337
|
+
console.log(`can not find the merged file[${fpInMp4}]`)
|
|
338
|
+
errTemp = `invalid url[${url}] or can not download`
|
|
339
|
+
return Promise.reject(errTemp)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
//fpOut
|
|
343
|
+
let fpOut = fp
|
|
344
|
+
// console.log('fpOut', fpOut)
|
|
345
|
+
|
|
346
|
+
let rc
|
|
347
|
+
|
|
348
|
+
//fsCopyFile
|
|
349
|
+
rc = fsCopyFile(fpInMp4, fpOut)
|
|
350
|
+
errTemp = get(rc, 'error')
|
|
351
|
+
if (errTemp) {
|
|
352
|
+
return Promise.reject(errTemp.toString())
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
//fsDeleteFile
|
|
356
|
+
rc = fsDeleteFile(fpInMp4)
|
|
357
|
+
//可能無檔案無法刪, 故不檢查錯誤
|
|
358
|
+
|
|
359
|
+
// //fsDeleteFile
|
|
360
|
+
// rc = fsDeleteFile(fpInWebm)
|
|
361
|
+
// //可能無檔案無法刪, 故不檢查錯誤
|
|
362
|
+
|
|
363
|
+
// //fsDeleteFile
|
|
364
|
+
// rc = fsDeleteFile(fpInMp4)
|
|
365
|
+
// errTemp = get(rc, 'error')
|
|
366
|
+
// if (errTemp) {
|
|
367
|
+
// return Promise.reject(errTemp.toString())
|
|
368
|
+
// }
|
|
369
|
+
|
|
370
|
+
// //fsDeleteFile
|
|
371
|
+
// rc = fsDeleteFile(fpInTs)
|
|
372
|
+
// //可能無檔案無法刪, 故不檢查錯誤
|
|
373
|
+
|
|
374
|
+
// //fsDeleteFolder
|
|
375
|
+
// rc = fsDeleteFolder(fdDownloadsId)
|
|
376
|
+
// errTemp = get(rc, 'error')
|
|
377
|
+
// if (errTemp) {
|
|
378
|
+
// return Promise.reject(errTemp.toString())
|
|
379
|
+
// }
|
|
380
|
+
|
|
381
|
+
// //fsCleanFolder
|
|
382
|
+
// rc = fsCleanFolder(fdLogs)
|
|
383
|
+
// errTemp = get(rc, 'error')
|
|
384
|
+
// if (errTemp) {
|
|
385
|
+
// return Promise.reject(errTemp.toString())
|
|
386
|
+
// }
|
|
387
|
+
|
|
388
|
+
return 'ok'
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
export default WDwloadDlp
|
|
393
|
+
</code></pre>
|
|
394
|
+
</article>
|
|
395
|
+
</section>
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
</div>
|
|
403
|
+
|
|
404
|
+
<br class="clear">
|
|
405
|
+
|
|
406
|
+
<footer>
|
|
407
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.3</a> on Tue May 21 2024 21:53:47 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
408
|
+
</footer>
|
|
409
|
+
|
|
410
|
+
<script>prettyPrint();</script>
|
|
411
|
+
<script src="scripts/polyfill.js"></script>
|
|
412
|
+
<script src="scripts/linenumber.js"></script>
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
</body>
|
|
417
|
+
</html>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|