dsh-sidebar-row-menu 1.3.2 → 1.3.4
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/README.en.md +34 -8
- package/README.md +32 -7
- package/lib/client.js +30 -0
- package/package.json +2 -1
- package/scripts/marketplace-preflight.mjs +169 -0
package/README.en.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-sidebar-row-menu
|
|
2
2
|
|
|
3
|
-
<img src="assets/icon-180.png" width="96" align="right" alt="Plugin icon" />
|
|
3
|
+
<img src="https://raw.githubusercontent.com/TLEWA/dsh-sidebar-row-menu/main/assets/icon-180.png" width="96" align="right" alt="Plugin icon" />
|
|
4
4
|
|
|
5
5
|
[](https://github.com/TLEWA/dsh-sidebar-row-menu/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/TLEWA/dsh-sidebar-row-menu/releases)
|
|
@@ -73,7 +73,33 @@ Requirements:
|
|
|
73
73
|
- Windows PowerShell 5.1+;
|
|
74
74
|
- Row components from the `0.2.1-rc.5` generation (see [Compatibility](#compatibility)).
|
|
75
75
|
|
|
76
|
-
### Install from
|
|
76
|
+
### Install from npm (recommended)
|
|
77
|
+
|
|
78
|
+
The package is published to the npm registry, and DSH's plugin installer can
|
|
79
|
+
resolve it directly by name:
|
|
80
|
+
|
|
81
|
+
1. Open **Plugins** in the sidebar → **Install plugin**;
|
|
82
|
+
2. Enter the package name and confirm:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
dsh-sidebar-row-menu
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
3. Hard-refresh (`Ctrl+Shift+R`); restart the desktop app if the host half is not active.
|
|
89
|
+
|
|
90
|
+
Pin a version by appending it to the name:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
dsh-sidebar-row-menu@1.3.4
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Equivalent command line:
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
dsh plugin --profile desktop add dsh-sidebar-row-menu@1.3.4
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Install from GitHub
|
|
77
103
|
|
|
78
104
|
DSH Desktop installs Git dependencies through pnpm. The `lib/` directory in this
|
|
79
105
|
repository is already runnable, so **no local build is required**.
|
|
@@ -90,13 +116,13 @@ repository is already runnable, so **no local build is required**.
|
|
|
90
116
|
That URL tracks the latest commit on `main`. Pin a tag for a stable version:
|
|
91
117
|
|
|
92
118
|
```
|
|
93
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.3.
|
|
119
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.3.4
|
|
94
120
|
```
|
|
95
121
|
|
|
96
122
|
Or install the tarball built by Actions directly, without Git:
|
|
97
123
|
|
|
98
124
|
```
|
|
99
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.3.
|
|
125
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.3.4/dsh-sidebar-row-menu-1.3.4.tgz
|
|
100
126
|
```
|
|
101
127
|
|
|
102
128
|
Equivalent command line:
|
|
@@ -175,10 +201,10 @@ repository itself is untouched.
|
|
|
175
201
|
> as relative to the profile, and cross-drive paths produce broken links. The
|
|
176
202
|
> script exists to avoid exactly that.
|
|
177
203
|
|
|
178
|
-
### Switching from the script install to
|
|
204
|
+
### Switching from the script install to a pnpm install (npm / GitHub)
|
|
179
205
|
|
|
180
|
-
If you installed the development copy with `scripts/install.ps1` and then
|
|
181
|
-
the GitHub URL into the Plugins page, pnpm may fail with:
|
|
206
|
+
If you installed the development copy with `scripts/install.ps1` and then enter
|
|
207
|
+
the npm package name or the GitHub URL into the Plugins page, pnpm may fail with:
|
|
182
208
|
|
|
183
209
|
```
|
|
184
210
|
[ERR_PNPM_EPERM] [importPackage ...\node_modules\dsh-sidebar-row-menu]
|
|
@@ -203,7 +229,7 @@ cmd /c rmdir "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-sidebar-ro
|
|
|
203
229
|
```
|
|
204
230
|
|
|
205
231
|
A fresh profile never hits this; it only affects the "script install, then
|
|
206
|
-
|
|
232
|
+
pnpm install (npm or GitHub)" transition.
|
|
207
233
|
|
|
208
234
|
## Development
|
|
209
235
|
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-sidebar-row-menu
|
|
2
2
|
|
|
3
|
-
<img src="assets/icon-180.png" width="96" align="right" alt="插件图标" />
|
|
3
|
+
<img src="https://raw.githubusercontent.com/TLEWA/dsh-sidebar-row-menu/main/assets/icon-180.png" width="96" align="right" alt="插件图标" />
|
|
4
4
|
|
|
5
5
|
[](https://github.com/TLEWA/dsh-sidebar-row-menu/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/TLEWA/dsh-sidebar-row-menu/releases)
|
|
@@ -66,7 +66,32 @@
|
|
|
66
66
|
- Windows PowerShell 5.1+;
|
|
67
67
|
- 与 DSH 客户端内置包 `0.2.1-rc.5` 同代的行组件(见[兼容性](#兼容性))。
|
|
68
68
|
|
|
69
|
-
### 从
|
|
69
|
+
### 从 npm 安装(推荐)
|
|
70
|
+
|
|
71
|
+
包已发布到 npm registry,DSH 的插件安装器可以直接按包名解析:
|
|
72
|
+
|
|
73
|
+
1. 打开侧边栏 **插件** 页 → **安装插件**;
|
|
74
|
+
2. 输入包名并确认:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
dsh-sidebar-row-menu
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
3. 安装完成后硬刷新(`Ctrl+Shift+R`);宿主半边未生效时重启桌面端。
|
|
81
|
+
|
|
82
|
+
要固定版本,在包名后加版本号:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
dsh-sidebar-row-menu@1.3.4
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
命令行等价写法:
|
|
89
|
+
|
|
90
|
+
```powershell
|
|
91
|
+
dsh plugin --profile desktop add dsh-sidebar-row-menu@1.3.4
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### 从 GitHub 安装
|
|
70
95
|
|
|
71
96
|
DSH 桌面端通过 pnpm 安装 Git 依赖;本仓库的 `lib/` 已是可直接运行的产物,安装时
|
|
72
97
|
**不需要本地构建**。
|
|
@@ -83,13 +108,13 @@ DSH 桌面端通过 pnpm 安装 Git 依赖;本仓库的 `lib/` 已是可直接
|
|
|
83
108
|
该地址跟随 `main` 的最新提交。要固定版本,在地址后加标签:
|
|
84
109
|
|
|
85
110
|
```
|
|
86
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.3.
|
|
111
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu#v1.3.4
|
|
87
112
|
```
|
|
88
113
|
|
|
89
114
|
也可以直接安装 Actions 打出的压缩包(不经过 Git):
|
|
90
115
|
|
|
91
116
|
```
|
|
92
|
-
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.3.
|
|
117
|
+
https://github.com/TLEWA/dsh-sidebar-row-menu/releases/download/v1.3.4/dsh-sidebar-row-menu-1.3.4.tgz
|
|
93
118
|
```
|
|
94
119
|
|
|
95
120
|
命令行等价写法:
|
|
@@ -158,9 +183,9 @@ powershell -NoProfile -File .\scripts\install.ps1 -Uninstall
|
|
|
158
183
|
> 不要用 `dsh plugin add link:<绝对路径>`:pnpm 在 Windows 上把 `link:` 当成相对
|
|
159
184
|
> profile 的路径,跨盘时会生成坏链接;脚本正是为了绕开这一点。
|
|
160
185
|
|
|
161
|
-
### 从脚本安装切换到 GitHub
|
|
186
|
+
### 从脚本安装切换到 pnpm 安装(npm / GitHub)
|
|
162
187
|
|
|
163
|
-
如果你先用 `scripts/install.ps1` 装过开发版,再在插件页输入 GitHub 地址,pnpm 可能报:
|
|
188
|
+
如果你先用 `scripts/install.ps1` 装过开发版,再在插件页输入 npm 包名或 GitHub 地址,pnpm 可能报:
|
|
164
189
|
|
|
165
190
|
```
|
|
166
191
|
[ERR_PNPM_EPERM] [importPackage ...\node_modules\dsh-sidebar-row-menu]
|
|
@@ -181,7 +206,7 @@ powershell -NoProfile -File .\scripts\install.ps1 -Uninstall
|
|
|
181
206
|
cmd /c rmdir "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-sidebar-row-menu"
|
|
182
207
|
```
|
|
183
208
|
|
|
184
|
-
全新 profile 不会遇到这个问题;它只影响“先脚本安装、后 GitHub
|
|
209
|
+
全新 profile 不会遇到这个问题;它只影响“先脚本安装、后 pnpm(npm 或 GitHub)安装”的切换场景。
|
|
185
210
|
|
|
186
211
|
## 开发
|
|
187
212
|
|
package/lib/client.js
CHANGED
|
@@ -649,6 +649,35 @@ window.__ModuleLoader__.load({
|
|
|
649
649
|
return null;
|
|
650
650
|
}
|
|
651
651
|
|
|
652
|
+
/**
|
|
653
|
+
* 有些插件(例如 meow-memory 的「记忆参与」)在菜单打开后才用
|
|
654
|
+
* MutationObserver 往面板里补一个 DOM 条目;它们只有在收到行内「…」
|
|
655
|
+
* 按钮的 pointerdown 时才走同步注入的快路径,否则要等约 120ms 的防抖,
|
|
656
|
+
* 表现就是菜单先出现、条目晚一拍再冒出来,触发一次可见的重排。
|
|
657
|
+
*
|
|
658
|
+
* 右键发生在行标题等位置,天然不会点到「…」按钮,所以这里补发一次
|
|
659
|
+
* pointerdown,让这类插件在菜单挂载的同一帧完成注入。事件只用于通知,
|
|
660
|
+
* 不派发 click,也不会二次打开菜单。
|
|
661
|
+
*/
|
|
662
|
+
function primeRowActionPointer(trigger) {
|
|
663
|
+
if (trigger === null || trigger === undefined || typeof trigger.dispatchEvent !== 'function') return;
|
|
664
|
+
if (typeof PointerEvent !== 'function') return;
|
|
665
|
+
try {
|
|
666
|
+
trigger.dispatchEvent(new PointerEvent('pointerdown', {
|
|
667
|
+
bubbles: true,
|
|
668
|
+
cancelable: true,
|
|
669
|
+
composed: true,
|
|
670
|
+
pointerId: 1,
|
|
671
|
+
pointerType: 'mouse',
|
|
672
|
+
isPrimary: true,
|
|
673
|
+
button: 0,
|
|
674
|
+
buttons: 1,
|
|
675
|
+
}));
|
|
676
|
+
} catch {
|
|
677
|
+
/* 第三方 pointerdown 监听器抛错不应影响菜单打开 */
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
|
|
652
681
|
/**
|
|
653
682
|
* 右键会话行时在指针处展开该行自带的「…」菜单。
|
|
654
683
|
* 菜单内容来自 slot 注册表:内置条目和第三方条目都在,本插件不复制内置动作;
|
|
@@ -667,6 +696,7 @@ window.__ModuleLoader__.load({
|
|
|
667
696
|
window.setTimeout(() => {
|
|
668
697
|
rightClickMenuUntil = 0;
|
|
669
698
|
}, 600);
|
|
699
|
+
primeRowActionPointer(trigger);
|
|
670
700
|
if (menu !== null) {
|
|
671
701
|
menu.anchor.props.onClick();
|
|
672
702
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-sidebar-row-menu",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DSH sidebar right-click menus: a self-composed menu for workspace rows, and the native slot menu opened at the pointer for session rows.",
|
|
6
6
|
"keywords": [
|
|
@@ -31,6 +31,7 @@
|
|
|
31
31
|
"lib",
|
|
32
32
|
"assets",
|
|
33
33
|
"scripts/install.ps1",
|
|
34
|
+
"scripts/marketplace-preflight.mjs",
|
|
34
35
|
"cordis.patch.yml",
|
|
35
36
|
"README.md",
|
|
36
37
|
"README.en.md",
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const root = join(dirname(fileURLToPath(import.meta.url)), '..');
|
|
6
|
+
const offline = process.argv.includes('--offline');
|
|
7
|
+
const entryPath = join(root, 'marketplace', 'TLEWA__dsh-sidebar-row-menu.yml');
|
|
8
|
+
const iconPath = join(root, 'assets', 'icon-180.png');
|
|
9
|
+
const repoSlug = 'TLEWA/dsh-sidebar-row-menu';
|
|
10
|
+
|
|
11
|
+
let failures = 0;
|
|
12
|
+
let warnings = 0;
|
|
13
|
+
|
|
14
|
+
const pass = (message, detail = '') => console.log(`PASS ${message}${detail ? ` — ${detail}` : ''}`);
|
|
15
|
+
const warn = (message, detail = '') => {
|
|
16
|
+
warnings += 1;
|
|
17
|
+
console.log(`WARN ${message}${detail ? ` — ${detail}` : ''}`);
|
|
18
|
+
};
|
|
19
|
+
const fail = (message, detail = '') => {
|
|
20
|
+
failures += 1;
|
|
21
|
+
console.log(`FAIL ${message}${detail ? ` — ${detail}` : ''}`);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
// The submission entry is local-only (git-ignored), so a fresh clone has no
|
|
25
|
+
// marketplace/ directory. Treat that as "nothing to check", not as a failure.
|
|
26
|
+
if (!existsSync(entryPath)) {
|
|
27
|
+
warn('marketplace entry', 'marketplace/ is local-only and absent in this checkout');
|
|
28
|
+
console.log('\nREADY — 0 failure(s), 1 warning(s)');
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readPngSize(file) {
|
|
33
|
+
const buffer = readFileSync(file);
|
|
34
|
+
const signature = buffer.subarray(0, 8).toString('hex');
|
|
35
|
+
if (signature !== '89504e470d0a1a0a') return null;
|
|
36
|
+
return { width: buffer.readUInt32BE(16), height: buffer.readUInt32BE(20) };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// --- package manifest -------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
42
|
+
pkg.name === 'dsh-sidebar-row-menu'
|
|
43
|
+
? pass('package name', pkg.name)
|
|
44
|
+
: fail('package name', `expected dsh-sidebar-row-menu, got ${pkg.name}`);
|
|
45
|
+
|
|
46
|
+
if (pkg.dsh?.bundle?.patch) {
|
|
47
|
+
pass('dsh.bundle.patch', pkg.dsh.bundle.patch);
|
|
48
|
+
const patchPath = join(root, pkg.dsh.bundle.patch);
|
|
49
|
+
if (!existsSync(patchPath)) {
|
|
50
|
+
fail('bundle patch exists', pkg.dsh.bundle.patch);
|
|
51
|
+
} else {
|
|
52
|
+
const patch = readFileSync(patchPath, 'utf8');
|
|
53
|
+
if (/insert:/.test(patch) && patch.includes(pkg.name)) {
|
|
54
|
+
pass('bundle patch content', 'insert + package name');
|
|
55
|
+
} else {
|
|
56
|
+
fail('bundle patch content', 'expected an insert entry naming the package');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
fail('dsh.bundle.patch', 'missing — dsh.client alone is not installable');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pkg.license === 'MIT' ? pass('license', 'MIT') : fail('license', `got ${pkg.license}`);
|
|
64
|
+
String(pkg.repository?.url ?? '').includes(repoSlug)
|
|
65
|
+
? pass('repository', pkg.repository.url)
|
|
66
|
+
: fail('repository', 'does not point at the GitHub repo');
|
|
67
|
+
|
|
68
|
+
// --- storefront icon --------------------------------------------------------
|
|
69
|
+
|
|
70
|
+
if (!existsSync(iconPath)) {
|
|
71
|
+
fail('assets/icon-180.png', 'missing');
|
|
72
|
+
} else {
|
|
73
|
+
const size = readPngSize(iconPath);
|
|
74
|
+
if (!size) {
|
|
75
|
+
fail('icon format', 'not a PNG');
|
|
76
|
+
} else if (size.width !== 180 || size.height !== 180) {
|
|
77
|
+
fail('icon dimensions', `${size.width}x${size.height}, expected 180x180`);
|
|
78
|
+
} else {
|
|
79
|
+
pass('icon', '180x180 PNG');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// --- submission entry -------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
if (!existsSync(entryPath)) {
|
|
86
|
+
fail('marketplace entry', 'missing');
|
|
87
|
+
} else {
|
|
88
|
+
const entry = readFileSync(entryPath, 'utf8');
|
|
89
|
+
const field = (name) => (entry.match(new RegExp(`^${name}:\\s*(.+)$`, 'm')) ?? [])[1]?.trim() ?? '';
|
|
90
|
+
const checks = [
|
|
91
|
+
['url', `https://github.com/${repoSlug}`],
|
|
92
|
+
['name', repoSlug],
|
|
93
|
+
['category', 'ui'],
|
|
94
|
+
['icon', `https://raw.githubusercontent.com/${repoSlug}/main/assets/icon-180.png`],
|
|
95
|
+
];
|
|
96
|
+
for (const [key, expected] of checks) {
|
|
97
|
+
const actual = field(key);
|
|
98
|
+
actual === expected
|
|
99
|
+
? pass(`entry.${key}`, actual)
|
|
100
|
+
: fail(`entry.${key}`, `expected ${expected}, got ${actual || '(missing)'}`);
|
|
101
|
+
}
|
|
102
|
+
/^\s+en:\s*\S/m.test(entry) ? pass('entry.description.en') : fail('entry.description.en', 'missing');
|
|
103
|
+
/^\s+zh:\s*\S/m.test(entry) ? pass('entry.description.zh') : warn('entry.description.zh', 'missing (optional)');
|
|
104
|
+
if (!/^tarball:\s*https:\/\/github\.com\/.+\/releases\/(download|latest\/download)\/.+\.tgz$/m.test(entry)) {
|
|
105
|
+
fail('entry.tarball', 'missing or not a GitHub release .tgz URL');
|
|
106
|
+
} else {
|
|
107
|
+
pass('entry.tarball');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// --- repository live checks -------------------------------------------------
|
|
112
|
+
|
|
113
|
+
if (offline) {
|
|
114
|
+
warn('GitHub checks', 'skipped (--offline)');
|
|
115
|
+
} else {
|
|
116
|
+
try {
|
|
117
|
+
const response = await fetch(`https://api.github.com/repos/${repoSlug}`, {
|
|
118
|
+
headers: { accept: 'application/vnd.github+json', 'user-agent': 'dsh-sidebar-row-menu-preflight' },
|
|
119
|
+
signal: AbortSignal.timeout(15000),
|
|
120
|
+
});
|
|
121
|
+
if (!response.ok) throw new Error(`GitHub API ${response.status}`);
|
|
122
|
+
const repo = await response.json();
|
|
123
|
+
|
|
124
|
+
const created = Date.parse(repo.created_at);
|
|
125
|
+
const ageMs = Date.now() - created;
|
|
126
|
+
const eligible = new Date(created + 86400000);
|
|
127
|
+
if (ageMs >= 86400000) {
|
|
128
|
+
pass('repo age', `${(ageMs / 86400000).toFixed(1)} days`);
|
|
129
|
+
} else {
|
|
130
|
+
warn(
|
|
131
|
+
'repo age',
|
|
132
|
+
`${(ageMs / 3600000).toFixed(1)} hours — eligible at ${eligible.toISOString()} (${eligible.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' })})`,
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Array.isArray(repo.topics) && repo.topics.includes('dsh-plugin')
|
|
137
|
+
? pass('topic', 'dsh-plugin')
|
|
138
|
+
: fail('topic', 'dsh-plugin is missing — required by awesome-dsh-plugin');
|
|
139
|
+
|
|
140
|
+
repo.description ? pass('repo description', repo.description) : fail('repo description', 'empty');
|
|
141
|
+
|
|
142
|
+
if (existsSync(entryPath)) {
|
|
143
|
+
const entry = readFileSync(entryPath, 'utf8');
|
|
144
|
+
const tarball = (entry.match(/^tarball:\s*(\S+)$/m) ?? [])[1];
|
|
145
|
+
if (tarball) {
|
|
146
|
+
const head = await fetch(tarball, {
|
|
147
|
+
method: 'HEAD',
|
|
148
|
+
redirect: 'follow',
|
|
149
|
+
signal: AbortSignal.timeout(20000),
|
|
150
|
+
});
|
|
151
|
+
head.ok
|
|
152
|
+
? pass('tarball URL', `${head.status} ${tarball}`)
|
|
153
|
+
: fail('tarball URL', `${head.status} ${tarball}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const iconUrl = `https://raw.githubusercontent.com/${repoSlug}/main/assets/icon-180.png`;
|
|
158
|
+
const iconHead = await fetch(iconUrl, { method: 'HEAD', signal: AbortSignal.timeout(15000) });
|
|
159
|
+
iconHead.ok ? pass('icon URL', `${iconHead.status}`) : fail('icon URL', `${iconHead.status}`);
|
|
160
|
+
} catch (error) {
|
|
161
|
+
fail('GitHub checks', error instanceof Error ? error.message : String(error));
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log(`\n${failures === 0 ? 'READY' : 'NOT READY'} — ${failures} failure(s), ${warnings} warning(s)`);
|
|
166
|
+
if (failures > 0) {
|
|
167
|
+
console.log('Fix the FAIL lines before opening the awesome-dsh-plugin pull request.');
|
|
168
|
+
process.exitCode = 1;
|
|
169
|
+
}
|