Compare commits

...

8 commits

Author SHA1 Message Date
3aa455b43c
fix (backend): undefined reference to ApiError 2024-02-28 00:05:50 +09:00
846e69fe7b
fix (backend): apply word mutes in notifications
Co-authored-by: naskya <m@naskya.net>
2024-02-26 03:08:22 +09:00
b02bba83d3
fix (backend-rs): properly compare strings in check_word_mute
Co-authored-by: naskya <m@naskya.net>
2024-02-26 03:07:53 +09:00
cd18bf0c48
chore: discontinue latest-version api 2024-02-26 02:59:20 +09:00
Ryan Cao
4bf63a73e0
refactor: make client and sw ES modules 2024-02-26 02:54:56 +09:00
e4bcd23f9d
fix (backend): check url properly
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
2024-02-26 02:50:10 +09:00
949084e218
feat: search posts by cw and alt texts
Co-authored-by: sup39 <dev@sup39.dev>
2024-02-26 02:48:45 +09:00
90a30f82be
chore: untrack traineddata 2024-02-26 01:41:32 +09:00
32 changed files with 137 additions and 68 deletions

2
.gitignore vendored
View file

@ -58,6 +58,8 @@ packages/backend/assets/LICENSE
packages/megalodon/lib packages/megalodon/lib
packages/megalodon/.idea packages/megalodon/.idea
*.traineddata
# blender backups # blender backups
*.blend1 *.blend1
*.blend2 *.blend2

View file

