mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
chore: clear lint rules warns: comments, tests
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
interface Props {
|
||||
title: string;
|
||||
description: string;
|
||||
/** Путь страницы от корня роутера ("/", "/list-tools", "/tools/…"). */
|
||||
/** Page path from the router root ("/", "/list-tools", "/tools/..."). */
|
||||
path: string;
|
||||
}
|
||||
let { title, description, path }: Props = $props();
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
label: string;
|
||||
value: unknown;
|
||||
spec: FieldSpec;
|
||||
/** Размеры входа шага: потолок осей для maxFromSource-полей. */
|
||||
/** Step input dimensions: axis cap for maxFromSource fields. */
|
||||
sourceDims?: Dimension;
|
||||
onchange?: (value: Dimension, axis?: "width" | "height" | "both") => void;
|
||||
}
|
||||
@@ -51,7 +51,7 @@
|
||||
}
|
||||
|
||||
function applyPreset(n: number) {
|
||||
// Пресет задаёт обе оси явно — lockAspect его не пересчитывает.
|
||||
// Preset sets both axes explicitly; lockAspect does not recompute it.
|
||||
onchange?.({ width: n, height: n }, "both");
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
let root = $state<HTMLDivElement | null>(null);
|
||||
|
||||
function choose(mime: OutputMime) {
|
||||
// Меню — ещё и панель настроек формата: не закрываем при выборе,
|
||||
// чтобы можно было сразу настроить качество.
|
||||
// Menu doubles as a format-settings panel: keep it open on select
|
||||
// so quality can be tuned right away.
|
||||
onformat(mime);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
schema: ToolSchema<Record<string, unknown>>;
|
||||
values: Record<string, unknown>;
|
||||
toolId: string;
|
||||
/** Размеры входа шага: для maxFromSource-полей (crop и т.п.). */
|
||||
/** Step input dimensions: for maxFromSource fields (crop, etc.). */
|
||||
sourceDims?: Dimension;
|
||||
onchange: (
|
||||
id: string,
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
let parts = $derived(
|
||||
resultKind === "files" && fileResult ? fileResult.files.length : undefined,
|
||||
);
|
||||
// Размеры одинаковы у всех частей (канвас дополняется) — показываем один раз.
|
||||
// All parts share the same size (canvas is padded); show it once.
|
||||
let partsDims = $derived(
|
||||
resultKind === "files" && fileResult && fileResult.files.length > 0
|
||||
? `${fileResult.files[0].image.width} × ${fileResult.files[0].image.height}`
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
let dragging = $state(false);
|
||||
let input = $state<HTMLInputElement | null>(null);
|
||||
// Подсказка замены: показываем на ховер и гасим через 10с до нового захода.
|
||||
// Replace hint: show on hover, fade after 10s until the next hover.
|
||||
let hintVisible = $state(false);
|
||||
let hintTimer: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
|
||||
@@ -76,10 +76,10 @@
|
||||
const inputMode = $derived(tool.input);
|
||||
|
||||
let steps = $state<ChainStep[]>([]);
|
||||
// Поля, изменённые пользователем (по шагам): при загрузке нового файла им не
|
||||
// даём перезаписаться source-дефолтами. Reset шага снимает пометку.
|
||||
// Fields edited by the user (per step): on new file load they must not be
|
||||
// overwritten by source defaults. Step reset clears the mark.
|
||||
const touchedByStep = new SvelteMap<string, SvelteSet<string>>();
|
||||
// Последняя правленая ось dimension-поля — ведущая при lockAspect.
|
||||
// Last edited axis of a dimension field; leads under lockAspect.
|
||||
const lastAxis: Record<string, "width" | "height"> = {};
|
||||
let stepDims = $state<(Dimension | undefined)[]>([]);
|
||||
let stepResults = $state<(PixelImage | null)[]>([]);
|
||||
@@ -96,7 +96,7 @@
|
||||
let displayError = $state<DisplayError | null>(null);
|
||||
let initedFor = $state("");
|
||||
let format = $state<OutputMime>("image/png");
|
||||
// Качество lossy-форматов для инструментов без quality-параметра в схеме.
|
||||
// Lossy-format quality for tools without a quality param in the schema.
|
||||
let formatQuality = $state<Record<string, number>>({});
|
||||
let dragFrom = $state<number | null>(null);
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
tool,
|
||||
);
|
||||
const resultKind = $derived(lastTool.result ?? "image");
|
||||
// Цепочку можно продолжить, только если последний шаг отдаёт картинку.
|
||||
// Chain can be extended only if the last step outputs an image.
|
||||
const canExtend = $derived((lastTool.result ?? "image") === "image");
|
||||
const alignedMode = $derived(
|
||||
aligned && resultKind === "image" && steps.length > 1,
|
||||
@@ -117,8 +117,8 @@
|
||||
!outputFormatByMime(format).supportsAlpha &&
|
||||
hasTransparency(result),
|
||||
);
|
||||
// Если в схеме последнего шага есть quality-параметр (convert-инструменты),
|
||||
// он — единый источник качества; dropdown редактирует его же.
|
||||
// If the last step's schema has a quality param (convert tools), it is the
|
||||
// single source of quality; the dropdown edits the same value.
|
||||
const qualityParamId = $derived(lastTool.output?.qualityParamId);
|
||||
const lastParams = $derived(steps.at(-1)?.params);
|
||||
const resultNote = $derived(
|
||||
@@ -196,8 +196,8 @@
|
||||
const next: Record<string, unknown> = { ...step.params, [id]: value };
|
||||
const stepSchema = toolSchemaOf(step);
|
||||
const spec = stepSchema?.fields[id]?.spec;
|
||||
// Аспект считается от входа шага: для первого — исходник, для остальных —
|
||||
// результат предыдущего шага (размеры известны после прогона).
|
||||
// Aspect derives from the step input: source for the first step,
|
||||
// previous step's result for the rest (dims known after the run).
|
||||
const dims = index === 0 ? (source ?? undefined) : stepDims[index - 1];
|
||||
if (dims && stepSchema && spec) {
|
||||
const aspect = dims.width / dims.height;
|
||||
@@ -213,7 +213,7 @@
|
||||
aspect,
|
||||
);
|
||||
} else if (spec.kind === "checkbox" && value === true) {
|
||||
// Включили lockAspect — сразу подгоняем привязанные поля под аспект.
|
||||
// lockAspect just enabled: snap bound fields to the aspect at once.
|
||||
for (const [fid, f] of Object.entries(stepSchema.fields)) {
|
||||
const fs = f.spec;
|
||||
if (fs.kind === "dimension" && fs.lockAspectWith === id) {
|
||||
@@ -261,8 +261,8 @@
|
||||
steps = steps.with(index, { ...step, collapsed: !step.collapsed });
|
||||
}
|
||||
|
||||
// Замена инструмента на месте: ключ и свёрнутость шага сохраняются,
|
||||
// параметры — дефолты нового инструмента, вход пересчитывается при прогоне.
|
||||
// In-place tool swap: step key and collapsed state are kept, params become
|
||||
// the new tool's defaults, input is recomputed on run.
|
||||
function replaceStepTool(index: number, toolId: string) {
|
||||
const step = steps[index];
|
||||
const next = createStep(toolId);
|
||||
@@ -433,7 +433,7 @@
|
||||
init();
|
||||
});
|
||||
|
||||
// Цепочка персистится по slug страницы; сохраняем после инициализации.
|
||||
// Chain persists per page slug; save only after initialization.
|
||||
$effect(() => {
|
||||
if (!initedFor) return;
|
||||
void steps;
|
||||
|
||||
@@ -18,12 +18,12 @@ function input(over: Partial<SchemaPreviewModelInput> = {}) {
|
||||
}
|
||||
|
||||
describe("hasPreviewResult", () => {
|
||||
it("image: результат только при наличии картинки", () => {
|
||||
it("image: result only when image present", () => {
|
||||
expect(hasPreviewResult(input({ result: image }))).toBe(true);
|
||||
expect(hasPreviewResult(input())).toBe(false);
|
||||
});
|
||||
|
||||
it("files: результат только при непустом наборе", () => {
|
||||
it("files: result only for non-empty set", () => {
|
||||
const fileResult = { files: [{ name: "part.png", image }] };
|
||||
expect(hasPreviewResult(input({ resultKind: "files", fileResult }))).toBe(
|
||||
true,
|
||||
@@ -36,7 +36,7 @@ describe("hasPreviewResult", () => {
|
||||
});
|
||||
|
||||
it.each(["text", "verdict"] as const)(
|
||||
"%s: результат по наличию текста",
|
||||
"%s: result depends on text presence",
|
||||
(resultKind) => {
|
||||
expect(hasPreviewResult(input({ resultKind, textResult: "done" }))).toBe(
|
||||
true,
|
||||
|
||||
@@ -9,7 +9,7 @@ export type SchemaPreviewModelInput = {
|
||||
textResult: string | null;
|
||||
};
|
||||
|
||||
/** Можно ли скачать результат: он есть и он не пустой. */
|
||||
/** Whether the result is downloadable: it exists and is non-empty. */
|
||||
export function hasPreviewResult(input: SchemaPreviewModelInput): boolean {
|
||||
const { resultKind, result, fileResult, textResult } = input;
|
||||
if (resultKind === "image") return Boolean(result);
|
||||
|
||||
Reference in New Issue
Block a user