Change:
<!-- Do Not Delete This! bugreporttemplate --<!-- Please read our Rules of Conduct: --<!-- Read our guide about submitting issues: --<!-- Search existing issues to avoid creating duplicates. --<!-- Test using the latest Insiders build to see if your issue has already been fixed: --<!-- Instead of creating your report here, use 'Report Issue' from the 'Help' menu in VS Code to pre-fill useful information. --<!-- Launch with to check. --Does this issue occur when all extensions are disabled?: Yes/No <!-- If you answered No above, use 'Help: Start Extension Bisect' from Command Palette to try to identify the cause. --<!-- Issues caused by an extension need to be reported directly to the extension publisher. The 'Help Report Issue' dialog can assist with this. --- VS Code Version: 1.68.1 OS Version: Windows 10 Steps to Reproduce: a Markdown file and open "Open Preview to the Side" add line: ! image in preview second line: ! second image shows up. Remove the line above image preview shows 2 images and does not update properly !
Thanks for creating this issue! It looks like you may be using an old version of VS Code, the latest stable release is 1.68.1. Please try upgrading to the latest version and checking whether this issue remains. Happy Coding!
Still happens in 1.68.1. Updating bug
Does this reproduce in the with all ?
Yes still happens with all extensions disabled

Discussion:
import { Slugifier } from './slugify'; import { ITextDocument } from './types/textDocument'; import { Disposable } from './util/dispose'; <del> import { stringHash } from './util/hash'; </del> import { WebviewResourceProvider } from './util/resources'; import { isOfScheme, Schemes } from './util/schemes'; import { MdDocumentInfoCache } from './util/workspaceCache';

export interface RenderOutput { html: string; <del> containingImages: { src: string }[]; </del> <ins> containingImages: Set<string>; </ins> } interface RenderEnv { <del> containingImages: { src: string }[]; </del> <ins> containingImages: Set<string>; </ins> currentDocument: vscode.Uri | undefined; resourceProvider: WebviewResourceProvider | undefined; }

: this.tokenizeDocument(input, config, engine); const env: RenderEnv = { <del> containingImages: [], </del> <ins> containingImages: new Set<string>(), </ins> currentDocument: typeof input === 'string' ? undefined : input.uri, resourceProvider, };

const original = md.renderer.rules.image; md.renderer.rules.image = (tokens: Token[], idx: number, options, env: RenderEnv, self) => { const token = tokens[idx]; <del> token.attrJoin('class', 'loading'); </del> const src = token.attrGet('src'); if (src) { <del> env.containingImages?.push({ src }); const imgHash = stringHash(src); token.attrSet('id', `image-hash-${imgHash}`); </del> <ins> env.containingImages?.add(src); </ins> if (!token.attrGet('data-src')) { token.attrSet('src', this.toResourceUri(src, env.currentDocument, env.resourceProvider));

export interface MarkdownContentProviderOutput { html: string; <del> containingImages: { src: string }[]; </del> <ins> containingImages: Set<string>; </ins> }

const body = await this.renderBody(markdownDocument, resourceProvider); if (token.isCancellationRequested) { <del> return { html: '', containingImages: [] }; </del> <ins> return { html: '', containingImages: new Set() }; </ins> } const html = `<!DOCTYPE html>

} } <del> private updateImageWatchers(containingImages: { src: string }[]) { const srcs = new Set(containingImages.map(img => img.src)); </del> <ins> private updateImageWatchers(srcs: Set<string>) { </ins> // Delete stale file watchers. for (const [src, watcher] of this._fileWatchersBySrc) { if (!srcs.has(src)) {

}); }); <del> suite('image-caching', () => { </del> <ins> suite.only('image-caching', () => { </ins> const input = '![](img.png) [](no-img.png) ![](http://example.org/img.png) ![](img.png) ![](./img2.png)'; test('Extracts all images', async () => { const engine = createNewMarkdownEngine(); <del> assert.deepStrictEqual((await engine.render(input)), { html: '<p data-line="0" class="code-line" dir="auto">' + '<img src="img.png" alt="" class="loading" id="image-hash--754511435" data-src="img.png"> ' + '<a href="no-img.png" data-href="no-img.png"></a> ' + '<img src="http://example.org/img.png" alt="" class="loading" id="image-hash--1903814170" data-src="http://example.org/img.png"> ' + '<img src="img.png" alt="" class="loading" id="image-hash--754511435" data-src="img.png"> ' + '<img src="./img2.png" alt="" class="loading" id="image-hash-265238964" data-src="./img2.png">' + '</p>n' , containingImages: [{ src: 'img.png' }, { src: 'http://example.org/img.png' }, { src: 'img.png' }, { src: './img2.png' }], }); </del> <ins> const result = await engine.render(input); assert.deepStrictEqual(result.html, '<p data-line="0" class="code-line" dir="auto">' + '<img src="img.png" alt="" data-src="img.png"> ' + '<a href="no-img.png" data-href="no-img.png"></a> ' + '<img src="http://example.org/img.png" alt="" data-src="http://example.org/img.png"> ' + '<img src="img.png" alt="" data-src="img.png"> ' + '<img src="./img2.png" alt="" data-src="./img2.png">' + '</p>n' ); assert.deepStrictEqual([...result.containingImages], ['img.png', 'http://example.org/img.png', './img2.png']); </ins> }); }); });

<del> /*--------------------------------------------------------------------------------------------- *  Copyright (c) Microsoft Corporation. All rights reserved. *  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ function numberHash(val: number, initialHashVal: number): number { return (((initialHashVal << 5) - initialHashVal) + val) | 0;  // hashVal * 31 + ch, keep as int32 } export function stringHash(s: string) { let hashVal = numberHash(149417, 0); for (let i = 0, length = s.length; i < length; i++) { hashVal = numberHash(s.charCodeAt(i), hashVal); } return hashVal; } </del>