@ -8,7 +8,6 @@ const replace = require("gulp-replace");
const terser = require("gulp-terser"); const terser = require("gulp-terser");
const cssnano = require("gulp-cssnano"); const cssnano = require("gulp-cssnano");
const locales = require("./locales");
const meta = require("./package.json"); const meta = require("./package.json");
gulp.task("copy:backend:views", () => gulp.task("copy:backend:views", () =>
@ -29,8 +28,9 @@ gulp.task("copy:client:fonts", () =>
.pipe(gulp.dest("./built/_client_dist_/fonts/")), .pipe(gulp.dest("./built/_client_dist_/fonts/")),
); );
gulp.task("copy:client:locales", (cb) => { gulp.task("copy:client:locales", async (cb) => {
fs.mkdirSync("./built/_client_dist_/locales", { recursive: true }); fs.mkdirSync("./built/_client_dist_/locales", { recursive: true });
const { default: locales } = await import("./locales/index.mjs");
const v = { _version_: meta.version }; const v = { _version_: meta.version };
@ -45,7 +45,9 @@ gulp.task("copy:client:locales", (cb) => {
cb(); cb();
}); });
gulp.task("build:backend:script", () => { gulp.task("build:backend:script", async () => {
const { default: locales } = await import("./locales/index.mjs");
return gulp return gulp
.src([ .src([
"./packages/backend/src/server/web/boot.js", "./packages/backend/src/server/web/boot.js",

View file

@ -1178,6 +1178,7 @@ useCdn: "Get assets from CDN"
useCdnDescription: "Load some static assets like Twemoji from the JSDelivr CDN instead of this Firefish server." useCdnDescription: "Load some static assets like Twemoji from the JSDelivr CDN instead of this Firefish server."
suggested: "Suggested" suggested: "Suggested"
noLanguage: "No language" noLanguage: "No language"
searchCwAndAlt: "Include content warnings and alt texts"
_sensitiveMediaDetection: _sensitiveMediaDetection:
description: "Reduces the effort of server moderation through automatically recognizing description: "Reduces the effort of server moderation through automatically recognizing

View file

@ -2,8 +2,14 @@
* Languages Loader * Languages Loader
*/ */
const fs = require("fs"); import fs from "node:fs";
const yaml = require("js-yaml"); import yaml from "js-yaml";
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const languages = []; const languages = [];
const languages_custom = []; const languages_custom = [];
@ -66,16 +72,17 @@ const locales_custom = languages_custom.reduce(
); );
Object.assign(locales, locales_custom); Object.assign(locales, locales_custom);
module.exports = Object.entries(locales).reduce( export default Object.entries(locales).reduce(
(a, [k, v]) => ( (a, [k, v]) => (
(a[k] = (() => { (a[k] = (() => {
const [lang] = k.split("-"); const [lang] = k.split("-");
return k === "en-US" ? v : return k === "en-US"
merge( ? v
locales["en-US"], : merge(
locales[`${lang}-${primaries[lang]}`] || {}, locales["en-US"],
v, locales[`${lang}-${primaries[lang]}`] || {},
); v,
);
})()), })()),
a a
), ),

View file

@ -2057,3 +2057,4 @@ searchUsersDescription: "投稿検索で投稿者を絞りたい場合、@user@e
searchRange: "投稿期間(オプション)" searchRange: "投稿期間(オプション)"
searchRangeDescription: "投稿検索で投稿期間を絞りたい場合、20220615-20231031 のような形式で投稿期間を入力してください。今年の日付を指定する場合には年の指定を省略できます0105-0106 や 20231105-0110 のように)。\n\n開始日と終了日のどちらか一方は省略可能です。例えば -0102 とすると今年1月2日までの投稿のみを、20231026- とすると2023年10月26日以降の投稿のみを検索します。" searchRangeDescription: "投稿検索で投稿期間を絞りたい場合、20220615-20231031 のような形式で投稿期間を入力してください。今年の日付を指定する場合には年の指定を省略できます0105-0106 や 20231105-0110 のように)。\n\n開始日と終了日のどちらか一方は省略可能です。例えば -0102 とすると今年1月2日までの投稿のみを、20231026- とすると2023年10月26日以降の投稿のみを検索します。"
searchPostsWithFiles: "添付ファイルのある投稿のみ" searchPostsWithFiles: "添付ファイルのある投稿のみ"
searchCwAndAlt: "閲覧注意の注釈と添付ファイルの代替テキストも検索する"

View file

@ -2050,3 +2050,4 @@ searchUsersDescription: "如欲搜尋特定使用者的貼文,請以「@user@e
searchWords: "搜尋關鍵字 / 查詢ID或URL" searchWords: "搜尋關鍵字 / 查詢ID或URL"
searchWordsDescription: "如欲搜尋貼文請在此欄位輸入欲搜尋的關鍵字。以空格分隔關鍵字以進行AND搜尋、在關鍵字之間插入「OR」以進行OR搜尋。\n舉例來說輸入「早上 晚上」會搜尋包含「早上」和「晚上」的貼文,「早上 OR 晚上」會搜尋包含「早上」或「晚上」(或兩者皆包含)的貼文。\n\n如欲前往特定使用者或貼文的頁面請在此欄位輸入使用者ID@user@example.com或貼文的URL並點擊「查詢」按鈕。點擊「搜尋」按鈕則會搜尋字面上包含輸入的ID或URL的貼文。" searchWordsDescription: "如欲搜尋貼文請在此欄位輸入欲搜尋的關鍵字。以空格分隔關鍵字以進行AND搜尋、在關鍵字之間插入「OR」以進行OR搜尋。\n舉例來說輸入「早上 晚上」會搜尋包含「早上」和「晚上」的貼文,「早上 OR 晚上」會搜尋包含「早上」或「晚上」(或兩者皆包含)的貼文。\n\n如欲前往特定使用者或貼文的頁面請在此欄位輸入使用者ID@user@example.com或貼文的URL並點擊「查詢」按鈕。點擊「搜尋」按鈕則會搜尋字面上包含輸入的ID或URL的貼文。"
suggested: "建議" suggested: "建議"
searchCwAndAlt: "包含內容警告及替代文字"

View file

@ -1,6 +1,7 @@
BEGIN; BEGIN;
DELETE FROM "migrations" WHERE name IN ( DELETE FROM "migrations" WHERE name IN (
'IndexAltTextAndCw1708872574733',
'SeparateHardMuteWordsAndPatterns1706413792769', 'SeparateHardMuteWordsAndPatterns1706413792769',
'RenameMetaColumns1705944717480', 'RenameMetaColumns1705944717480',
'RemoveNativeUtilsMigration1705877093218', 'RemoveNativeUtilsMigration1705877093218',
@ -13,6 +14,10 @@ DELETE FROM "migrations" WHERE name IN (
'EmojiModerator1692825433698' 'EmojiModerator1692825433698'
); );
-- index-alt-text-and-cw
DROP INDEX "IDX_f4f7b93d05958527300d79ac82";
DROP INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f";
-- separate-hard-mute-words-and-patterns -- separate-hard-mute-words-and-patterns
UPDATE "user_profile" SET "mutedWords" = "mutedWords" || array_to_json("mutedPatterns")::jsonb; UPDATE "user_profile" SET "mutedWords" = "mutedWords" || array_to_json("mutedPatterns")::jsonb;
ALTER TABLE "user_profile" DROP "mutedPatterns"; ALTER TABLE "user_profile" DROP "mutedPatterns";

View file

@ -79,7 +79,7 @@ fn check_word_mute_impl(
let text_lower = text.to_lowercase(); let text_lower = text.to_lowercase();
muted_word_list muted_word_list
.iter() .iter()
.all(|muted_word| text_lower.contains(muted_word)) .all(|muted_word| text_lower.contains(&muted_word.to_lowercase()))
}) })
}) || muted_patterns.iter().any(|muted_pattern| { }) || muted_patterns.iter().any(|muted_pattern| {
Regex::new(convert_regex(muted_pattern).as_str()) Regex::new(convert_regex(muted_pattern).as_str())

View file

@ -0,0 +1,17 @@
export class IndexAltTextAndCw1708872574733 {
name = "IndexAltTextAndCw1708872574733";
async up(queryRunner) {
await queryRunner.query(
`CREATE INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f" ON "note" USING "pgroonga" ("cw" pgroonga_varchar_full_text_search_ops_v2)`,
);
await queryRunner.query(
`CREATE INDEX "IDX_f4f7b93d05958527300d79ac82" ON "drive_file" USING "pgroonga" ("comment" pgroonga_varchar_full_text_search_ops_v2)`,
);
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "IDX_f4f7b93d05958527300d79ac82"`);
await queryRunner.query(`DROP INDEX "IDX_8e3bbbeb3df04d1a8105da4c8f"`);
}
}

View file

@ -70,6 +70,7 @@ export class DriveFile {
}) })
public size: number; public size: number;
@Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2
@Column("varchar", { @Column("varchar", {
length: DB_MAX_IMAGE_COMMENT_LENGTH, length: DB_MAX_IMAGE_COMMENT_LENGTH,
nullable: true, nullable: true,

View file

@ -79,6 +79,7 @@ export class Note {
}) })
public name: string | null; public name: string | null;
@Index() // USING pgroonga pgroonga_varchar_full_text_search_ops_v2
@Column("varchar", { @Column("varchar", {
length: 512, length: 512,
nullable: true, nullable: true,

View file

@ -1,4 +1,5 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { ApiError } from "@/server/api/error.js";
import { Emojis } from "@/models/index.js"; import { Emojis } from "@/models/index.js";
import { In } from "typeorm"; import { In } from "typeorm";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";

View file

@ -1,4 +1,5 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { ApiError } from "@/server/api/error.js";
import { Emojis } from "@/models/index.js"; import { Emojis } from "@/models/index.js";
import { In } from "typeorm"; import { In } from "typeorm";
import { insertModerationLog } from "@/services/insert-moderation-log.js"; import { insertModerationLog } from "@/services/insert-moderation-log.js";

View file

@ -1,4 +1,5 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { ApiError } from "@/server/api/error.js";
import { Emojis } from "@/models/index.js"; import { Emojis } from "@/models/index.js";
import { In } from "typeorm"; import { In } from "typeorm";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";

View file

@ -1,4 +1,5 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { ApiError } from "@/server/api/error.js";
import { Emojis } from "@/models/index.js"; import { Emojis } from "@/models/index.js";
import { In } from "typeorm"; import { In } from "typeorm";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";

View file

@ -1,4 +1,5 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { ApiError } from "@/server/api/error.js";
import { Emojis } from "@/models/index.js"; import { Emojis } from "@/models/index.js";
import { In } from "typeorm"; import { In } from "typeorm";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";

View file

@ -1,4 +1,5 @@
import define from "@/server/api/define.js"; import define from "@/server/api/define.js";
import { ApiError } from "@/server/api/error.js";
import { Emojis } from "@/models/index.js"; import { Emojis } from "@/models/index.js";
import { In } from "typeorm"; import { In } from "typeorm";
import { db } from "@/db/postgre.js"; import { db } from "@/db/postgre.js";

View file

@ -14,18 +14,7 @@ export const paramDef = {
} as const; } as const;
export default define(meta, paramDef, async () => { export default define(meta, paramDef, async () => {
let tag_name: string;
const pattern = /&quot;version&quot;: &quot;(.*)&quot;,$/m;
await fetch(
"https://code.naskya.net/naskya/firefish/source-by/main/package.json",
)
.then((response) => response.text())
.then((text) => {
tag_name = pattern.exec(text)[1];
});
return { return {
tag_name, tag_name: "neko",
}; };
}); });

View file

@ -7,6 +7,7 @@ import { generateMutedUserQuery } from "@/server/api/common/generate-muted-user-
import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js"; import { makePaginationQuery } from "@/server/api/common/make-pagination-query.js";
import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js"; import { generateBlockedUserQuery } from "@/server/api/common/generate-block-query.js";
import { generateMutedNoteThreadQuery } from "@/server/api/common/generate-muted-note-thread-query.js"; import { generateMutedNoteThreadQuery } from "@/server/api/common/generate-muted-note-thread-query.js";
import { generateMutedNoteQuery } from "@/server/api/common/generate-muted-note-query.js";
export const meta = { export const meta = {
tags: ["notes"], tags: ["notes"],
@ -69,6 +70,7 @@ export default define(meta, paramDef, async (ps, user) => {
generateVisibilityQuery(query, user); generateVisibilityQuery(query, user);
generateMutedUserQuery(query, user); generateMutedUserQuery(query, user);
generateMutedNoteQuery(query, user);
generateMutedNoteThreadQuery(query, user); generateMutedNoteThreadQuery(query, user);
generateBlockedUserQuery(query, user); generateBlockedUserQuery(query, user);

View file

@ -1,4 +1,5 @@
// import { FindManyOptions, In } from "typeorm"; // import { FindManyOptions, In } from "typeorm";
import { Brackets } from "typeorm";
import { Notes } from "@/models/index.js"; import { Notes } from "@/models/index.js";
import { Note } from "@/models/entities/note.js"; import { Note } from "@/models/entities/note.js";
// import config from "@/config/index.js"; // import config from "@/config/index.js";
@ -56,6 +57,7 @@ export const paramDef = {
default: null, default: null,
}, },
withFiles: { type: "boolean", nullable: true }, withFiles: { type: "boolean", nullable: true },
searchCwAndAlt: { type: "boolean", nullable: true },
channelId: { channelId: {
type: "string", type: "string",
format: "misskey:id", format: "misskey:id",
@ -92,7 +94,28 @@ export default define(meta, paramDef, async (ps, me) => {
} }
if (ps.query != null) { if (ps.query != null) {
query.andWhere("note.text &@~ :q", { q: `${sqlLikeEscape(ps.query)}` }); const q = sqlLikeEscape(ps.query);
if (ps.searchCwAndAlt) {
query.andWhere(
new Brackets((qb) => {
qb.where("note.text &@~ :q", { q })
.orWhere("note.cw &@~ :q", { q })
.orWhere(
`EXISTS (
SELECT FROM "drive_file"
WHERE
comment &@~ :q
AND
drive_file."id" = ANY(note."fileIds")
)`,
{ q },
);
}),
);
} else {
query.andWhere("note.text &@~ :q", { q });
}
} }
query.innerJoinAndSelect("note.user", "user"); query.innerJoinAndSelect("note.user", "user");

View file

@ -54,7 +54,9 @@ const bullBoardPath = "/queue";
// Authenticate // Authenticate
app.use(async (ctx, next) => { app.use(async (ctx, next) => {
if (ctx.path === bullBoardPath || ctx.path.startsWith(`${bullBoardPath}/`)) { const url = decodeURI(ctx.path);
if (url === bullBoardPath || url.startsWith(`${bullBoardPath}/`)) {
const token = ctx.cookies.get("token"); const token = ctx.cookies.get("token");
if (token == null) { if (token == null) {
ctx.status = 401; ctx.status = 401;

View file

@ -887,14 +887,17 @@ async function createMentionedEvents(
nm: NotificationManager, nm: NotificationManager,
) { ) {
for (const u of mentionedUsers.filter((u) => Users.isLocalUser(u))) { for (const u of mentionedUsers.filter((u) => Users.isLocalUser(u))) {
const threadMuted = await NoteThreadMutings.findOneBy({ const isWordMuted = await MutedNotes.existsBy({
userId: u.id, userId: u.id,
threadId: note.threadId || note.id, noteId: note.id,
}); });
if (isWordMuted) continue;
if (threadMuted) { const isThreadMuted = await NoteThreadMutings.existsBy({
continue; userId: u.id,
} threadId: note.threadId ?? note.id,
});
if (isThreadMuted) continue;
// note with "specified" visibility might not be visible to mentioned users // note with "specified" visibility might not be visible to mentioned users
try { try {

View file

@ -1,6 +1,7 @@
{ {
"name": "client", "name": "client",
"private": true, "private": true,
"type": "module",
"scripts": { "scripts": {
"watch": "pnpm vite build --watch --mode development", "watch": "pnpm vite build --watch --mode development",
"build": "pnpm vite build", "build": "pnpm vite build",

View file

@ -68,6 +68,12 @@
:class="$style.input" :class="$style.input"
>{{ i18n.ts.searchPostsWithFiles }}</FormSwitch >{{ i18n.ts.searchPostsWithFiles }}</FormSwitch
> >
<FormSwitch
v-model="searchCwAndAlt"
class="form-switch"
:class="$style.input"
>{{ i18n.ts.searchCwAndAlt }}</FormSwitch
>
<div :class="$style.buttons"> <div :class="$style.buttons">
<MkButton inline primary @click="search" <MkButton inline primary @click="search"
>{{ i18n.ts.search }} >{{ i18n.ts.search }}
@ -128,7 +134,8 @@ const searchRange = ref(
}` }`
: "", : "",
); );
const searchPostsWithFiles = ref(searchParams.get("withFiles") === "true"); const searchPostsWithFiles = ref(searchParams.get("withFiles") === "1");
const searchCwAndAlt = ref(searchParams.get("detailed") === "1");
function done(canceled: boolean, result?: searchQuery) { function done(canceled: boolean, result?: searchQuery) {
emit("done", { canceled, result }); emit("done", { canceled, result });
@ -149,6 +156,7 @@ function search() {
from: searchUsers.value === "" ? undefined : searchUsers.value, from: searchUsers.value === "" ? undefined : searchUsers.value,
range: searchRange.value === "" ? undefined : searchRange.value, range: searchRange.value === "" ? undefined : searchRange.value,
withFiles: searchPostsWithFiles.value, withFiles: searchPostsWithFiles.value,
searchCwAndAlt: searchCwAndAlt.value,
}); });
} }

View file

@ -42,15 +42,6 @@
i18n.ts.configure i18n.ts.configure
}}</MkA></MkInfo }}</MkA></MkInfo
> >
<MkInfo v-if="updateAvailable" warn class="info"
>{{ i18n.ts.updateAvailable }}
<a
href="https://code.naskya.net/naskya/firefish"
target="_bank"
class="_link"
>{{ i18n.ts.check }}</a
></MkInfo
>
<MkSuperMenu :def="menuDef" :grid="narrow"></MkSuperMenu> <MkSuperMenu :def="menuDef" :grid="narrow"></MkSuperMenu>
</div> </div>
@ -113,7 +104,6 @@ const noBotProtection =
!instance.enableRecaptcha; !instance.enableRecaptcha;
const noEmailServer = !instance.enableEmail; const noEmailServer = !instance.enableEmail;
const thereIsUnresolvedAbuseReport = ref(false); const thereIsUnresolvedAbuseReport = ref(false);
const updateAvailable = ref(false);
const currentPage = computed(() => router.currentRef.value.child); const currentPage = computed(() => router.currentRef.value.child);
os.api("admin/abuse-user-reports", { os.api("admin/abuse-user-reports", {
@ -123,13 +113,6 @@ os.api("admin/abuse-user-reports", {
if (reports?.length > 0) thereIsUnresolvedAbuseReport.value = true; if (reports?.length > 0) thereIsUnresolvedAbuseReport.value = true;
}); });
if (defaultStore.state.showAdminUpdates) {
os.api("latest-version").then((res) => {
if (res == null || res.tag_name == null) return;
updateAvailable.value = !version.startsWith(res.tag_name);
});
}
const NARROW_THRESHOLD = 600; const NARROW_THRESHOLD = 600;
const ro = new ResizeObserver((entries, observer) => { const ro = new ResizeObserver((entries, observer) => {
if (entries.length === 0) return; if (entries.length === 0) return;

View file

@ -63,7 +63,8 @@ const props = defineProps<{
since?: string; since?: string;
until?: string; until?: string;
channel?: string; channel?: string;
withFiles: "false" | "true"; withFiles: "0" | "1";
searchCwAndAlt: "0" | "1";
}>(); }>();
const userId = props.user == null ? undefined : await getUserId(props.user); const userId = props.user == null ? undefined : await getUserId(props.user);
@ -79,7 +80,8 @@ const notesPagination = {
props.since == null ? undefined : getUnixTime(props.since, false), props.since == null ? undefined : getUnixTime(props.since, false),
untilDate: untilDate:
props.until == null ? undefined : getUnixTime(props.until, true), props.until == null ? undefined : getUnixTime(props.until, true),
withFiles: props.withFiles === "true", withFiles: props.withFiles === "1",
searchCwAndAlt: props.searchCwAndAlt === "1",
channelId: props.channel, channelId: props.channel,
})), })),
}; };

View file

@ -310,6 +310,7 @@ export const routes = [
until: "until", until: "until",
withFiles: "withFiles", withFiles: "withFiles",
channel: "channel", channel: "channel",
detailed: "searchCwAndAlt",
}, },
}, },
{ {

View file

@ -21,6 +21,7 @@ export async function search() {
from?: string; from?: string;
range?: string; range?: string;
withFiles: boolean; withFiles: boolean;
searchCwAndAlt: boolean;
}; };
} }
>((resolve, _) => { >((resolve, _) => {
@ -69,24 +70,35 @@ export async function search() {
} }
if (result.action === "search") { if (result.action === "search") {
let paramString = `withFiles=${result.withFiles ? "true" : "false"}`; const params = new URLSearchParams();
params.append("withFiles", result.withFiles ? "1" : "0");
if (result.query != null) { if (result.query != null) {
paramString += `&q=${encodeURIComponent(result.query)}`; params.append("q", result.query);
} }
if (result.from != null) { if (result.from != null) {
if (result.from === "me" || result.from.includes("@")) if (result.from === "me" || result.from.includes("@"))
paramString += `&user=${encodeURIComponent(result.from)}`; params.append("user", result.from);
else paramString += `&host=${encodeURIComponent(result.from)}`; else params.append("host", result.from);
} }
if (result.range != null) { if (result.range != null) {
const split = result.range.split("-"); const split = result.range.split("-");
if (split[0] !== "") paramString += `&since=${split[0]}`; if (split.length === 1) {
if (split[1] !== "") paramString += `&until=${split[1]}`; params.append("since", result.range);
params.append("until", result.range);
} else {
if (split[0] !== "") params.append("since", split[0]);
if (split[1] !== "") params.append("until", split[1]);
}
} }
mainRouter.push(`/search?${paramString}`); if (result.searchCwAndAlt) {
params.append("detailed", "1");
}
mainRouter.push(`/search?${params.toString()}`);
} }
} }

View file

@ -2,10 +2,10 @@ import * as fs from "fs";
import pluginVue from "@vitejs/plugin-vue"; import pluginVue from "@vitejs/plugin-vue";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import viteCompression from "vite-plugin-compression"; import locales from "../../locales/index.mjs";
import locales from "../../locales"; import meta from "../../package.json" assert { type: "json" };
import meta from "../../package.json";
import pluginJson5 from "./vite.json5"; import pluginJson5 from "./vite.json5";
import viteCompression from "vite-plugin-compression";
const extensions = [ const extensions = [
".ts", ".ts",

View file

@ -1,6 +1,7 @@
{ {
"name": "sw", "name": "sw",
"private": true, "private": true,
"type": "module",
"scripts": { "scripts": {
"build": "pnpm vite build --emptyOutDir", "build": "pnpm vite build --emptyOutDir",
"build:debug": "pnpm run build", "build:debug": "pnpm run build",

View file

@ -16,6 +16,7 @@
"noLib": false, "noLib": false,
"strict": true, "strict": true,
"strictNullChecks": true, "strictNullChecks": true,
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true, "experimentalDecorators": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,
@ -23,10 +24,7 @@
"paths": { "paths": {
"@/*": ["./src/*"] "@/*": ["./src/*"]
}, },
"typeRoots": [ "typeRoots": ["node_modules/@types", "@types"],
"node_modules/@types",
"@types",
],
"lib": ["esnext", "webworker"] "lib": ["esnext", "webworker"]
}, },
"compileOnSave": false, "compileOnSave": false,

View file

@ -1,6 +1,6 @@
import { defineConfig } from "vite"; import { defineConfig } from "vite";
const locales = require("../../locales"); import locales from "../../locales/index.mjs";
const meta = require("../../package.json"); import meta from "../../package.json" assert { type: "json" };
const isProduction = process.env.NODE_ENV === "production"; const isProduction = process.env.NODE_ENV === "production";
import viteCompression from "vite-plugin-compression"; import viteCompression from "vite-plugin-compression";