mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
feat: move routes to slugs
This commit is contained in:
@@ -31,14 +31,14 @@ export async function useEnglish(page: Page): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function openTool(page: Page, id: string): Promise<void> {
|
export async function openTool(page: Page, slug: string): Promise<void> {
|
||||||
await useEnglish(page);
|
await useEnglish(page);
|
||||||
await page.goto(`/tools/${id}`);
|
await page.goto(`/tools/${slug}`);
|
||||||
await expect(page.getByRole("heading", { level: 1 })).toBeVisible();
|
await expect(page.getByRole("heading", { level: 1 })).toBeVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toolLink(page: Page, id: string): Locator {
|
export function toolLink(page: Page, slug: string): Locator {
|
||||||
return page.locator(`a[href="/tools/${id}"]`);
|
return page.locator(`a[href="/tools/${slug}"]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resultImage(page: Page): Locator {
|
export function resultImage(page: Page): Locator {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
let { title, slug, description, index, icon }: Props = $props();
|
let { title, slug, description, index, icon }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a class="tool-card" href={resolve("/tools/[id]", { id: slug })}>
|
<a class="tool-card" href={resolve("/tools/[slug]", { slug })}>
|
||||||
{#if icon}<span class="tool-icon"><Icon {icon} size={19} /></span>{/if}
|
{#if icon}<span class="tool-icon"><Icon {icon} size={19} /></span>{/if}
|
||||||
<span class="tool-copy">
|
<span class="tool-copy">
|
||||||
<strong>{title}</strong>
|
<strong>{title}</strong>
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ export const en: Dict = {
|
|||||||
textRequired: "Enter text first",
|
textRequired: "Enter text first",
|
||||||
workerFailed: "Worker execution failed",
|
workerFailed: "Worker execution failed",
|
||||||
workerUnavailable: "Worker is unavailable",
|
workerUnavailable: "Worker is unavailable",
|
||||||
notFound: "Tool not found",
|
notFound: "Page not found",
|
||||||
noWatermark: "Pick a watermark image first",
|
noWatermark: "Pick a watermark image first",
|
||||||
badTransform: "Degenerate transformation matrix",
|
badTransform: "Degenerate transformation matrix",
|
||||||
skewAngle: "Skew angles cannot be 90° or -90°",
|
skewAngle: "Skew angles cannot be 90° or -90°",
|
||||||
@@ -189,7 +189,6 @@ export const en: Dict = {
|
|||||||
"Each pixel must be 8 hex characters RRGGBBAA, separated by spaces",
|
"Each pixel must be 8 hex characters RRGGBBAA, separated by spaces",
|
||||||
pixelCountMismatch:
|
pixelCountMismatch:
|
||||||
"Pixel count ({count}) is not divisible by width {width} without a remainder",
|
"Pixel count ({count}) is not divisible by width {width} without a remainder",
|
||||||
toolNotFound: 'Tool "{id}" not found',
|
|
||||||
badJson: "The file is not valid JSON",
|
badJson: "The file is not valid JSON",
|
||||||
badPipelineShape: "The file structure does not look like a chain of steps",
|
badPipelineShape: "The file structure does not look like a chain of steps",
|
||||||
pipelineVersion: "Unsupported chain version: {version}",
|
pipelineVersion: "Unsupported chain version: {version}",
|
||||||
@@ -201,7 +200,7 @@ export const en: Dict = {
|
|||||||
cropSize: "Crop width and height must be positive",
|
cropSize: "Crop width and height must be positive",
|
||||||
sizePositive: "Dimensions must be positive and finite",
|
sizePositive: "Dimensions must be positive and finite",
|
||||||
tooManyParts: "Too many parts ({count}). Maximum is 1000.",
|
tooManyParts: "Too many parts ({count}). Maximum is 1000.",
|
||||||
toolUnknown: 'No tool is registered under "{id}".',
|
pageUnknown: 'No page is registered under "{slug}".',
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
alphaThreshold: "Alpha threshold",
|
alphaThreshold: "Alpha threshold",
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ export const ru: Dict = {
|
|||||||
textRequired: "Сначала введите текст",
|
textRequired: "Сначала введите текст",
|
||||||
workerFailed: "Ошибка исполнения в воркере",
|
workerFailed: "Ошибка исполнения в воркере",
|
||||||
workerUnavailable: "Воркер недоступен",
|
workerUnavailable: "Воркер недоступен",
|
||||||
notFound: "Инструмент не найден",
|
notFound: "Страница не найдена",
|
||||||
noWatermark: "Сначала выберите картинку-знак",
|
noWatermark: "Сначала выберите картинку-знак",
|
||||||
badTransform: "Вырожденная матрица трансформации",
|
badTransform: "Вырожденная матрица трансформации",
|
||||||
skewAngle: "Углы наклона не могут быть 90° или -90°",
|
skewAngle: "Углы наклона не могут быть 90° или -90°",
|
||||||
@@ -190,7 +190,6 @@ export const ru: Dict = {
|
|||||||
"Каждый пиксель — 8 hex-символов RRGGBBAA, значения через пробел",
|
"Каждый пиксель — 8 hex-символов RRGGBBAA, значения через пробел",
|
||||||
pixelCountMismatch:
|
pixelCountMismatch:
|
||||||
"Число пикселей ({count}) не делится на ширину {width} без остатка",
|
"Число пикселей ({count}) не делится на ширину {width} без остатка",
|
||||||
toolNotFound: 'Инструмент "{id}" не найден',
|
|
||||||
badJson: "Файл не является корректным JSON",
|
badJson: "Файл не является корректным JSON",
|
||||||
badPipelineShape: "Структура файла не похожа на цепочку шагов",
|
badPipelineShape: "Структура файла не похожа на цепочку шагов",
|
||||||
pipelineVersion: "Неподдерживаемая версия цепочки: {version}",
|
pipelineVersion: "Неподдерживаемая версия цепочки: {version}",
|
||||||
@@ -202,7 +201,7 @@ export const ru: Dict = {
|
|||||||
cropSize: "Ширина и высота области обрезки должны быть положительными",
|
cropSize: "Ширина и высота области обрезки должны быть положительными",
|
||||||
sizePositive: "Размеры должны быть положительными и конечными",
|
sizePositive: "Размеры должны быть положительными и конечными",
|
||||||
tooManyParts: "Слишком много частей ({count}). Ограничение — 1000.",
|
tooManyParts: "Слишком много частей ({count}). Ограничение — 1000.",
|
||||||
toolUnknown: "Инструмента с id «{id}» нет в реестре.",
|
pageUnknown: "Страницы «{slug}» нет в каталоге.",
|
||||||
},
|
},
|
||||||
fields: {
|
fields: {
|
||||||
alphaThreshold: "Порог альфы",
|
alphaThreshold: "Порог альфы",
|
||||||
|
|||||||
@@ -64,11 +64,12 @@ describe("Смоук §6 i18n (новый UI)", () => {
|
|||||||
expect(t("errors.badHex", { value: "#zz" })).toBe(
|
expect(t("errors.badHex", { value: "#zz" })).toBe(
|
||||||
'Некорректный HEX-цвет: "#zz"',
|
'Некорректный HEX-цвет: "#zz"',
|
||||||
);
|
);
|
||||||
expect(t("errors.toolNotFound", { id: "x" })).toContain("не найден");
|
expect(t("errors.pageUnknown", { slug: "x" })).toContain("каталоге");
|
||||||
setLocale("en");
|
setLocale("en");
|
||||||
expect(t("errors.badHex", { value: "#zz" })).toBe(
|
expect(t("errors.badHex", { value: "#zz" })).toBe(
|
||||||
'Invalid HEX color: "#zz"',
|
'Invalid HEX color: "#zz"',
|
||||||
);
|
);
|
||||||
|
expect(t("errors.pageUnknown", { slug: "x" })).toContain("No page");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("6. Ё не мешает нормализации поискового запроса", () => {
|
it("6. Ё не мешает нормализации поискового запроса", () => {
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
import { PAGES } from "$lib/registry";
|
|
||||||
|
|
||||||
export const prerender = true;
|
|
||||||
|
|
||||||
export function entries() {
|
|
||||||
return PAGES.map((page) => ({ id: page.slug }));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function load({ params }: { params: { id: string } }) {
|
|
||||||
return { id: params.id };
|
|
||||||
}
|
|
||||||
@@ -6,11 +6,11 @@
|
|||||||
import { SlidersHorizontal as ToolIcon } from "@lucide/svelte";
|
import { SlidersHorizontal as ToolIcon } from "@lucide/svelte";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
data: { id: string };
|
data: { slug: string };
|
||||||
}
|
}
|
||||||
let { data }: Props = $props();
|
let { data }: Props = $props();
|
||||||
|
|
||||||
const page = $derived(getPageBySlug(data.id));
|
const page = $derived(getPageBySlug(data.slug));
|
||||||
const tool = $derived(page ? getTool(page.steps[0].id) : undefined);
|
const tool = $derived(page ? getTool(page.steps[0].id) : undefined);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<div class="notfound">
|
<div class="notfound">
|
||||||
<EmptyState
|
<EmptyState
|
||||||
title={t("errors.notFound")}
|
title={t("errors.notFound")}
|
||||||
description={t("errors.toolUnknown", { id: data.id })}
|
description={t("errors.pageUnknown", { slug: data.slug })}
|
||||||
icon={ToolIcon}
|
icon={ToolIcon}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import { PAGES } from "$lib/registry";
|
||||||
|
|
||||||
|
export const prerender = true;
|
||||||
|
|
||||||
|
export function entries() {
|
||||||
|
return PAGES.map((page) => ({ slug: page.slug }));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function load({ params }: { params: { slug: string } }) {
|
||||||
|
return { slug: params.slug };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user