- Show exclude/delete buttons on hover for images inside a group; deleting an
image still referenced elsewhere in the vault now asks for confirmation
before touching the original file.
- Track each image's own start/end offset within its line (getImageMatches)
so dragging one image out of a line with multiple images no longer removes
or disturbs its neighbors.
- Group the image settings panel into labeled sections (Canvas size /
Appearance) for clarity.
Also satisfies Obsidian's plugin lint pass: bump tsconfig `lib` to ES2019
(Object.entries/Array.flat were silently type-checked only via @types/node's
hidden lib reference, not the project's own lib config), switch remaining
bare `document` event listeners to `activeDocument` for popout-window
compatibility, and replace `el.closest(...) as HTMLElement | null` with the
explicit `el.closest<HTMLElement>(...)` generic form (the `as` cast was
itself supplying the contextual type that made the assertion look
redundant to `no-unnecessary-type-assertion`).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Source imports EditorView directly from @codemirror/view (used by
editor-drop-target.ts, hover-group-trigger.ts, image-drag-source.ts,
markdown/persistence.ts), but these packages only existed as peer-dependency
resolutions of obsidian, not as top-level devDependencies. Locally pnpm
auto-hoists them so the build worked, but CI's `pnpm install --frozen-lockfile`
did not reliably hoist them, causing tsc to fail with "Cannot find module
'@codemirror/view'" — this is why the pushed 1.3.6 tag's release workflow
run failed and no GitHub release was ever created for it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The pnpm override pinned js-yaml to ^4.1.1, but the DoS advisory
(GHSA-h67p-54hq-rp68) covers <=4.1.1 with the fix landing in 4.2.0 —
so the override was resolving straight to the vulnerable version.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
gh release create --draft has been requiring a manual "Publish release"
click on GitHub after every CI run since this workflow was added; if that
step gets forgotten, Obsidian's manifest.json version has no matching
public release ("No release matches your manifest version"). Every prior
release was published this way by hand. Drop --draft so a green CI run is
itself the publish step, and pull release notes from the pushed annotated
tag's message (with --generate-notes as a fallback for lightweight tags)
instead of leaving the release body empty.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The native edit-block-button on an ungrouped image embed appears on
:focus-within, not :hover — anchoring the injected Group button to the
same trigger keeps the two visually and behaviorally consistent (previously
the Group button showed on .cm-embed-block:hover, which could appear/disappear
independently of the native button). Switches the button to a real <button>
element, resets its native button chrome (background/border/height) to match
the plain-div edit-block-button, and raises its own CSS specificity so it
reliably sits above the native button's focus z-index without !important.
Also resolves the event target via UIEvent.targetNode (Node) instead of the
raw EventTarget from e.target, so the eligibility check can use Obsidian's
cross-window-safe .instanceOf() instead of a bare instanceof that breaks for
notes opened in a popout window.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Design-mockup exports and screenshots often carry a solid-color canvas
border (e.g. black padding), which a plain center-square crop bakes into
the thumbnail whenever the padded side is the one left untouched by the
crop. detectContentRect heuristically finds and trims that border before
cropping. Off by default risk of false positives on content that's itself
close to a solid background is mitigated by a settings toggle
(enableThumbnailBorderTrim, on by default) to fall back to the old
full-image center crop.
Also fixes thumbnail generation to update every <img> waiting on a given
thumbnail path, not just the one passed into the first call — the same
thumbnail can be requested by multiple re-renders of the same code block
before generation finishes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Dragging a standalone image into a group could silently fail (optimistic
temp wrapper never rolled back) because persistDragInsertToSource read the
file via vault.read(), which measurably lags behind the live CodeMirror
editor buffer for a currently-open file — an in-bounds line index computed
from the editor would come back out-of-bounds a moment later. Reading from
the live editor buffer instead (readCurrentContent) removes the stale-read
window entirely; persistence calls now also report success/failure so the
caller can roll back the optimistic DOM insert on failure, and are queued
per file path so overlapping drags can't interleave their reads and writes.
Also guards the code-block re-render lifecycle: rapid re-renders of the same
`el` (e.g. triggered by the plugin's own writes) could leave a stale
container's settingWrapper/click-listener/drag-sort bindings alive alongside
the new render, causing duplicated event handling and drag indicator glitches.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Instead of tracking hover state and positioning the Group button manually,
inject it once next to the native edit-block-button and let CSS hover rules
handle show/hide together.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The button is a fixed-position element appended to document.body and
only cleaned up via mouseover/mouseout. Native drag-and-drop suppresses
those events for the drag's duration, so when the hovered image was
dragged into a group the underlying <img> was removed by the editor
re-render but the floating button was never told to clean up, leaving
it stuck at the image's old position. Removing it on dragstart for the
active image closes that gap.
The <img> is draggable by the browser by default, so starting a drag
on it made the browser treat the <img> itself as the native drag
source and auto-populate drag data from img.src, which points at the
cached thumbnail rather than the original file. This raced with the
plugin's own wrapper-level drag payload and let Obsidian's drop
handling embed the cache path instead. Disabling native drag on the
<img> forces the wrapper (which carries the correct markdown line) to
be the sole drag source.
Adds a container-level drag target highlight and a row-based nearest-
image fallback so dropping between images or in trailing blank space
inserts at the expected position, not just directly on a wrapper.
Reuses the CM6-based line mapping from the hover-to-group button to
identify the drag source, and performs the removal + insertion as a
single vault read-modify-write to avoid a two-write race. Guards
against cross-file drags and same-line multi-image cases.
Avoids conflicting with other plugins' image right-click menus by
triggering the imgs-block conversion via a hover overlay button
instead, using CM6's public EditorView API to map the DOM image back
to its source line.