mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-28 14:30:39 +01:00
Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
This commit is contained in:
commit
fc4c868269
14 changed files with 3506 additions and 6 deletions
43
.github/workflows/changelog-check.yml
vendored
Normal file
43
.github/workflows/changelog-check.yml
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
name: Check the description in CHANGELOG.md
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
check-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout head
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4.0.1
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Checkout base
|
||||
run: |
|
||||
mkdir _base
|
||||
cp -r .git _base/.git
|
||||
cd _base
|
||||
git fetch --depth 1 origin ${{ github.base_ref }}
|
||||
git checkout origin/${{ github.base_ref }} CHANGELOG.md
|
||||
|
||||
- name: Copy to Checker directory for CHANGELOG-base.md
|
||||
run: cp _base/CHANGELOG.md scripts/changelog-checker/CHANGELOG-base.md
|
||||
- name: Copy to Checker directory for CHANGELOG-head.md
|
||||
run: cp CHANGELOG.md scripts/changelog-checker/CHANGELOG-head.md
|
||||
- name: diff
|
||||
continue-on-error: true
|
||||
run: diff -u CHANGELOG-base.md CHANGELOG-head.md
|
||||
working-directory: scripts/changelog-checker
|
||||
|
||||
- name: Setup Checker
|
||||
run: npm install
|
||||
working-directory: scripts/changelog-checker
|
||||
- name: Run Checker
|
||||
run: npm run run
|
||||
working-directory: scripts/changelog-checker
|
|
@ -21,6 +21,7 @@
|
|||
### Client
|
||||
- Feat: 新しいゲームを追加
|
||||
- Feat: 絵文字の詳細ダイアログを追加
|
||||
- Feat: 枠線をつけるMFM`$[border.width=1,style=solid,color=fff,radius=0 ...]`を追加
|
||||
- Enhance: ハッシュタグ入力時に、本文の末尾の行に何も書かれていない場合は新たにスペースを追加しないように
|
||||
- Enhance: チャンネルノートのピン留めをノートのメニューからできるように
|
||||
- Enhance: 管理者の場合はAPI tokenの発行画面で管理機能に関する権限を付与できるように
|
||||
|
|
|
@ -62,6 +62,11 @@ export default function(props: MfmProps, context: SetupContext<MfmEvents>) {
|
|||
return t.match(/^[0-9.]+s$/) ? t : null;
|
||||
};
|
||||
|
||||
const validColor = (c: string | null | undefined): string | null => {
|
||||
if (c == null) return null;
|
||||
return c.match(/^[0-9a-f]{3,6}$/i) ? c : null;
|
||||
};
|
||||
|
||||
const useAnim = defaultStore.state.advancedMfm && defaultStore.state.animatedMfm;
|
||||
|
||||
/**
|
||||
|
@ -240,17 +245,30 @@ export default function(props: MfmProps, context: SetupContext<MfmEvents>) {
|
|||
break;
|
||||
}
|
||||
case 'fg': {
|
||||
let color = token.props.args.color;
|
||||
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
|
||||
let color = validColor(token.props.args.color);
|
||||
color = color ?? 'f00';
|
||||
style = `color: #${color}; overflow-wrap: anywhere;`;
|
||||
break;
|
||||
}
|
||||
case 'bg': {
|
||||
let color = token.props.args.color;
|
||||
if (!/^[0-9a-f]{3,6}$/i.test(color)) color = 'f00';
|
||||
let color = validColor(token.props.args.color);
|
||||
color = color ?? 'f00';
|
||||
style = `background-color: #${color}; overflow-wrap: anywhere;`;
|
||||
break;
|
||||
}
|
||||
case 'border': {
|
||||
let color = validColor(token.props.args.color);
|
||||
color = color ? `#${color}` : 'var(--accent)';
|
||||
let b_style = token.props.args.style;
|
||||
if (
|
||||
!['hidden', 'dotted', 'dashed', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset']
|
||||
.includes(b_style)
|
||||
) b_style = 'solid';
|
||||
const width = parseFloat(token.props.args.width ?? '1');
|
||||
const radius = parseFloat(token.props.args.radius ?? '0');
|
||||
style = `border: ${width}px ${b_style} ${color}; border-radius: ${radius}px`;
|
||||
break;
|
||||
}
|
||||
case 'ruby': {
|
||||
if (token.children.length === 1) {
|
||||
const child = token.children[0];
|
||||
|
|
|
@ -108,4 +108,4 @@ export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error
|
|||
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
|
||||
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';
|
||||
|
||||
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime'];
|
||||
export const MFM_TAGS = ['tada', 'jelly', 'twitch', 'shake', 'spin', 'jump', 'bounce', 'flip', 'x2', 'x3', 'x4', 'scale', 'position', 'fg', 'bg', 'border', 'font', 'blur', 'rainbow', 'sparkle', 'rotate', 'ruby', 'unixtime'];
|
||||
|
|
9
scripts/changelog-checker/.eslintrc.cjs
Normal file
9
scripts/changelog-checker/.eslintrc.cjs
Normal file
|
@ -0,0 +1,9 @@
|
|||
module.exports = {
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: ['./tsconfig.json'],
|
||||
},
|
||||
extends: [
|
||||
'../../packages/shared/.eslintrc.js',
|
||||
],
|
||||
};
|
3
scripts/changelog-checker/.gitignore
vendored
Normal file
3
scripts/changelog-checker/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
coverage
|
||||
.idea
|
2769
scripts/changelog-checker/package-lock.json
generated
Normal file
2769
scripts/changelog-checker/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
24
scripts/changelog-checker/package.json
Normal file
24
scripts/changelog-checker/package.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "changelog-checker",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"run": "vite-node src/index.ts",
|
||||
"test": "vitest run",
|
||||
"test:coverage": "vitest run --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/mdast": "4.0.3",
|
||||
"@types/node": "20.10.7",
|
||||
"@vitest/coverage-v8": "1.1.3",
|
||||
"mdast-util-to-string": "4.0.0",
|
||||
"remark": "15.0.1",
|
||||
"remark-parse": "11.0.0",
|
||||
"typescript": "5.3.3",
|
||||
"unified": "11.0.4",
|
||||
"vite": "5.0.11",
|
||||
"vite-node": "1.1.3",
|
||||
"vitest": "1.1.3"
|
||||
}
|
||||
}
|
87
scripts/changelog-checker/src/checker.ts
Normal file
87
scripts/changelog-checker/src/checker.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
import { Release } from './parser.js';
|
||||
|
||||
export class Result {
|
||||
public readonly success: boolean;
|
||||
public readonly message?: string;
|
||||
|
||||
private constructor(success: boolean, message?: string) {
|
||||
this.success = success;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
static ofSuccess(): Result {
|
||||
return new Result(true);
|
||||
}
|
||||
|
||||
static ofFailed(message?: string): Result {
|
||||
return new Result(false, message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* develop -> masterまたはrelease -> masterを想定したパターン。
|
||||
* base側の先頭とhead側で追加された分のリリースより1つ前のバージョンが等価であるかチェックする。
|
||||
*/
|
||||
export function checkNewRelease(base: Release[], head: Release[]): Result {
|
||||
const releaseCountDiff = head.length - base.length;
|
||||
if (releaseCountDiff <= 0) {
|
||||
return Result.ofFailed('Invalid release count.');
|
||||
}
|
||||
|
||||
const baseLatest = base[0];
|
||||
const headPrevious = head[releaseCountDiff];
|
||||
|
||||
if (baseLatest.releaseName !== headPrevious.releaseName) {
|
||||
return Result.ofFailed('Contains unexpected releases.');
|
||||
}
|
||||
|
||||
return Result.ofSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* topic -> developまたはtopic -> masterを想定したパターン。
|
||||
* head側の最新リリース配下に書き加えられているかをチェックする。
|
||||
*/
|
||||
export function checkNewTopic(base: Release[], head: Release[]): Result {
|
||||
if (head.length !== base.length) {
|
||||
return Result.ofFailed('Invalid release count.');
|
||||
}
|
||||
|
||||
const headLatest = head[0];
|
||||
for (let relIdx = 0; relIdx < base.length; relIdx++) {
|
||||
const baseItem = base[relIdx];
|
||||
const headItem = head[relIdx];
|
||||
if (baseItem.releaseName !== headItem.releaseName) {
|
||||
// リリースの順番が変わってると成立しないのでエラーにする
|
||||
return Result.ofFailed(`Release is different. base:${baseItem.releaseName}, head:${headItem.releaseName}`);
|
||||
}
|
||||
|
||||
if (baseItem.categories.length !== headItem.categories.length) {
|
||||
// カテゴリごと書き加えられたパターン
|
||||
if (headLatest.releaseName !== headItem.releaseName) {
|
||||
// 最新リリース以外に追記されていた場合
|
||||
return Result.ofFailed(`There is an error in the update history. expected additions:${headLatest.releaseName}, actual additions:${headItem.releaseName}`);
|
||||
}
|
||||
} else {
|
||||
// カテゴリ数の変動はないのでリスト項目の数をチェック
|
||||
for (let catIdx = 0; catIdx < baseItem.categories.length; catIdx++) {
|
||||
const baseCategory = baseItem.categories[catIdx];
|
||||
const headCategory = headItem.categories[catIdx];
|
||||
|
||||
if (baseCategory.categoryName !== headCategory.categoryName) {
|
||||
// カテゴリの順番が変わっていると成立しないのでエラーにする
|
||||
return Result.ofFailed(`Category is different. base:${baseCategory.categoryName}, head:${headCategory.categoryName}`);
|
||||
}
|
||||
|
||||
if (baseCategory.items.length !== headCategory.items.length) {
|
||||
if (headLatest.releaseName !== headItem.releaseName) {
|
||||
// 最新リリース以外に追記されていた場合
|
||||
return Result.ofFailed(`There is an error in the update history. expected additions:${headLatest.releaseName}, actual additions:${headItem.releaseName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result.ofSuccess();
|
||||
}
|
33
scripts/changelog-checker/src/index.ts
Normal file
33
scripts/changelog-checker/src/index.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import * as process from 'process';
|
||||
import * as fs from 'fs';
|
||||
import { parseChangeLog } from './parser.js';
|
||||
import { checkNewRelease, checkNewTopic } from './checker.js';
|
||||
|
||||
function abort(message?: string) {
|
||||
if (message) {
|
||||
console.error(message);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function main() {
|
||||
if (!fs.existsSync('./CHANGELOG-base.md') || !fs.existsSync('./CHANGELOG-head.md')) {
|
||||
console.error('CHANGELOG-base.md or CHANGELOG-head.md is missing.');
|
||||
return;
|
||||
}
|
||||
|
||||
const base = parseChangeLog('./CHANGELOG-base.md');
|
||||
const head = parseChangeLog('./CHANGELOG-head.md');
|
||||
|
||||
const result = (base.length < head.length)
|
||||
? checkNewRelease(base, head)
|
||||
: checkNewTopic(base, head);
|
||||
|
||||
if (!result.success) {
|
||||
abort(result.message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
62
scripts/changelog-checker/src/parser.ts
Normal file
62
scripts/changelog-checker/src/parser.ts
Normal file
|
@ -0,0 +1,62 @@
|
|||
import * as fs from 'node:fs';
|
||||
import { unified } from 'unified';
|
||||
import remarkParse from 'remark-parse';
|
||||
import { Heading, List, Node } from 'mdast';
|
||||
import { toString } from 'mdast-util-to-string';
|
||||
|
||||
export class Release {
|
||||
public readonly releaseName: string;
|
||||
public readonly categories: ReleaseCategory[];
|
||||
|
||||
constructor(releaseName: string, categories: ReleaseCategory[] = []) {
|
||||
this.releaseName = releaseName;
|
||||
this.categories = [...categories];
|
||||
}
|
||||
}
|
||||
|
||||
export class ReleaseCategory {
|
||||
public readonly categoryName: string;
|
||||
public readonly items: string[];
|
||||
|
||||
constructor(categoryName: string, items: string[] = []) {
|
||||
this.categoryName = categoryName;
|
||||
this.items = [...items];
|
||||
}
|
||||
}
|
||||
|
||||
function isHeading(node: Node): node is Heading {
|
||||
return node.type === 'heading';
|
||||
}
|
||||
|
||||
function isList(node: Node): node is List {
|
||||
return node.type === 'list';
|
||||
}
|
||||
|
||||
export function parseChangeLog(path: string): Release[] {
|
||||
const input = fs.readFileSync(path, { encoding: 'utf8' });
|
||||
const processor = unified().use(remarkParse);
|
||||
|
||||
const releases: Release[] = [];
|
||||
const root = processor.parse(input);
|
||||
|
||||
let release: Release | null = null;
|
||||
let category: ReleaseCategory | null = null;
|
||||
for (const it of root.children) {
|
||||
if (isHeading(it) && it.depth === 2) {
|
||||
// リリース
|
||||
release = new Release(toString(it));
|
||||
releases.push(release);
|
||||
} else if (isHeading(it) && it.depth === 3 && release) {
|
||||
// リリース配下のカテゴリ
|
||||
category = new ReleaseCategory(toString(it));
|
||||
release.categories.push(category);
|
||||
} else if (isList(it) && category) {
|
||||
for (const listItem of it.children) {
|
||||
// カテゴリ配下のリスト項目
|
||||
category.items.push(toString(listItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
414
scripts/changelog-checker/test/checker.test.ts
Normal file
414
scripts/changelog-checker/test/checker.test.ts
Normal file
|
@ -0,0 +1,414 @@
|
|||
import {expect, suite, test} from "vitest";
|
||||
import {Release, ReleaseCategory} from "../src/parser";
|
||||
import {checkNewRelease, checkNewTopic} from "../src/checker";
|
||||
|
||||
suite('checkNewRelease', () => {
|
||||
test('headに新しいリリースがある1', () => {
|
||||
const base = [new Release('2024.12.0')]
|
||||
const head = [new Release('2024.12.1'), new Release('2024.12.0')]
|
||||
|
||||
const result = checkNewRelease(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
test('headに新しいリリースがある2', () => {
|
||||
const base = [new Release('2024.12.0')]
|
||||
const head = [new Release('2024.12.2'), new Release('2024.12.1'), new Release('2024.12.0')]
|
||||
|
||||
const result = checkNewRelease(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
|
||||
test('リリースの数が同じ', () => {
|
||||
const base = [new Release('2024.12.0')]
|
||||
const head = [new Release('2024.12.0')]
|
||||
|
||||
const result = checkNewRelease(base, head)
|
||||
|
||||
console.log(result.message)
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
test('baseにあるリリースがheadにない', () => {
|
||||
const base = [new Release('2024.12.0')]
|
||||
const head = [new Release('2024.12.2'), new Release('2024.12.1')]
|
||||
|
||||
const result = checkNewRelease(base, head)
|
||||
|
||||
console.log(result.message)
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
suite('checkNewTopic', () => {
|
||||
test('追記なし', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
test('最新バージョンにカテゴリを追加したときはエラーにならない', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
test('最新バージョンからカテゴリを削除したときはエラーにならない', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat3',
|
||||
'feat4',
|
||||
])
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
test('最新バージョンに追記したときはエラーにならない', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
'feat3',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
test('最新バージョンから削除したときはエラーにならない', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
expect(result.success).toBe(true)
|
||||
})
|
||||
|
||||
test('古いバージョンにカテゴリを追加したときはエラーになる', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
new ReleaseCategory('Client', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
console.log(result.message)
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
test('古いバージョンからカテゴリを削除したときはエラーになる', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
console.log(result.message)
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
test('古いバージョンに追記したときはエラーになる', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
'feat3',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
console.log(result.message)
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
|
||||
test('古いバージョンから削除したときはエラーになる', () => {
|
||||
const base = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const head = [
|
||||
new Release('2024.12.1', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
'feat2',
|
||||
]),
|
||||
]),
|
||||
new Release('2024.12.0', [
|
||||
new ReleaseCategory('Server', [
|
||||
'feat1',
|
||||
]),
|
||||
])
|
||||
]
|
||||
|
||||
const result = checkNewTopic(base, head)
|
||||
|
||||
console.log(result.message)
|
||||
expect(result.success).toBe(false)
|
||||
})
|
||||
})
|
31
scripts/changelog-checker/tsconfig.json
Normal file
31
scripts/changelog-checker/tsconfig.json
Normal file
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "nodenext",
|
||||
"moduleResolution": "nodenext",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"strict": true,
|
||||
"strictFunctionTypes": true,
|
||||
"strictNullChecks": true,
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitReturns": true,
|
||||
"esModuleInterop": true,
|
||||
"typeRoots": [
|
||||
"./node_modules/@types"
|
||||
],
|
||||
"lib": [
|
||||
"esnext"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"test/**/*"
|
||||
]
|
||||
}
|
6
scripts/changelog-checker/vite.config.ts
Normal file
6
scripts/changelog-checker/vite.config.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import {defineConfig} from 'vite';
|
||||
|
||||
|
||||
const config = defineConfig({});
|
||||
|
||||
export default config;
|
Loading…
Reference in a new issue