efront 4.12.1 → 4.13.2

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.
@@ -1,3 +1,15 @@
1
+ - zh-CN: 加载失败
2
+ en: Loading failed
3
+
4
+ - zh-CN: 发现递归请求!
5
+ en: Found recursive request!
6
+
7
+ - zh-CN: 您的请求信息异常!请更换浏览器重试!
8
+ en: Your request information is abnormal! Please change your browser and try again!
9
+
10
+ - zh-CN: 配置的域名无法生成正则表达式:$1
11
+ en: "The configured domain name cannot generate a regular expression: $1"
12
+
1
13
  - zh-CN: 这个文件的内容不能在非nodejs环境中运行
2
14
  en: The content of this file cannot be run in a non nodejs environment
3
15
 
@@ -20,6 +20,15 @@
20
20
  // -------/// ---------------1---------------------------------///////////////////2-----3--------//////// ------4----2/////5---------------------------------------------------6------------------------------------------------------------------------------------//////////////-7--5///8-------9----------//10--11---10/8/--12----////
21
21
  var reg = /^([^\:\/\\\?#\[]+\:(?![^\:\/\\\?\#]*@|[\/\\][^\/\\]))?(?:\/\/|\\\\)?(?:(([^\:\/\\\?#]+)?(?:\:([^\/\\\?#]+))?)@)?(([^\/\\@\?\#\.]*?[^\/\\@\:\?\#\.\d][^\/\\@\:\?\#\.]*?|[^\/\\@\:\?\#\.]+(?:\:[^\@\/\\\?#\.]*[^\d\@\:\/\\\?#\.]+|(?:\.[^\/\\@\:\?\#\.]+)+))?(?:(?:\:|^)(\d+))?)(((?:\/|\\|^)[^\?#]*)?(\?([^#]*))?)(#[\s\S]*)?$/;
22
22
  class URL {
23
+ resolve(url) {
24
+ var u = new URL;
25
+ Object.assign(u, this);
26
+ if (!/^([^\:\/\\\?#\[]+\:|[\:\/\\\?#\[]+)/.test(url)) {
27
+ url = u.pathname.replace(/[^\/]+$/, '') + url;
28
+ }
29
+ u.locate(url);
30
+ return u;
31
+ }
23
32
  locate(url) {
24
33
  if (url === undefined || url === null) url = '';
25
34
  var [__, protocol, auth, username, password, host, hostname, port, path, pathname, search, query, hash] = reg.exec(url);
@@ -429,7 +429,6 @@ var getFromScopeList = function (name, varsList, value = name) {
429
429
  while (name in o) {
430
430
  name = o[name];
431
431
  if (typeof name !== 'string') return name;
432
- name = strings.decode(name);
433
432
  if (!/^\-\-|^@[^\{]/.test(name)) return name;
434
433
  if (queue.indexOf(name) >= 0) throw `变量环形引用,无法初始化:${queue}`;
435
434
  queue.push(name);
@@ -490,8 +489,11 @@ var Method = function () {
490
489
  }
491
490
  var vlist = [], mlist = [macros], clist = [], base = '';
492
491
  var calcvars = function (v) {
492
+ var decode = /^['"`]/.test(v) ? strings.decode : a => a;
493
493
  return v.replace(/@[^\s\{\}\(\)\[\]\:\+\*\/,;\!\>\$\=\&\%\#\@'"`\?\.\/\|~#]+|@\{[^\}@]*\}/g, function (m) {
494
- return getFromScopeList(m, vlist, m);
494
+ var value = getFromScopeList(m, vlist, m);
495
+ value = decode(value);
496
+ return value;
495
497
  }).replace(/(^|\s|[\]\)\(\[\-\+\*\/,;])(?:var\s*\(([\s\S]*?)\)|(--\S+))/g, function (m, q, a, b) {
496
498
  return q + getFromScopeList(b || a.trim(), vlist, m.slice(q.length));
497
499
  });
@@ -1,31 +1,164 @@
1
- var URL = require("url");
2
1
  var path = require("path");
3
- function main(m3u8, dst) {
4
- function index(a, total) {
5
- a = String(a);
6
- return String(total).replace(/\d/g, function (m, index, input) {
7
- if (index + a.length < input.length) return '0';
8
- return a[index + a.length - input.length];
9
- });
2
+ var fs = require("fs");
3
+ var http = require("http");
4
+ var https = require("https");
5
+ var parseM3U8 = function (text, url) {
6
+ url = parseURL(url);
7
+ var list = text.split(/[\r\n]+/).filter(a => !!a).map(function (name) {
8
+ if (/^#/.test(name)) return name;
9
+ name = url.resolve(name).toString();
10
+ return name;
11
+ });
12
+ return list;
13
+ };
14
+ var fillTree = function (node, pathname) {
15
+ var pathlist = pathname.split(/[\\\/]/);
16
+ for (var p of pathlist) {
17
+ if (!node[p]) node[p] = Object.create(null);
18
+ node = node[p];
19
+ }
20
+ }
21
+ var formatName = function (videos, urls) {
22
+ var pathMap = Object.create(null);
23
+ var treeMap = Object.create(null);
24
+ urls.forEach(function (url) {
25
+ var { pathname } = parseURL(url);
26
+ fillTree(treeMap, pathname);
27
+ });
28
+ for (var v of videos) {
29
+ var { pathname } = parseURL(v);
30
+ fillTree(treeMap, pathname);
31
+ pathname = pathname.replace(/^[\\\/]+/, '').replace(/[\d\-\s\~\_\:\.\/\\]+(\.\w+)$/, '$1');
32
+ pathname = pathname.replace(/\.[^\.\\\/]+$/, '').replace(/[\\\/]/g, '-');
33
+ var list = pathMap[pathname];
34
+ if (!list) {
35
+ pathMap[pathname] = [v];
36
+ }
37
+ else {
38
+ list.push(v);
39
+ }
40
+ }
41
+ var treePath = [];
42
+ do {
43
+ var treekeys = Object.keys(treeMap);
44
+ if (treekeys.length !== 1) break;
45
+ treekeys = treekeys[0];
46
+ treePath.push(treekeys);
47
+ treeMap = treeMap[treekeys];
48
+ } while (treeMap);
49
+ treePath = treePath.join('/');
50
+ var pathLength = treePath.length;
51
+ var realMap = Object.create(null);
52
+ for (var pathname in pathMap) {
53
+ var list = pathMap[pathname];
54
+ pathname = pathname.slice(pathLength);
55
+ if (list.length > 1) {
56
+ var ilength = String(list.length).length;
57
+ list = list.forEach((n, i) => {
58
+ var i = String(i);
59
+ i = Array(ilength + 1 - i.length).join("0") + i;
60
+ realMap[n] = pathname + "-" + i + path.extname(n);
61
+ });
62
+ }
63
+ else {
64
+ realMap[list[0]] = pathname;
65
+ }
10
66
  }
11
- fetch(m3u8).then(function (a) {
12
- var reg = /^(.*?)\?start=(\d+)&end=.*?$/;
13
- var downloaded = {};
14
- var list = a.toString().split(/[\r\n]+/).filter(e => e && !/^#/.test(e)).map(function (name) {
15
- var match = reg.exec(name);
16
- if (!match) return;
17
- var file = match[1];
18
- if (downloaded[file]) return;
19
- downloaded[file] = true;
20
- return file;
21
- }).filter(a => !!a);
22
- return queue.call(list, function (file, cx) {
23
- console.info(file);
24
- var fileurl = URL.resolve(m3u8, file);
25
- return fetch(fileurl).then(function (buff) {
26
- return fs2(path.join(dst, index(cx, list.length) + '.' + file)).writeSync(buff);
67
+ return [realMap, treePath];
68
+ };
69
+ var downLoad = function (url, dest) {
70
+ return new Promise(function (ok, oh) {
71
+ var h = /^https\:/.test(url) ? https : http;
72
+ var r = h.get(url, function (r) {
73
+ var w = fs.createWriteStream(dest);
74
+ r = decodeHttpResponse(r);
75
+ r.pipe(w);
76
+ r.once("error", function (error) {
77
+ w.close(function () {
78
+ fs.unlink(dest, function () {
79
+ oh(error)
80
+ });
81
+ });
27
82
  });
83
+ w.once('error', oh);
84
+ w.once("finish", ok);
28
85
  });
86
+ r.once('error', oh);
87
+ r.end();
29
88
  });
89
+ }
90
+ var breakLine = '\r\n';
91
+ var deepFetch = async function (url, dest) {
92
+ var rest = [];
93
+ var is_m3u8 = true;
94
+ var videos = [];
95
+ var urls = [url];
96
+ var commentMap = [];
97
+ var comments = ["#EXTM3U"];
98
+ do {
99
+ if (is_m3u8) {
100
+ var response = await fetch(url);
101
+ switch (response.status) {
102
+ case 0:
103
+ case 200:
104
+ case 304:
105
+ var m3u8 = await response.text();
106
+ urls.push(url);
107
+ var list = parseM3U8(m3u8, url).reverse();
108
+ if (/#EXTM3U/i.test(list[list.length - 1])) list.pop();
109
+ rest.push(...list);
110
+ break;
111
+ default:
112
+ throw new Error(`加载 ${url} 失败: ${response.statusText}`);
113
+ }
114
+ }
115
+ else {
116
+ if (/^#/.test(url)) {
117
+ comments.push(url);
118
+ }
119
+ else {
120
+ commentMap[url] = comments.join(breakLine);
121
+ comments = [];
122
+ videos.push(url);
123
+ }
124
+ }
125
+ url = rest.pop();
126
+ is_m3u8 = url && /\.m3u8$/i.test(url);
127
+ } while (url);
30
128
 
129
+ var [nameMap, treePath] = formatName(videos, urls);
130
+ var videoname = path.basename(treePath);
131
+ if (!videoname) if (videos.length === 1) videoname = nameMap[videos[0]];
132
+ if (!videoname) {
133
+ if (fs.existsSync(dest)) throw new Error("目标文件夹已存在!");
134
+ videoname = path.basename(dest);
135
+ dest = path.dirname(dest);
136
+ }
137
+ if (!fs.existsSync(dest)) throw new Error("目标文件夹无效!");
138
+ if (path.basename(dest) !== videoname) dest = path.join(dest, videoname);
139
+ if (!fs.existsSync(dest)) fs.mkdirSync(dest);
140
+ for (var v of videos) {
141
+ try {
142
+ var d = path.join(dest, nameMap[v]);
143
+ if (fs.existsSync(d)) {
144
+ console.info(`已跳过文件 ${d}`);
145
+ continue;
146
+ }
147
+ console.info(`正在下载 ${v}`)
148
+ await downLoad(v, d);
149
+ } catch (e) {
150
+ console.error(`下载 ${v} 失败:${e}`);
151
+ }
152
+ }
153
+ var index = videos.map(v => {
154
+ var n = nameMap[v];
155
+ var c = commentMap[v];
156
+ return c + breakLine + n;
157
+ });
158
+ index.push(...comments);
159
+ index = index.join(breakLine) + breakLine;
160
+ await fs.promises.writeFile(path.join(dest, 'index.m3u8'), index);
161
+ }
162
+ function main(m3u8, dst) {
163
+ return deepFetch(m3u8, dst);
31
164
  }
@@ -1,5 +1,5 @@
1
1
 
2
2
  m3u8Download(
3
- `https://1251953721.vod2.myqcloud.com/0ec02e46vodcq1251953721/7c4525705285890791033559507/playlist.m3u8`,
3
+ `http://localhost/绝命幽灵船/index.m3u8`,
4
4
  "/data/"
5
5
  );
@@ -1,8 +1,11 @@
1
1
  <thead @mounted="setFixedColumn.call(this.parentNode),setContextMenu(this)">
2
2
  <tr inline-block #adapter thead @mounted="resizeT(this)">
3
- <td draggable="false" fixed row-index><mask></mask>${i18n`序号`}</td>
4
- <td fixed:="f.fixed" -repeat="f in fields track by f.id" :style="{width:f.width}" @dblclick="sort(f)" swapped_="f.summary"><mask></mask><i
5
- -if="f.icon" -class="f.icon"></i><span -if="f.name" -html="f.name"
3
+ <td draggable="false" fixed row-index>
4
+ <mask></mask>${i18n`序号`}
5
+ </td>
6
+ <td fixed:="f.fixed" -repeat="f in fields track by f.id" :style="{width:f.width}" @dblclick="sort(f)"
7
+ swapped_="f.summary">
8
+ <mask></mask><i -if="f.icon" -class="f.icon"></i><span -if="f.name" -html="f.name"
6
9
  type@="typeof f.type==='string'?f.type:''"></span><template -else>&nbsp;</template>
7
10
  </td>
8
11
  <td style="min-width: 0;" draggable="false">&nbsp;</td>
@@ -10,7 +13,8 @@
10
13
  </thead>
11
14
  <tbody -src="(d,i) in data" :style="tbodyHeight(this,hasFoot)">
12
15
  <tr inline-block :style="{width:adapter.style.width}" @click="rowClick(d,i,event)" @mounted="resizeR(this)">
13
- <td fixed row-index :style="adapter.firstChild.getAttribute('style')"><mask></mask><span -bind="i+1"></span>
16
+ <td fixed row-index :style="adapter.firstChild.getAttribute('style')">
17
+ <mask></mask><span -bind="i+1"></span>
14
18
  </td>
15
19
  <td fixed:="f.fixed" -repeat="(f,i) in fields" :style="adapter.children[i+1].getAttribute('style')">
16
20
  <mask></mask>
@@ -21,13 +25,16 @@
21
25
  <span -text="o.name instanceof Function?o.name(d):o.name"></span>
22
26
  </a>
23
27
  </td>
24
- <td :style="adapter.lastChild.getAttribute('style')"><mask></mask>&nbsp;</td>
28
+ <td :style="adapter.lastChild.getAttribute('style')">
29
+ <mask></mask>&nbsp;
30
+ </td>
25
31
  </tr>
26
32
  </tbody>
27
33
  <tfoot>
28
34
  <tr .fade -if="!data||!data.length" style="padding-bottom: 20px;">
29
35
  <td style="text-align: center;">
30
36
  <template -if="data.is_loading">${i18n`加载中`}</template>
37
+ <template -elseif="data.is_errored">${i18n`加载失败`}</template>
31
38
  <template -else>${i18n`无数据`}</template>
32
39
  </td>
33
40
  </tr>
@@ -575,7 +575,8 @@ function table(elem) {
575
575
  };
576
576
  render(this, $scope, this.$parentScopes.concat(this.$scope));
577
577
  if (isMounted(table)) setFixedColumn.call(table);
578
- $scope.data = Table.from(fields, await data);
578
+ await data;
579
+ if (!data.is_errored) $scope.data = Table.from(fields, data);
579
580
  $scope.data.callback = function () {
580
581
  render.digest();
581
582
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "efront",
3
- "version": "4.12.1",
3
+ "version": "4.13.2",
4
4
  "description": "简化前端开发,优化web性能",
5
5
  "main": "public/efront.js",
6
6
  "directories": {