Skip to content

Commit

Permalink
Merge branch 'main' into configmanagerにスナップショットテスト追加
Browse files Browse the repository at this point in the history
  • Loading branch information
Hiroshiba authored Nov 18, 2024
2 parents 1ae518e + 416bed1 commit 21803d9
Show file tree
Hide file tree
Showing 20 changed files with 4,235 additions and 2,501 deletions.
2 changes: 1 addition & 1 deletion .node-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20.12.2
22.11.0
1 change: 0 additions & 1 deletion .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const config: StorybookConfig = {
"@storybook/addon-links",
"@storybook/addon-essentials",
"@chromatic-com/storybook",
"@storybook/addon-interactions",
"@storybook/addon-themes",
"@storybook/experimental-addon-test",
],
Expand Down
6,492 changes: 4,105 additions & 2,387 deletions package-lock.json

Large diffs are not rendered by default.

51 changes: 25 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"private": true,
"main": "./dist/main.js",
"engines": {
"node": ">=20.12.2 <21",
"npm": ">=10.5.0 <11"
"node": ">=22.11.0 <23",
"npm": ">=10.9.0 <11"
},
"volta": {
"node": "20.12.2",
Expand Down Expand Up @@ -53,14 +53,14 @@
"encoding-japanese": "1.0.30",
"fast-array-diff": "1.1.0",
"fast-base64": "0.1.8",
"glob": "8.0.3",
"glob": "11.0.0",
"hotkeys-js": "3.13.6",
"immer": "9.0.21",
"markdown-it": "13.0.2",
"move-file": "3.0.0",
"multistream": "4.1.0",
"pixi.js": "7.4.0",
"quasar": "2.17.0",
"quasar": "2.17.2",
"radix-vue": "1.9.6",
"rfdc": "1.4.1",
"semver": "7.5.4",
Expand All @@ -77,19 +77,18 @@
},
"devDependencies": {
"@chromatic-com/storybook": "1.5.0",
"@openapitools/openapi-generator-cli": "2.13.4",
"@openapitools/openapi-generator-cli": "2.15.3",
"@playwright/test": "1.48.0",
"@quasar/vite-plugin": "1.7.0",
"@storybook/addon-essentials": "8.3.5",
"@storybook/addon-interactions": "8.3.5",
"@storybook/addon-links": "8.3.5",
"@storybook/addon-themes": "8.3.5",
"@storybook/blocks": "8.3.5",
"@storybook/experimental-addon-test": "8.3.5",
"@storybook/test": "8.3.5",
"@storybook/types": "8.3.5",
"@storybook/vue3": "8.3.5",
"@storybook/vue3-vite": "8.3.5",
"@quasar/vite-plugin": "1.8.1",
"@storybook/addon-essentials": "8.4.4",
"@storybook/addon-links": "8.4.4",
"@storybook/addon-themes": "8.4.4",
"@storybook/blocks": "8.4.4",
"@storybook/experimental-addon-test": "8.4.4",
"@storybook/test": "8.4.4",
"@storybook/types": "8.4.4",
"@storybook/vue3": "8.4.4",
"@storybook/vue3-vite": "8.4.4",
"@types/async-lock": "1.4.0",
"@types/encoding-japanese": "1.0.18",
"@types/glob": "8.0.0",
Expand All @@ -112,29 +111,29 @@
"chromatic": "11.5.4",
"cross-env": "7.0.3",
"dotenv": "16.0.0",
"electron": "30.0.1",
"electron-builder": "24.13.3",
"electron": "33.2.0",
"electron-builder": "25.1.8",
"electron-devtools-installer": "3.2.0",
"eslint": "8.57.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-storybook": "0.8.0",
"eslint-plugin-vue": "9.26.0",
"happy-dom": "8.4.2",
"happy-dom": "15.11.6",
"license-checker-rseidelsohn": "4.3.0",
"markdownlint-cli": "0.37.0",
"node-fetch": "2.7.0",
"playwright": "1.48.0",
"prettier": "3.2.5",
"sass": "1.77.8",
"storybook": "8.3.5",
"ts-node": "10.9.1",
"sass-embedded": "1.81.0",
"storybook": "8.4.4",
"typescript": "5.5.2",
"vite": "5.3.2",
"vite": "5.4.11",
"vite-plugin-checker": "0.8.0",
"vite-plugin-electron": "0.28.4",
"vite-plugin-node-polyfills": "0.21.0",
"vite-tsconfig-paths": "4.2.1",
"vite-plugin-electron": "0.29.0",
"vite-plugin-node-polyfills": "0.22.0",
"vite-tsconfig-paths": "5.1.2",
"vitest": "2.1.2",
"vue-tsc": "2.1.6",
"yargs": "17.2.1"
Expand Down
1 change: 1 addition & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const config: PlaywrightTestConfig = {
testDir: "./tests/e2e",
/* Maximum time one test can run for. */
timeout: 60 * 1000,
globalTimeout: 5 * 60 * 1000,
expect: {
/**
* Maximum time expect() should wait for the condition to be met.
Expand Down
13 changes: 12 additions & 1 deletion public/licenses.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
[
{"name": "dummy name1", "version": "0.0.1", "license": "dummy license1", "text": "dummy text1"}, {"name": "dummy name2", "version": "0.0.2", "license": "dummy license2", "text": "dummy text2"}
{
"name": "dummy name1",
"version": "0.0.1",
"license": "dummy license1",
"text": "dummy text1"
},
{
"name": "dummy name2",
"version": "0.0.2",
"license": "dummy license2",
"text": "dummy text2"
}
]
2 changes: 1 addition & 1 deletion src/backend/browser/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { AssetTextFileNames } from "@/type/staticResources";

const toStaticPath = (fileName: string) =>
`${import.meta.env.BASE_URL}/${fileName}`.replaceAll(/\/\/+/, "/");
`${import.meta.env.BASE_URL}/${fileName}`.replaceAll(/\/\/+/g, "/");

// FIXME: asを使わないようオーバーロードにした。オーバーロードも使わない書き方にしたい。
function onReceivedIPCMsg<
Expand Down
18 changes: 10 additions & 8 deletions src/backend/electron/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,19 @@ export const ipcMainSendProxy = new Proxy(

/** IPCメッセージの送信元を確認する */
const validateIpcSender = (event: IpcMainInvokeEvent) => {
let isValid: boolean;
const senderUrl = new URL(event.senderFrame.url);
if (import.meta.env.VITE_DEV_SERVER_URL != undefined) {
const devServerUrl = new URL(import.meta.env.VITE_DEV_SERVER_URL);
isValid = senderUrl.origin === devServerUrl.origin;
} else {
isValid = senderUrl.protocol === "app:";
let isValid: boolean = false;
if (event.senderFrame) {
const senderUrl = new URL(event.senderFrame.url);
if (import.meta.env.VITE_DEV_SERVER_URL != undefined) {
const devServerUrl = new URL(import.meta.env.VITE_DEV_SERVER_URL);
isValid = senderUrl.origin === devServerUrl.origin;
} else {
isValid = senderUrl.protocol === "app:";
}
}
if (!isValid) {
throw new Error(
`不正なURLからのIPCメッセージを検出しました。senderUrl: ${senderUrl.toString()}`,
`不正なURLからのIPCメッセージを検出しました。senderUrl: ${event.senderFrame?.url}`,
);
}
};
11 changes: 2 additions & 9 deletions src/backend/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,13 +437,6 @@ const retryShowSaveDialogWhileSafeDir = async <
const filePath =
"filePaths" in result ? result.filePaths[0] : result.filePath;

// filePathが未定義の場合、エラーを返す
if (filePath == undefined) {
throw new Error(
`canseld == ${result.canceled} but filePath == ${filePath}`,
);
}

// 選択されたパスが安全かどうかを確認
if (isUnsafePath(filePath)) {
const result = await showWarningDialog();
Expand Down Expand Up @@ -762,7 +755,7 @@ registerIpcMainHandle<IpcMainHandle>({
});

// app callback
app.on("web-contents-created", (e, contents) => {
app.on("web-contents-created", (_e, contents) => {
// リンククリック時はブラウザを開く
contents.setWindowOpenHandler(({ url }) => {
const { protocol } = new URL(url);
Expand Down Expand Up @@ -972,7 +965,7 @@ app.on("ready", async () => {
});

// 他のプロセスが起動したとき、`requestSingleInstanceLock`経由で`rawData`が送信される。
app.on("second-instance", async (event, argv, workDir, rawData) => {
app.on("second-instance", async (_event, _argv, _workDir, rawData) => {
const data = rawData as SingleInstanceLockData;
if (!data.filePath) {
log.info("No file path sent");
Expand Down
12 changes: 7 additions & 5 deletions src/backend/electron/manager/RuntimeInfoManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import log from "electron-log/main";
import type { AltPortInfos } from "@/store/type";
import { EngineId, EngineInfo } from "@/type/preload";
import { writeFileSafely } from "@/backend/electron/fileHelper";
import { createEngineUrl } from "@/domain/url";

/**
* ランタイム情報書き出しに必要なEngineInfo
Expand Down Expand Up @@ -85,13 +86,14 @@ export class RuntimeInfoManager {
const altPort: string | undefined =
this.altportInfos[engineInfo.uuid];
const port = altPort ?? engineInfo.defaultPort;
// NOTE: URLを正規化する
const url = new URL(`${engineInfo.protocol}//${engineInfo.hostname}`);
url.port = port;
return {
uuid: engineInfo.uuid,
// NOTE: URLインターフェースは"pathname"が空文字でも"/"を付けるので手動で結合する。
url: `${url.origin}${engineInfo.pathname}`,
url: createEngineUrl({
protocol: engineInfo.protocol,
hostname: engineInfo.hostname,
port,
pathname: engineInfo.pathname,
}),
name: engineInfo.name,
};
}),
Expand Down
17 changes: 2 additions & 15 deletions src/backend/electron/manager/vvppManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import log from "electron-log/main";
import { moveFile } from "move-file";
import { app, dialog } from "electron";
import MultiStream from "multistream";
import glob, { glob as callbackGlob } from "glob";
import { glob } from "glob";
import AsyncLock from "async-lock";
import {
EngineId,
Expand All @@ -24,19 +24,6 @@ const SEVEN_ZIP_MAGIC_NUMBER = Buffer.from([

const ZIP_MAGIC_NUMBER = Buffer.from([0x50, 0x4b, 0x03, 0x04]);

// globのPromise化
const globAsync = (pattern: string, options?: glob.IOptions) => {
return new Promise<string[]>((resolve, reject) => {
callbackGlob(pattern, options ?? {}, (err, matches) => {
if (err) {
reject(err);
} else {
resolve(matches);
}
});
});
};

export const isVvppFile = (filePath: string) => {
return (
path.extname(filePath) === ".vvpp" || path.extname(filePath) === ".vvppp"
Expand Down Expand Up @@ -134,7 +121,7 @@ export class VvppManager {
.replace(/\.[0-9]+\.vvppp$/, ".*.vvppp")
.replace(/\\/g, "/"); // node-globはバックスラッシュを使えないので、スラッシュに置換する
const filePaths: string[] = [];
for (const p of await globAsync(vvpppPathGlob)) {
for (const p of await glob(vvpppPathGlob)) {
if (!p.match(/\.[0-9]+\.vvppp$/)) {
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Sing/ToolBar/ToolBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,7 @@ const snapTypeSelectModel = computed({
.sing-volume-icon {
margin-right: 8px;
:deep {
:deep() {
color: var(--scheme-color-outline);
}
}
Expand Down
15 changes: 15 additions & 0 deletions src/domain/japanese/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,18 @@ export const convertLongVowel = (text: string): string => {
.replace(/(?<=[ん]ー*)ー/g, "ん")
.replace(/(?<=[っ]ー*)ー/g, "っ");
};

// 参考:https://github.com/VOICEVOX/voicevox_core/blob/0848630d81ae3e917c6ff2038f0b15bbd4270702/crates/voicevox_core/src/user_dict/word.rs#L83-L90
export const moraPattern = new RegExp(
"(?:" +
"[イ][ェ]|[ヴ][ャュョ]|[トド][ゥ]|[テデ][ィャュョ]|[デ][ェ]|[クグ][ヮ]|" + // rule_others
"[キシチニヒミリギジビピ][ェャュョ]|" + // rule_line_i
"[ツフヴ][ァ]|[ウスツフヴズ][ィ]|[ウツフヴ][ェォ]|" + // rule_line_u
"[ァ-ヴー]|" + // rule_one_mora
"[い][ぇ]|[ゃゅょ]|[とど][ぅ]|[てで][ぃゃゅょ]|[で][ぇ]|[くぐ][ゎ]|" + // rule_others
"[きしちにひみりぎじびぴ][ぇゃゅょ]|" + // rule_line_i
"[つふゔ][ぁ]|[うすつふゔず][ぃ]|[うつふゔ][ぇぉ]|" + // rule_line_u
"[ぁ-ゔー]" + // rule_one_mora
")",
"g",
);
18 changes: 18 additions & 0 deletions src/domain/url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/** エンジンのURLを構成するパラメータ */
export type EngineUrlParams = {
protocol: string; // `http:`など
hostname: string; // `example.com`など
port: string; // `50021`など。空文字列もありえる。
pathname: string; // `/engine`など。空文字列もありえる。
};

/**
* URLを構成するパラメータから、VOICEVOXエディタが初期から想定しているURL文字列を組み立てる。
* pathnameが空文字の場合は末尾にスラッシュを付与しない、などがビルトインのURLクラスと異なる。
*/
export function createEngineUrl(params: EngineUrlParams) {
const { protocol, hostname, port, pathname } = params;
const url = new URL(`${protocol}//${hostname}`); // NOTE: URLを正規化する
url.port = port;
return `${url.origin}${pathname}`; // NOTE: URLインターフェースは"pathname"が空文字でも"/"を付けるので手動で結合する。
}
17 changes: 1 addition & 16 deletions src/sing/domain.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { calculateHash } from "./utility";
import { convertLongVowel } from "@/domain/japanese";
import { convertLongVowel, moraPattern } from "@/domain/japanese";
import {
Note,
Phrase,
Expand Down Expand Up @@ -534,21 +534,6 @@ export function applyPitchEdit(
}
}

// 参考:https://github.com/VOICEVOX/voicevox_core/blob/0848630d81ae3e917c6ff2038f0b15bbd4270702/crates/voicevox_core/src/user_dict/word.rs#L83-L90
export const moraPattern = new RegExp(
"(?:" +
"[イ][ェ]|[ヴ][ャュョ]|[トド][ゥ]|[テデ][ィャュョ]|[デ][ェ]|[クグ][ヮ]|" + // rule_others
"[キシチニヒミリギジビピ][ェャュョ]|" + // rule_line_i
"[ツフヴ][ァ]|[ウスツフヴズ][ィ]|[ウツフヴ][ェォ]|" + // rule_line_u
"[ァ-ヴー]|" + // rule_one_mora
"[い][ぇ]|[ゃゅょ]|[とど][ぅ]|[てで][ぃゃゅょ]|[で][ぇ]|[くぐ][ゎ]|" + // rule_others
"[きしちにひみりぎじびぴ][ぇゃゅょ]|" + // rule_line_i
"[つふゔ][ぁ]|[うすつふゔず][ぃ]|[うつふゔ][ぇぉ]|" + // rule_line_u
"[ぁ-ゔー]" + // rule_one_mora
")",
"g",
);

/**
* 文字列をモーラと非モーラに分割する。長音は展開される。連続する非モーラはまとめる。
* 例:"カナー漢字" -> ["カ", "ナ", "ア", "漢字"]
Expand Down
12 changes: 7 additions & 5 deletions src/store/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ProxyStoreState, ProxyStoreTypes, EditorAudioQuery } from "./type";
import { createPartialStore } from "./vuex";
import { createEngineUrl } from "@/domain/url";
import {
IEngineConnectorFactory,
OpenAPIEngineConnectorFactory,
Expand All @@ -22,12 +23,13 @@ const proxyStoreCreator = (_engineFactory: IEngineConnectorFactory) => {

const altPort: string | undefined = state.altPortInfos[engineId];
const port = altPort ?? engineInfo.defaultPort;
// NOTE: URLを正規化する
const url = new URL(`${engineInfo.protocol}//${engineInfo.hostname}`);
url.port = port;
// NOTE: URLインターフェースは"pathname"が空文字でも"/"を付けるので手動で結合する。
const instance = _engineFactory.instance(
`${url.origin}${engineInfo.pathname}`,
createEngineUrl({
protocol: engineInfo.protocol,
hostname: engineInfo.hostname,
port,
pathname: engineInfo.pathname,
}),
);
return Promise.resolve({
invoke: (v) => (arg) =>
Expand Down
2 changes: 1 addition & 1 deletion src/styles/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
@use "./v2/colors" as colors-v2;
@use "./v2/sing-colors"; // ソング用カラー
@use "./v2/cursor"; // カーソル
@import "./fonts";
@use "fonts";

// 優先度を強引に上げる
body:not(#dummy) {
Expand Down
Loading

0 comments on commit 21803d9

Please sign in to comment.