diff --git a/src/docs.ts b/src/docs.ts index 277d8ec9..04f1d071 100644 --- a/src/docs.ts +++ b/src/docs.ts @@ -17,6 +17,7 @@ export const DOCS_BASE_URL = "https://quickadd.obsidian.guide"; export const DOCS_URLS = { gettingStarted: `${DOCS_BASE_URL}/docs/`, + formatSyntax: `${DOCS_BASE_URL}/docs/FormatSyntax/`, onePageInputs: `${DOCS_BASE_URL}/docs/Advanced/onePageInputs/`, userScripts: `${DOCS_BASE_URL}/docs/Choices/MacroChoice/#user-scripts`, packages: `${DOCS_BASE_URL}/docs/Choices/Packages/`, diff --git a/src/gui/ChoiceBuilder/CaptureChoiceForm.svelte b/src/gui/ChoiceBuilder/CaptureChoiceForm.svelte index 16590adc..3a577a3b 100644 --- a/src/gui/ChoiceBuilder/CaptureChoiceForm.svelte +++ b/src/gui/ChoiceBuilder/CaptureChoiceForm.svelte @@ -12,6 +12,7 @@ import ChoiceNameHeader from "./components/ChoiceNameHeader.svelte"; import ValidatedInput from "./components/ValidatedInput.svelte"; import LabeledField from "./components/LabeledField.svelte"; import FormatPreviewField from "./components/FormatPreviewField.svelte"; +import FormatTokenHint from "./components/FormatTokenHint.svelte"; import AppendLinkSetting from "./components/AppendLinkSetting.svelte"; import OpenFileSetting from "./components/OpenFileSetting.svelte"; import FileOpeningSetting from "./components/FileOpeningSetting.svelte"; @@ -170,6 +171,7 @@ function onTemplaterAfterCaptureChange(value: boolean) { requiredMessage="Capture format is required when enabled" makeSuggesters={formatSuggesters} /> + {/snippet} diff --git a/src/gui/ChoiceBuilder/TemplateChoiceForm.svelte b/src/gui/ChoiceBuilder/TemplateChoiceForm.svelte index aee1ebc6..44f5867f 100644 --- a/src/gui/ChoiceBuilder/TemplateChoiceForm.svelte +++ b/src/gui/ChoiceBuilder/TemplateChoiceForm.svelte @@ -34,6 +34,7 @@ import ChoiceNameHeader from "./components/ChoiceNameHeader.svelte"; import ValidatedInput from "./components/ValidatedInput.svelte"; import LabeledField from "./components/LabeledField.svelte"; import FormatPreviewField from "./components/FormatPreviewField.svelte"; +import FormatTokenHint from "./components/FormatTokenHint.svelte"; import AppendLinkSetting from "./components/AppendLinkSetting.svelte"; import OpenFileSetting from "./components/OpenFileSetting.svelte"; import FileOpeningSetting from "./components/FileOpeningSetting.svelte"; @@ -222,6 +223,7 @@ function onModeChange(value: string) { placeholder="File name format" makeSuggesters={fileNameSuggesters} /> + + {#if !usesPickerTargetSyntax} {/if} diff --git a/src/gui/ChoiceBuilder/components/FormatTokenHint.svelte b/src/gui/ChoiceBuilder/components/FormatTokenHint.svelte new file mode 100644 index 00000000..528f110a --- /dev/null +++ b/src/gui/ChoiceBuilder/components/FormatTokenHint.svelte @@ -0,0 +1,35 @@ + + +{#if shown} +
+ Type {{ to insert a token · + Format syntax +
+{/if} diff --git a/src/gui/ChoiceBuilder/components/FormatTokenHint.test.ts b/src/gui/ChoiceBuilder/components/FormatTokenHint.test.ts new file mode 100644 index 00000000..373cd6a0 --- /dev/null +++ b/src/gui/ChoiceBuilder/components/FormatTokenHint.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, it } from "vitest"; +import { render } from "@testing-library/svelte"; +import { tick } from "svelte"; +import FormatTokenHint from "./FormatTokenHint.svelte"; +import { DOCS_URLS } from "../../../docs"; + +const hint = (container: HTMLElement) => + container.querySelector(".qa-token-hint"); + +/** + * Issue #1542, ask 1. The token autocomplete opens on `{{` and nothing said so. + */ +describe("FormatTokenHint", () => { + it("names the two characters that open the autocomplete", async () => { + const { container } = render(FormatTokenHint, { props: { value: "" } }); + await tick(); + + const text = hint(container as HTMLElement)?.textContent ?? ""; + expect(text).toContain("{{"); + expect(text).toContain("to insert a token"); + }); + + it("links the format syntax reference", async () => { + const { container } = render(FormatTokenHint, { props: { value: "" } }); + await tick(); + + const link = container.querySelector("a.quickadd-docs-link"); + expect(link?.getAttribute("href")).toBe(DOCS_URLS.formatSyntax); + expect(link?.getAttribute("target")).toBe("_blank"); + expect(link?.getAttribute("rel")).toBe("noopener noreferrer"); + }); + + it("stays out of the way once the field uses a token", async () => { + const { container } = render(FormatTokenHint, { + props: { value: "- [ ] {{VALUE}}" }, + }); + await tick(); + expect(hint(container as HTMLElement)).toBeNull(); + }); + + it("shows again if the user removes every token", async () => { + const { container, rerender } = render(FormatTokenHint, { + props: { value: "{{DATE}}" }, + }); + await tick(); + expect(hint(container as HTMLElement)).toBeNull(); + + await rerender({ value: "plain text" }); + await tick(); + expect(hint(container as HTMLElement)).not.toBeNull(); + }); +}); diff --git a/src/styles.css b/src/styles.css index 855e159e..80cd0cfb 100644 --- a/src/styles.css +++ b/src/styles.css @@ -232,6 +232,19 @@ border: 0; } +/* "Type {{ to insert a token" under a format field (#1542). A quiet secondary + line, matching .qa-preview-row: it is a teaching aid, not part of the field. */ +.quickAddModal .qa-token-hint { + margin: -4px 0 8px; + font-size: var(--font-ui-smaller); + color: var(--text-muted); +} +.quickAddModal .qa-token-hint code { + font-size: inherit; + padding: 1px 4px; + border-radius: var(--radius-s, 4px); +} + /* Problems the preview pass ran into, shown here instead of as a Notice per keystroke (#1558). Colour carries severity — no glyph — matching .qa-folder-mode-warning. Clamped with the full text in `title`, because the