poi-plugin-item-improvement2-beta 1.0.26 → 1.0.28
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.md +30 -18
- package/i18n/en-US.json +2 -1
- package/i18n/ja-JP.json +2 -1
- package/i18n/zh-CN.json +2 -1
- package/i18n/zh-TW.json +2 -1
- package/package.json +4 -8
- package/views/changelog.js +3 -0
- package/views/data-package.js +25 -6
- package/views/improvement-data-source.js +4 -0
- package/CHANGELOG.md +0 -107
- package/REFACTOR_NOTES.md +0 -43
- package/scripts/publish-beta.js +0 -163
- package/tests/improvement-data.test.js +0 -271
package/README.md
CHANGED
|
@@ -1,27 +1,39 @@
|
|
|
1
|
-
# Plugin
|
|
2
|
-
Show improvable items of the day
|
|
3
|
-
#### Usage
|
|
4
|
-
Put the folder into /path/to/poi/resources/app/plugins.
|
|
1
|
+
# Plugin Item Improvement
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
The plugin makes use of equipment improvement data from [Akashi List](https://akashi-list.me/).
|
|
3
|
+
Poi plugin for viewing KanColle equipment improvement schedules, complete recipe routes, costs, and required materials.
|
|
8
4
|
|
|
9
|
-
##
|
|
5
|
+
## Usage
|
|
10
6
|
|
|
11
|
-
|
|
7
|
+
Install the plugin through Poi, or place the package in Poi's plugin directory.
|
|
8
|
+
|
|
9
|
+
Improvement data and use-item assets are supplied by the local npm dependency `@sakura2333/kancolle-data`; the plugin does not download GitHub data at runtime.
|
|
10
|
+
|
|
11
|
+
## Development
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm
|
|
15
|
-
npm
|
|
14
|
+
npm ci --include=dev
|
|
15
|
+
npm test
|
|
16
|
+
npm pack --dry-run
|
|
16
17
|
```
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
`poi-plugin-item-improvement2-beta` with `poi-plugin-item-improvement2-beta-beta`, runs
|
|
20
|
-
`npm publish`, and restores the original files even when publishing fails.
|
|
21
|
-
Arguments after `--` are forwarded to `npm publish`.
|
|
19
|
+
The committed lockfile keeps the legacy Poi transpilation toolchain reproducible. CI tests both the locked minimum-compatible data package and the latest compatible data package.
|
|
22
20
|
|
|
23
|
-
##
|
|
21
|
+
## Publishing
|
|
22
|
+
|
|
23
|
+
Publish a compatible `@sakura2333/kancolle-data` release before publishing a plugin version that depends on it.
|
|
24
|
+
|
|
25
|
+
Official package:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm test
|
|
29
|
+
npm publish --registry=https://registry.npmjs.org/
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Beta package:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm run publish:beta:dry-run
|
|
36
|
+
npm run publish:beta
|
|
37
|
+
```
|
|
24
38
|
|
|
25
|
-
|
|
26
|
-
`@sakura2333/kancolle-data`. The plugin no longer downloads data from GitHub at runtime.
|
|
27
|
-
Publish the data package before publishing a plugin version that depends on it.
|
|
39
|
+
The beta script temporarily changes the package and runtime namespace to `poi-plugin-item-improvement2-beta-beta`, publishes it, and restores the source tree even when publication fails.
|
package/i18n/en-US.json
CHANGED
|
@@ -58,5 +58,6 @@
|
|
|
58
58
|
"changelog_1_0_22_reopen_notes": "A What’s New button was added to the toolbar so release notes can be reopened at any time.",
|
|
59
59
|
"changelog_1_0_21_stable_data": "Improvement information now loads and updates more reliably.",
|
|
60
60
|
"changelog_1_0_21_separate_routes": "Improvement routes with different materials, costs, or upgrade targets are now shown in separate tables.",
|
|
61
|
-
"changelog_1_0_21_tamanami_route": "Added Tamanami Kai Ni’s dedicated material route and kept it separate from the normal route."
|
|
61
|
+
"changelog_1_0_21_tamanami_route": "Added Tamanami Kai Ni’s dedicated material route and kept it separate from the normal route.",
|
|
62
|
+
"changelog_1_0_27_data_safety": "Improved data safety checks so incomplete or incompatible improvement information is rejected instead of being displayed incorrectly."
|
|
62
63
|
}
|
package/i18n/ja-JP.json
CHANGED
|
@@ -58,5 +58,6 @@
|
|
|
58
58
|
"changelog_1_0_22_reopen_notes": "ツールバーに「更新履歴」ボタンを追加し、いつでも変更内容を確認できるようにしました。",
|
|
59
59
|
"changelog_1_0_21_stable_data": "改修情報の読み込みと更新をより安定させました。",
|
|
60
60
|
"changelog_1_0_21_separate_routes": "必要装備、資材、更新先が異なる改修ルートを別々の表で表示するようにしました。",
|
|
61
|
-
"changelog_1_0_21_tamanami_route": "玉波改二専用の改修素材ルートを追加し、通常ルートと混在しないようにしました。"
|
|
61
|
+
"changelog_1_0_21_tamanami_route": "玉波改二専用の改修素材ルートを追加し、通常ルートと混在しないようにしました。",
|
|
62
|
+
"changelog_1_0_27_data_safety": "不完全または互換性のない改修情報を誤って表示しないよう、データ確認を強化しました。"
|
|
62
63
|
}
|
package/i18n/zh-CN.json
CHANGED
|
@@ -58,5 +58,6 @@
|
|
|
58
58
|
"changelog_1_0_22_reopen_notes": "工具栏新增“更新日志”按钮,可随时回看版本变化。",
|
|
59
59
|
"changelog_1_0_21_stable_data": "改修信息的加载和更新更加稳定。",
|
|
60
60
|
"changelog_1_0_21_separate_routes": "材料、资材或升级目标不同的改修路线现在会分表展示。",
|
|
61
|
-
"changelog_1_0_21_tamanami_route": "补充玉波改二专属的改修材料路线,避免与普通路线混在一起。"
|
|
61
|
+
"changelog_1_0_21_tamanami_route": "补充玉波改二专属的改修材料路线,避免与普通路线混在一起。",
|
|
62
|
+
"changelog_1_0_27_data_safety": "加强改修资料完整性检查,遇到不完整或不兼容的资料时会拒绝加载,避免显示错误内容。"
|
|
62
63
|
}
|
package/i18n/zh-TW.json
CHANGED
|
@@ -58,5 +58,6 @@
|
|
|
58
58
|
"changelog_1_0_22_reopen_notes": "工具列新增「更新日誌」按鈕,可隨時回看版本變更。",
|
|
59
59
|
"changelog_1_0_21_stable_data": "改修資訊的載入與更新更加穩定。",
|
|
60
60
|
"changelog_1_0_21_separate_routes": "材料、資材或升級目標不同的改修路線現在會分表顯示。",
|
|
61
|
-
"changelog_1_0_21_tamanami_route": "補充玉波改二專屬的改修材料路線,避免與一般路線混在一起。"
|
|
61
|
+
"changelog_1_0_21_tamanami_route": "補充玉波改二專屬的改修材料路線,避免與一般路線混在一起。",
|
|
62
|
+
"changelog_1_0_27_data_safety": "加強改修資料完整性檢查,遇到不完整或不相容的資料時會拒絕載入,避免顯示錯誤內容。"
|
|
62
63
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "poi-plugin-item-improvement2-beta",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.28",
|
|
4
|
+
"description": "View KanColle equipment improvement schedules, routes, costs, and required materials in Poi",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepack": "poi-util-transpile",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"dom-to-image": "^2.6.0",
|
|
36
36
|
"react-numeric-input": "^2.2.3",
|
|
37
|
-
"@sakura2333/kancolle-data": "
|
|
37
|
+
"@sakura2333/kancolle-data": ">=0.1.0 <0.3.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"babel-eslint": "^10.0.1",
|
|
@@ -63,10 +63,6 @@
|
|
|
63
63
|
"views/**/*.js",
|
|
64
64
|
"assets/**/*",
|
|
65
65
|
"i18n/*.json",
|
|
66
|
-
"
|
|
67
|
-
"tests/improvement-data.test.js",
|
|
68
|
-
"CHANGELOG.md",
|
|
69
|
-
"README.md",
|
|
70
|
-
"REFACTOR_NOTES.md"
|
|
66
|
+
"README.md"
|
|
71
67
|
]
|
|
72
68
|
}
|
package/views/changelog.js
CHANGED
|
@@ -13,6 +13,9 @@ const CHANGELOG_BASELINE_VERSION = '1.0.20'; // Keep in-app notes focused on use
|
|
|
13
13
|
|
|
14
14
|
exports.CHANGELOG_BASELINE_VERSION = CHANGELOG_BASELINE_VERSION;
|
|
15
15
|
const CHANGELOG = [{
|
|
16
|
+
version: '1.0.27',
|
|
17
|
+
items: ['changelog_1_0_27_data_safety']
|
|
18
|
+
}, {
|
|
16
19
|
version: '1.0.26',
|
|
17
20
|
items: ['changelog_1_0_26_useitem_icon']
|
|
18
21
|
}, {
|
package/views/data-package.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.
|
|
4
|
+
exports.validateSchemaVersion = exports.SUPPORTED_IMPROVEMENT_LIST_SCHEMA_VERSION = exports.SUPPORTED_IMPROVEMENT_SCHEMA_VERSION = exports.DATA_PACKAGE_NAME = exports.getUseitemIconPath = exports.getImprovementDataPaths = exports.getDataPackageManifest = void 0;
|
|
5
5
|
|
|
6
6
|
var _fs = _interopRequireDefault(require("fs"));
|
|
7
7
|
|
|
8
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
9
|
|
|
10
10
|
const PACKAGE_NAME = '@sakura2333/kancolle-data';
|
|
11
|
-
const
|
|
11
|
+
const IMPROVEMENT_SCHEMA_VERSION = 3;
|
|
12
|
+
const IMPROVEMENT_LIST_SCHEMA_VERSION = 2;
|
|
12
13
|
let dataPackage = null;
|
|
13
14
|
let manifest = null;
|
|
14
15
|
|
|
@@ -26,6 +27,14 @@ function loadDataPackage() {
|
|
|
26
27
|
return dataPackage;
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
function requireExactSchema(value, expected, label) {
|
|
31
|
+
const schemaVersion = Number(value);
|
|
32
|
+
|
|
33
|
+
if (!Number.isInteger(schemaVersion) || schemaVersion !== expected) {
|
|
34
|
+
throw new Error(`Unsupported ${label} schema ${value}; supported version is ${expected}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
29
38
|
function readManifest() {
|
|
30
39
|
if (manifest) return manifest;
|
|
31
40
|
const pkg = loadDataPackage();
|
|
@@ -41,8 +50,10 @@ function readManifest() {
|
|
|
41
50
|
throw new Error(`${PACKAGE_NAME} does not contain the improvement dataset`);
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
requireExactSchema(improvement.schemaVersion, IMPROVEMENT_SCHEMA_VERSION, 'improvement detail');
|
|
54
|
+
|
|
55
|
+
if (improvement.listSchemaVersion != null) {
|
|
56
|
+
requireExactSchema(improvement.listSchemaVersion, IMPROVEMENT_LIST_SCHEMA_VERSION, 'improvement list');
|
|
46
57
|
}
|
|
47
58
|
|
|
48
59
|
return manifest;
|
|
@@ -60,6 +71,10 @@ const getImprovementDataPaths = () => {
|
|
|
60
71
|
throw new Error(`${PACKAGE_NAME} improvement paths are incomplete`);
|
|
61
72
|
}
|
|
62
73
|
|
|
74
|
+
if (!_fs.default.existsSync(pkg.improvement.listPath) || !_fs.default.existsSync(pkg.improvement.detailPath)) {
|
|
75
|
+
throw new Error(`${PACKAGE_NAME} improvement files are missing`);
|
|
76
|
+
}
|
|
77
|
+
|
|
63
78
|
return {
|
|
64
79
|
listPath: pkg.improvement.listPath,
|
|
65
80
|
detailPath: pkg.improvement.detailPath
|
|
@@ -76,5 +91,9 @@ const getUseitemIconPath = id => {
|
|
|
76
91
|
exports.getUseitemIconPath = getUseitemIconPath;
|
|
77
92
|
const DATA_PACKAGE_NAME = PACKAGE_NAME;
|
|
78
93
|
exports.DATA_PACKAGE_NAME = DATA_PACKAGE_NAME;
|
|
79
|
-
const
|
|
80
|
-
exports.
|
|
94
|
+
const SUPPORTED_IMPROVEMENT_SCHEMA_VERSION = IMPROVEMENT_SCHEMA_VERSION;
|
|
95
|
+
exports.SUPPORTED_IMPROVEMENT_SCHEMA_VERSION = SUPPORTED_IMPROVEMENT_SCHEMA_VERSION;
|
|
96
|
+
const SUPPORTED_IMPROVEMENT_LIST_SCHEMA_VERSION = IMPROVEMENT_LIST_SCHEMA_VERSION;
|
|
97
|
+
exports.SUPPORTED_IMPROVEMENT_LIST_SCHEMA_VERSION = SUPPORTED_IMPROVEMENT_LIST_SCHEMA_VERSION;
|
|
98
|
+
const validateSchemaVersion = requireExactSchema;
|
|
99
|
+
exports.validateSchemaVersion = validateSchemaVersion;
|
|
@@ -26,6 +26,10 @@ function validateListData(data) {
|
|
|
26
26
|
throw new Error('Invalid improvement list data');
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
if (Number(data.metadata.schemaVersion) !== 2 || !Array.isArray(data.metadata.rowSchema) || data.metadata.rowSchema.length !== 2 || data.metadata.rowSchema[0] !== 'itemId' || data.metadata.rowSchema[1] !== 'assistantTexts') {
|
|
30
|
+
throw new Error('Unsupported improvement list schema');
|
|
31
|
+
}
|
|
32
|
+
|
|
29
33
|
data.data.forEach((rows, viewIndex) => {
|
|
30
34
|
if (!Array.isArray(rows)) {
|
|
31
35
|
throw new Error(`Invalid improvement list view: ${viewIndex}`);
|
package/CHANGELOG.md
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to `poi-plugin-item-improvement2-beta` are documented here.
|
|
4
|
-
|
|
5
|
-
## [Unreleased]
|
|
6
|
-
|
|
7
|
-
### Planned
|
|
8
|
-
|
|
9
|
-
- Add consumer views for equipment acquisition sources and special ship bonuses from `@sakura2333/kancolle-data`.
|
|
10
|
-
- Remove the remaining local compatibility icon after the shared data package contains it.
|
|
11
|
-
|
|
12
|
-
## [1.0.26] - 2026-06-28
|
|
13
|
-
|
|
14
|
-
### Fixed
|
|
15
|
-
|
|
16
|
-
- Ensured the local use-item 71 compatibility PNG is explicitly included in official and beta npm packages.
|
|
17
|
-
- Re-encoded the unchanged icon pixels so Git patches and repository updates physically carry the binary asset instead of relying on an existing working-tree copy.
|
|
18
|
-
|
|
19
|
-
### Changed
|
|
20
|
-
|
|
21
|
-
- Added an explicit npm `files` allowlist covering runtime JavaScript, localized resources, styles, and all icon assets.
|
|
22
|
-
|
|
23
|
-
### Validation
|
|
24
|
-
|
|
25
|
-
- Added a package dry-run assertion that fails when `assets/icon/71.png` is absent from the npm tarball file list.
|
|
26
|
-
- Added PNG signature validation for the compatibility icon.
|
|
27
|
-
|
|
28
|
-
## [1.0.25] - 2026-06-28
|
|
29
|
-
|
|
30
|
-
### Changed
|
|
31
|
-
|
|
32
|
-
- Rewrote the in-app release notes to describe user-visible behavior instead of npm, schema, repository, and packaging implementation details.
|
|
33
|
-
- Added localized user-facing release-note copy for Simplified Chinese, Traditional Chinese, Japanese, and English.
|
|
34
|
-
- Kept detailed engineering changes in this repository `CHANGELOG.md` for development and release auditing.
|
|
35
|
-
|
|
36
|
-
### Validation
|
|
37
|
-
|
|
38
|
-
- Added coverage that every in-app changelog key exists in all supported locales.
|
|
39
|
-
- Added coverage preventing technical package terminology from leaking back into the Simplified Chinese in-app release notes.
|
|
40
|
-
|
|
41
|
-
## [1.0.24] - 2026-06-28
|
|
42
|
-
|
|
43
|
-
### Changed
|
|
44
|
-
|
|
45
|
-
- Relaxed the shared data dependency from exact `0.1.0` to the compatible `^0.1.0` range.
|
|
46
|
-
- New plugin installs and dependency refreshes can now consume automatically published `0.1.x` data-only patch releases without requiring a plugin release for every dataset refresh.
|
|
47
|
-
|
|
48
|
-
### Compatibility
|
|
49
|
-
|
|
50
|
-
- Data package minor/schema releases remain blocked until the plugin explicitly updates its supported dependency range and schema checks.
|
|
51
|
-
- Existing installed plugins still need their dependency installation to be refreshed before npm can resolve a newer data patch.
|
|
52
|
-
|
|
53
|
-
## [1.0.23] - 2026-06-28
|
|
54
|
-
|
|
55
|
-
### Added
|
|
56
|
-
|
|
57
|
-
- Added the versioned `@sakura2333/kancolle-data@0.1.0` runtime dependency.
|
|
58
|
-
- Added a data-package adapter that exposes improvement list/detail paths and validates the supported improvement schema.
|
|
59
|
-
- Added shared use-item icon lookup through the data package.
|
|
60
|
-
|
|
61
|
-
### Changed
|
|
62
|
-
|
|
63
|
-
- Moved improvement list data, improvement detail data, and most use-item PNG assets out of the plugin package.
|
|
64
|
-
- Removed runtime GitHub data synchronization; all required data is installed locally by npm.
|
|
65
|
-
- Changed official and beta builds to consume the same versioned data package.
|
|
66
|
-
- Reduced the plugin tarball from the historical embedded-data size to a lightweight code package.
|
|
67
|
-
- Kept the local `71.png` and generic SVG as temporary compatibility assets.
|
|
68
|
-
|
|
69
|
-
### Fixed
|
|
70
|
-
|
|
71
|
-
- Fixed plugin startup being dependent on GitHub Raw availability and network conditions.
|
|
72
|
-
- Fixed data and PNG updates requiring duplicate copies in the Spider and plugin repositories.
|
|
73
|
-
|
|
74
|
-
### Compatibility
|
|
75
|
-
|
|
76
|
-
- Requires `@sakura2333/kancolle-data` with a supported improvement schema.
|
|
77
|
-
- Publish the data package before publishing a plugin version that depends on it.
|
|
78
|
-
|
|
79
|
-
## [1.0.22] - 2026-06-28
|
|
80
|
-
|
|
81
|
-
### Added
|
|
82
|
-
|
|
83
|
-
- Added a localized release-notes dialog shown once after a version change.
|
|
84
|
-
- Added a toolbar entry for reopening the release notes manually.
|
|
85
|
-
- Added `publish:beta` and `publish:beta:dry-run` scripts.
|
|
86
|
-
|
|
87
|
-
### Changed
|
|
88
|
-
|
|
89
|
-
- Beta publishing temporarily changes package and runtime namespaces to `poi-plugin-item-improvement2-beta-beta` and always restores the working tree afterward.
|
|
90
|
-
|
|
91
|
-
## [1.0.21] - 2026-06-28
|
|
92
|
-
|
|
93
|
-
### Added
|
|
94
|
-
|
|
95
|
-
- Added separate list and detail data projections.
|
|
96
|
-
- Added support for multiple independent improvement recipe routes.
|
|
97
|
-
- Added the Tamanami Kai Ni assistant-specific material route.
|
|
98
|
-
|
|
99
|
-
### Changed
|
|
100
|
-
|
|
101
|
-
- Changed the detail UI to render one table per complete recipe route.
|
|
102
|
-
- Unified list and detail assistant presentation through normalized view models.
|
|
103
|
-
|
|
104
|
-
### Fixed
|
|
105
|
-
|
|
106
|
-
- Fixed routes with different materials, costs, or upgrade targets sharing the first route's table header.
|
|
107
|
-
- Fixed the default route and Tamanami Kai Ni route being merged back together in the UI.
|
package/REFACTOR_NOTES.md
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# Data package and route-aware UI
|
|
2
|
-
|
|
3
|
-
## Runtime data
|
|
4
|
-
|
|
5
|
-
The plugin consumes the versioned npm dependency `@sakura2333/kancolle-data`:
|
|
6
|
-
|
|
7
|
-
- `improvement/list.json`: compact all + seven-day list projection.
|
|
8
|
-
- `improvement/detail.nedb`: full equipment detail and recipe routes.
|
|
9
|
-
- `assets/useitems/*.png`: shared use-item icons.
|
|
10
|
-
|
|
11
|
-
The plugin no longer downloads GitHub files at runtime and no longer carries duplicate
|
|
12
|
-
improvement datasets. `assets/icon/useitem.svg` remains the generic fallback; the legacy
|
|
13
|
-
`71.png` is temporarily retained until it is present in the data package.
|
|
14
|
-
|
|
15
|
-
## Responsibility boundary
|
|
16
|
-
|
|
17
|
-
- Spider collects and validates sources, normalizes assistant IDs, splits concrete recipes,
|
|
18
|
-
and publishes `@sakura2333/kancolle-data`.
|
|
19
|
-
- The data package exposes stable local paths and dataset manifests.
|
|
20
|
-
- The plugin reads the installed package, validates the supported improvement schema, and
|
|
21
|
-
maps the data into UI view models.
|
|
22
|
-
- The list page reads backend-provided `[itemId, assistantTexts]` rows.
|
|
23
|
-
- The detail page displays every `improvementList[]` entry as one independent route.
|
|
24
|
-
|
|
25
|
-
## Multiple route support
|
|
26
|
-
|
|
27
|
-
`DetailRow` renders one table per improvement route. Each table uses its own base resources,
|
|
28
|
-
stage costs, consumables, MAX target, and assistant schedule. This supports assistant-specific
|
|
29
|
-
recipes such as the `玉波改二` route for `12.7cm連装砲D型改二`.
|
|
30
|
-
|
|
31
|
-
## Publish order
|
|
32
|
-
|
|
33
|
-
1. Build and publish `@sakura2333/kancolle-data` from the Spider repository.
|
|
34
|
-
2. Install development dependencies for this plugin.
|
|
35
|
-
3. Run tests and publish the official or beta plugin.
|
|
36
|
-
|
|
37
|
-
```bash
|
|
38
|
-
npm ci --include=dev
|
|
39
|
-
npm test
|
|
40
|
-
npm publish
|
|
41
|
-
# or
|
|
42
|
-
npm run publish:beta
|
|
43
|
-
```
|
package/scripts/publish-beta.js
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
'use strict'
|
|
4
|
-
|
|
5
|
-
const fs = require('fs')
|
|
6
|
-
const path = require('path')
|
|
7
|
-
const { spawn } = require('child_process')
|
|
8
|
-
|
|
9
|
-
const ROOT = path.resolve(__dirname, '..')
|
|
10
|
-
const OFFICIAL_NAME = 'poi-plugin-item-improvement2'
|
|
11
|
-
const BETA_NAME = 'poi-plugin-item-improvement2-beta'
|
|
12
|
-
const SELF_PATH = path.resolve(__filename)
|
|
13
|
-
const SKIP_DIRECTORIES = new Set(['.git', 'node_modules'])
|
|
14
|
-
const MAX_TEXT_FILE_SIZE = 5 * 1024 * 1024
|
|
15
|
-
|
|
16
|
-
function isProbablyText(buffer) {
|
|
17
|
-
return !buffer.includes(0)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function collectFiles(directory, output = []) {
|
|
21
|
-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
22
|
-
if (entry.isDirectory() && SKIP_DIRECTORIES.has(entry.name)) continue
|
|
23
|
-
|
|
24
|
-
const absolutePath = path.join(directory, entry.name)
|
|
25
|
-
if (entry.isDirectory()) {
|
|
26
|
-
collectFiles(absolutePath, output)
|
|
27
|
-
} else if (entry.isFile()) {
|
|
28
|
-
output.push(absolutePath)
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return output
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function buildReplacementPlan() {
|
|
35
|
-
const replacements = []
|
|
36
|
-
|
|
37
|
-
for (const filePath of collectFiles(ROOT)) {
|
|
38
|
-
if (path.resolve(filePath) === SELF_PATH) continue
|
|
39
|
-
|
|
40
|
-
const stat = fs.statSync(filePath)
|
|
41
|
-
if (stat.size > MAX_TEXT_FILE_SIZE) continue
|
|
42
|
-
|
|
43
|
-
const original = fs.readFileSync(filePath)
|
|
44
|
-
if (!isProbablyText(original)) continue
|
|
45
|
-
|
|
46
|
-
const originalText = original.toString('utf8')
|
|
47
|
-
if (!originalText.includes(OFFICIAL_NAME)) continue
|
|
48
|
-
|
|
49
|
-
const betaText = originalText.split(OFFICIAL_NAME).join(BETA_NAME)
|
|
50
|
-
replacements.push({
|
|
51
|
-
filePath,
|
|
52
|
-
original,
|
|
53
|
-
replacement: Buffer.from(betaText, 'utf8'),
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return replacements
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function assertOfficialWorkspace() {
|
|
61
|
-
const packageJsonPath = path.join(ROOT, 'package.json')
|
|
62
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
|
|
63
|
-
|
|
64
|
-
if (packageJson.name !== OFFICIAL_NAME) {
|
|
65
|
-
throw new Error(
|
|
66
|
-
`Expected package.json name to be ${OFFICIAL_NAME}, got ${packageJson.name}`
|
|
67
|
-
)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function applyReplacementPlan(plan) {
|
|
72
|
-
for (const entry of plan) {
|
|
73
|
-
fs.writeFileSync(entry.filePath, entry.replacement)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function restoreReplacementPlan(plan) {
|
|
78
|
-
for (const entry of plan) {
|
|
79
|
-
fs.writeFileSync(entry.filePath, entry.original)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function relative(filePath) {
|
|
84
|
-
return path.relative(ROOT, filePath) || '.'
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function runNpmPublish(args) {
|
|
88
|
-
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'
|
|
89
|
-
|
|
90
|
-
return new Promise((resolve, reject) => {
|
|
91
|
-
const child = spawn(npmCommand, ['publish', ...args], {
|
|
92
|
-
cwd: ROOT,
|
|
93
|
-
env: process.env,
|
|
94
|
-
stdio: 'inherit',
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
const forwardSignal = signal => {
|
|
98
|
-
if (!child.killed) child.kill(signal)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
process.once('SIGINT', forwardSignal)
|
|
102
|
-
process.once('SIGTERM', forwardSignal)
|
|
103
|
-
|
|
104
|
-
child.once('error', error => {
|
|
105
|
-
process.removeListener('SIGINT', forwardSignal)
|
|
106
|
-
process.removeListener('SIGTERM', forwardSignal)
|
|
107
|
-
reject(error)
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
child.once('exit', (code, signal) => {
|
|
111
|
-
process.removeListener('SIGINT', forwardSignal)
|
|
112
|
-
process.removeListener('SIGTERM', forwardSignal)
|
|
113
|
-
|
|
114
|
-
if (signal) {
|
|
115
|
-
reject(new Error(`npm publish terminated by ${signal}`))
|
|
116
|
-
} else {
|
|
117
|
-
resolve(code == null ? 1 : code)
|
|
118
|
-
}
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function main() {
|
|
124
|
-
assertOfficialWorkspace()
|
|
125
|
-
|
|
126
|
-
const plan = buildReplacementPlan()
|
|
127
|
-
if (plan.length === 0) {
|
|
128
|
-
throw new Error(`No occurrences of ${OFFICIAL_NAME} were found`)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
console.log(`Temporarily switching package namespace:`)
|
|
132
|
-
console.log(` ${OFFICIAL_NAME} -> ${BETA_NAME}`)
|
|
133
|
-
console.log('Changed files:')
|
|
134
|
-
for (const entry of plan) {
|
|
135
|
-
console.log(` - ${relative(entry.filePath)}`)
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
let exitCode = 1
|
|
139
|
-
applyReplacementPlan(plan)
|
|
140
|
-
|
|
141
|
-
try {
|
|
142
|
-
const betaPackage = JSON.parse(
|
|
143
|
-
fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8')
|
|
144
|
-
)
|
|
145
|
-
if (betaPackage.name !== BETA_NAME) {
|
|
146
|
-
throw new Error('Temporary beta package-name replacement failed')
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
exitCode = await runNpmPublish(process.argv.slice(2))
|
|
150
|
-
} finally {
|
|
151
|
-
restoreReplacementPlan(plan)
|
|
152
|
-
console.log(`Restored workspace namespace to ${OFFICIAL_NAME}`)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (exitCode !== 0) {
|
|
156
|
-
throw new Error(`npm publish exited with code ${exitCode}`)
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
main().catch(error => {
|
|
161
|
-
console.error(`[publish:beta] ${error.message}`)
|
|
162
|
-
process.exitCode = 1
|
|
163
|
-
})
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
const assert = require('assert')
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const { execFileSync } = require('child_process')
|
|
5
|
-
const {
|
|
6
|
-
buildAssistantTextByDay,
|
|
7
|
-
buildImprovementItem,
|
|
8
|
-
createShipNameResolver,
|
|
9
|
-
normalizeAssistant,
|
|
10
|
-
normalizeListProjection,
|
|
11
|
-
normalizeShipIds,
|
|
12
|
-
} = require('../views/improvement-data.js')
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const {
|
|
16
|
-
CHANGELOG,
|
|
17
|
-
compareVersions,
|
|
18
|
-
getChangelogEntriesSince,
|
|
19
|
-
} = require('../views/changelog.js')
|
|
20
|
-
|
|
21
|
-
assert.strictEqual(compareVersions('1.0.22', '1.0.21'), 1)
|
|
22
|
-
assert.strictEqual(compareVersions('1.0.21', '1.0.21'), 0)
|
|
23
|
-
assert.strictEqual(compareVersions('1.0.20', '1.0.21'), -1)
|
|
24
|
-
assert.deepStrictEqual(
|
|
25
|
-
getChangelogEntriesSince('1.0.21').map(entry => entry.version),
|
|
26
|
-
['1.0.26', '1.0.25', '1.0.24', '1.0.23', '1.0.22']
|
|
27
|
-
)
|
|
28
|
-
assert.deepStrictEqual(
|
|
29
|
-
getChangelogEntriesSince(null).map(entry => entry.version),
|
|
30
|
-
['1.0.26', '1.0.25', '1.0.24', '1.0.23', '1.0.22', '1.0.21']
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
const localeNames = ['zh-CN', 'zh-TW', 'ja-JP', 'en-US']
|
|
34
|
-
const locales = localeNames.reduce((result, localeName) => {
|
|
35
|
-
const localePath = path.join(__dirname, '..', 'i18n', `${localeName}.json`)
|
|
36
|
-
result[localeName] = JSON.parse(fs.readFileSync(localePath, 'utf8'))
|
|
37
|
-
return result
|
|
38
|
-
}, {})
|
|
39
|
-
|
|
40
|
-
const changelogKeys = CHANGELOG.reduce(
|
|
41
|
-
(keys, entry) => keys.concat(entry.items),
|
|
42
|
-
[]
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
localeNames.forEach(localeName => {
|
|
46
|
-
changelogKeys.forEach(key => {
|
|
47
|
-
assert.strictEqual(
|
|
48
|
-
typeof locales[localeName][key],
|
|
49
|
-
'string',
|
|
50
|
-
`${localeName} is missing changelog entry ${key}`
|
|
51
|
-
)
|
|
52
|
-
assert.ok(
|
|
53
|
-
locales[localeName][key].trim().length > 0,
|
|
54
|
-
`${localeName} has an empty changelog entry ${key}`
|
|
55
|
-
)
|
|
56
|
-
})
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
const technicalTerms = [
|
|
60
|
-
'@sakura2333/kancolle-data',
|
|
61
|
-
'npm',
|
|
62
|
-
'Schema',
|
|
63
|
-
'0.1.x',
|
|
64
|
-
'PNG',
|
|
65
|
-
'GitHub',
|
|
66
|
-
]
|
|
67
|
-
const simplifiedChineseNotes = changelogKeys
|
|
68
|
-
.map(key => locales['zh-CN'][key])
|
|
69
|
-
.join('\n')
|
|
70
|
-
technicalTerms.forEach(term => {
|
|
71
|
-
assert.strictEqual(
|
|
72
|
-
simplifiedChineseNotes.includes(term),
|
|
73
|
-
false,
|
|
74
|
-
`user-facing changelog should not contain technical term: ${term}`
|
|
75
|
-
)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
const projectRoot = path.join(__dirname, '..')
|
|
79
|
-
const compatibilityIconPath = path.join(projectRoot, 'assets', 'icon', '71.png')
|
|
80
|
-
const pngSignature = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])
|
|
81
|
-
assert.ok(fs.existsSync(compatibilityIconPath), 'compatibility icon 71.png is missing')
|
|
82
|
-
assert.ok(
|
|
83
|
-
fs.readFileSync(compatibilityIconPath).subarray(0, 8).equals(pngSignature),
|
|
84
|
-
'compatibility icon 71.png is not a valid PNG'
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
const dryRunOutput = execFileSync(
|
|
88
|
-
process.platform === 'win32' ? 'npm.cmd' : 'npm',
|
|
89
|
-
['pack', '--dry-run', '--json', '--ignore-scripts'],
|
|
90
|
-
{ cwd: projectRoot, encoding: 'utf8' }
|
|
91
|
-
)
|
|
92
|
-
const dryRun = JSON.parse(dryRunOutput)
|
|
93
|
-
const packedFiles = new Set(dryRun[0].files.map(file => file.path))
|
|
94
|
-
assert.ok(
|
|
95
|
-
packedFiles.has('assets/icon/71.png'),
|
|
96
|
-
'npm package is missing assets/icon/71.png'
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const ships = {
|
|
101
|
-
89: { api_id: 89, api_name: '鳳翔' },
|
|
102
|
-
622: { api_id: 622, api_name: '夕張改二' },
|
|
103
|
-
623: { api_id: 623, api_name: '夕張改二特' },
|
|
104
|
-
624: { api_id: 624, api_name: '夕張改二丁' },
|
|
105
|
-
718: { api_id: 718, api_name: '玉波改' },
|
|
106
|
-
1033: { api_id: 1033, api_name: '玉波改二' },
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const resolveShipName = createShipNameResolver(ships, name => `local:${name}`)
|
|
110
|
-
|
|
111
|
-
const exact = normalizeAssistant({
|
|
112
|
-
id: [89],
|
|
113
|
-
text: '鳳翔',
|
|
114
|
-
week: [true, false, false, false, false, false, false],
|
|
115
|
-
}, resolveShipName)
|
|
116
|
-
assert.deepStrictEqual(exact.shipIds, [89])
|
|
117
|
-
assert.strictEqual(exact.idsComplete, true)
|
|
118
|
-
assert.strictEqual(exact.displayText, 'local:鳳翔')
|
|
119
|
-
|
|
120
|
-
const legacyIrregular = normalizeAssistant({
|
|
121
|
-
id: [622],
|
|
122
|
-
text: '夕張改二/特/丁',
|
|
123
|
-
week: [true, true, true, true, true, true, true],
|
|
124
|
-
}, resolveShipName)
|
|
125
|
-
assert.strictEqual(legacyIrregular.idsComplete, false)
|
|
126
|
-
assert.strictEqual(legacyIrregular.displayText, '夕張改二/特/丁')
|
|
127
|
-
|
|
128
|
-
const generatedButNotConnected = normalizeAssistant({
|
|
129
|
-
id: [622],
|
|
130
|
-
shipIdList: [622, 623, 624],
|
|
131
|
-
text: '夕張改二/特/丁',
|
|
132
|
-
parseStatus: 'resolved',
|
|
133
|
-
week: [true, true, true, true, true, true, true],
|
|
134
|
-
}, resolveShipName)
|
|
135
|
-
assert.strictEqual(generatedButNotConnected.idsComplete, false)
|
|
136
|
-
assert.strictEqual(generatedButNotConnected.displayText, '夕張改二/特/丁')
|
|
137
|
-
|
|
138
|
-
const resolvedMultiple = normalizeAssistant({
|
|
139
|
-
id: [622, 623, 624],
|
|
140
|
-
text: '夕張改二/特/丁',
|
|
141
|
-
week: [true, true, true, true, true, true, true],
|
|
142
|
-
}, resolveShipName)
|
|
143
|
-
assert.strictEqual(resolvedMultiple.idsComplete, true)
|
|
144
|
-
assert.strictEqual(
|
|
145
|
-
resolvedMultiple.displayText,
|
|
146
|
-
'local:夕張改二 / local:夕張改二特 / local:夕張改二丁'
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
const explicitSingle = normalizeAssistant({
|
|
150
|
-
id: [622],
|
|
151
|
-
text: '夕張改二のみ',
|
|
152
|
-
idsComplete: true,
|
|
153
|
-
week: [true, true, true, true, true, true, true],
|
|
154
|
-
}, resolveShipName)
|
|
155
|
-
assert.strictEqual(explicitSingle.displayText, 'local:夕張改二')
|
|
156
|
-
|
|
157
|
-
const unknown = normalizeAssistant({
|
|
158
|
-
shipIds: [9999],
|
|
159
|
-
resolved: true,
|
|
160
|
-
week: [true],
|
|
161
|
-
}, resolveShipName)
|
|
162
|
-
assert.strictEqual(unknown.displayText, '#9999')
|
|
163
|
-
|
|
164
|
-
assert.deepStrictEqual(normalizeShipIds({ id: ['89', 89, 0, 'bad'] }), [89])
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const noSpecificAssistant = normalizeAssistant({
|
|
168
|
-
id: [0],
|
|
169
|
-
text: '',
|
|
170
|
-
week: [true, true, false, false, false, false, false],
|
|
171
|
-
}, resolveShipName)
|
|
172
|
-
assert.deepStrictEqual(noSpecificAssistant.shipIds, [])
|
|
173
|
-
assert.strictEqual(noSpecificAssistant.displayText, '')
|
|
174
|
-
assert.deepStrictEqual(noSpecificAssistant.days, [0, 1])
|
|
175
|
-
|
|
176
|
-
const improvementList = [
|
|
177
|
-
{
|
|
178
|
-
assistantList: [exact, legacyIrregular],
|
|
179
|
-
},
|
|
180
|
-
]
|
|
181
|
-
const textByDay = buildAssistantTextByDay(improvementList)
|
|
182
|
-
assert.strictEqual(textByDay[0], 'local:鳳翔 / 夕張改二/特/丁')
|
|
183
|
-
assert.strictEqual(textByDay[1], '夕張改二/特/丁')
|
|
184
|
-
assert.strictEqual(textByDay[-1], 'local:鳳翔 / 夕張改二/特/丁')
|
|
185
|
-
|
|
186
|
-
const item = buildImprovementItem({
|
|
187
|
-
id: 19,
|
|
188
|
-
improvementList: [
|
|
189
|
-
{
|
|
190
|
-
shipWeekList: [
|
|
191
|
-
{
|
|
192
|
-
id: [89],
|
|
193
|
-
text: '鳳翔',
|
|
194
|
-
week: [true, false, false, false, false, false, false],
|
|
195
|
-
},
|
|
196
|
-
],
|
|
197
|
-
},
|
|
198
|
-
],
|
|
199
|
-
}, { api_name: '九六式艦戦' }, resolveShipName)
|
|
200
|
-
assert.strictEqual(item.api_name, '九六式艦戦')
|
|
201
|
-
assert.strictEqual(item.improvementList[0].assistantList[0].displayText, 'local:鳳翔')
|
|
202
|
-
assert.strictEqual(item.assistantTextByDay[0], 'local:鳳翔')
|
|
203
|
-
assert.strictEqual(item.assistantTextByDay[1], '')
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const listProjection = normalizeListProjection({
|
|
207
|
-
metadata: { schemaVersion: 2 },
|
|
208
|
-
data: [
|
|
209
|
-
[[19, ['鳳翔', '鳳翔改二']]],
|
|
210
|
-
[[19, ['鳳翔']]],
|
|
211
|
-
[], [], [], [], [], [],
|
|
212
|
-
],
|
|
213
|
-
})
|
|
214
|
-
assert.deepStrictEqual(listProjection.itemIdsByDay[-1], [19])
|
|
215
|
-
assert.deepStrictEqual(listProjection.itemIdsByDay[0], [19])
|
|
216
|
-
assert.strictEqual(listProjection.assistantTextByItemId[19][-1], '鳳翔 / 鳳翔改二')
|
|
217
|
-
assert.strictEqual(listProjection.assistantTextByItemId[19][0], '鳳翔')
|
|
218
|
-
|
|
219
|
-
const kancolleData = require('@sakura2333/kancolle-data')
|
|
220
|
-
|
|
221
|
-
const {
|
|
222
|
-
DATA_PACKAGE_NAME,
|
|
223
|
-
MAX_SUPPORTED_IMPROVEMENT_SCHEMA_VERSION,
|
|
224
|
-
getDataPackageManifest,
|
|
225
|
-
getImprovementDataPaths,
|
|
226
|
-
getUseitemIconPath,
|
|
227
|
-
} = require('../views/data-package.js')
|
|
228
|
-
|
|
229
|
-
const packageManifest = getDataPackageManifest()
|
|
230
|
-
assert.strictEqual(DATA_PACKAGE_NAME, '@sakura2333/kancolle-data')
|
|
231
|
-
assert.strictEqual(packageManifest.datasets.improvement.schemaVersion, 3)
|
|
232
|
-
assert.strictEqual(MAX_SUPPORTED_IMPROVEMENT_SCHEMA_VERSION, 3)
|
|
233
|
-
assert.ok(fs.existsSync(getImprovementDataPaths().listPath))
|
|
234
|
-
assert.ok(fs.existsSync(getImprovementDataPaths().detailPath))
|
|
235
|
-
assert.ok(fs.existsSync(getUseitemIconPath(57)))
|
|
236
|
-
const listAsset = JSON.parse(fs.readFileSync(kancolleData.improvement.listPath, 'utf8'))
|
|
237
|
-
const detailIds = new Set(
|
|
238
|
-
fs.readFileSync(kancolleData.improvement.detailPath, 'utf8')
|
|
239
|
-
.split('\n')
|
|
240
|
-
.filter(Boolean)
|
|
241
|
-
.map(line => JSON.parse(line).id)
|
|
242
|
-
)
|
|
243
|
-
assert.strictEqual(listAsset.metadata.schemaVersion, 2)
|
|
244
|
-
assert.ok(fs.existsSync(kancolleData.manifestPath))
|
|
245
|
-
assert.ok(fs.existsSync(kancolleData.assets.useitemPath(57)))
|
|
246
|
-
assert.strictEqual(listAsset.data.length, 8)
|
|
247
|
-
listAsset.data.forEach(rows => rows.forEach(([itemId]) => assert.ok(detailIds.has(itemId))))
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
const detailRows = fs.readFileSync(kancolleData.improvement.detailPath, 'utf8')
|
|
251
|
-
.split('\n')
|
|
252
|
-
.filter(Boolean)
|
|
253
|
-
.map(line => JSON.parse(line))
|
|
254
|
-
const tamanamiRouteItem = detailRows.find(row => row.id === 267)
|
|
255
|
-
assert.ok(tamanamiRouteItem)
|
|
256
|
-
assert.strictEqual(tamanamiRouteItem.improvementList.length, 2)
|
|
257
|
-
const normalRoute = tamanamiRouteItem.improvementList.find(route => route.routeType === 'default')
|
|
258
|
-
const specialRoute = tamanamiRouteItem.improvementList.find(route => route.routeType === 'assistant-specific')
|
|
259
|
-
assert.ok(normalRoute)
|
|
260
|
-
assert.ok(specialRoute)
|
|
261
|
-
assert.deepStrictEqual(specialRoute.routeShipIds, [1033])
|
|
262
|
-
assert.deepStrictEqual(specialRoute.stageList[0].consumables, [{ id: 10, count: 3, type: 0 }])
|
|
263
|
-
assert.deepStrictEqual(normalRoute.stageList[0].consumables, [{ id: 3, count: 2, type: 0 }])
|
|
264
|
-
const normalizedTamanami = buildImprovementItem(tamanamiRouteItem, { api_name: tamanamiRouteItem.name }, resolveShipName)
|
|
265
|
-
assert.strictEqual(normalizedTamanami.improvementList.length, 2)
|
|
266
|
-
assert.strictEqual(
|
|
267
|
-
normalizedTamanami.improvementList.find(route => route.routeType === 'assistant-specific').assistantList[0].displayText,
|
|
268
|
-
'local:玉波改二'
|
|
269
|
-
)
|
|
270
|
-
|
|
271
|
-
console.log('improvement-data tests passed')
|