Skip to content

Commit 8dc9784

Browse files
ggrossetieclaude
andcommitted
fix(core): encode spaces in data: URI image targets
AbstractNode#imageUri() short-circuited on any data: URI target by returning it unchanged, added to avoid a spurious "could not retrieve image data from URI" warning when embedding inline SVGs. That bypassed the space-encoding that normalizeWebPath() still applies to every other URI-ish target, and that upstream Asciidoctor (Ruby) also applies since image_uri has no data:-specific early return. Run data: targets through encodeSpacesInUri() before returning them so output matches Ruby again. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent f1c93e5 commit 8dc9784

3 files changed

Lines changed: 16 additions & 2 deletions

File tree

CHANGELOG.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ For a detailed view of what has changed, refer to the {uri-repo}/commits/main[co
1010

1111
Bug Fixes::
1212

13+
* Fix `AbstractNode#imageUri()` no longer percent-encoding spaces in a `data:` URI image target (e.g. `image::data:image/svg+xml,<svg ...><text>a b</text></svg>[]`), a regression from the data URI image target support added for inline SVG embedding. That change short-circuited `imageUri()` for any `data:` target by returning it unchanged, bypassing the space-encoding that `normalizeWebPath()` still applies for every other URI-ish target — and that upstream Asciidoctor (Ruby) also applies, since `image_uri` has no `data:`-specific early return at all. `imageUri()` now runs `data:` targets through `encodeSpacesInUri()` before returning them, matching Ruby's output byte-for-byte, while still avoiding the spurious `could not retrieve image data from URI` warning the earlier fix was meant to prevent
1314
* Fix `tasks/changelog.js notes` (used to generate GitHub release notes) leaving AsciiDoc attribute references such as `{uri-repo}/issues/1857[#1857]` unresolved in the generated Markdown. `extractReleaseNotes` used to extract the raw AsciiDoc section for a release and convert only that fragment to Markdown, losing the `:uri-repo:` attribute definition from the changelog header in the process. The whole changelog is now converted to Markdown once, and the release section is extracted from the resulting Markdown instead, so attribute references resolve correctly
1415
* Type `Logger#warn()`/`#debug()`/`#info()`/`#error()`/`#fatal()`/`#unknown()`/`#log()` (and the matching `MemoryLogger` methods) with an optional `progname`/`pn` parameter instead of a required one. The generated `.d.ts` previously declared both arguments as mandatory, so calling `doc.getLogger().warn(doc.messageWithContext(...))` with a single argument — the documented pattern for logging from an extension — was flagged by editors as "expected 2 arguments" even though it is valid at runtime; the error surfaced because `getLogger()` resolves to the `LoggerLike` union (`Logger | MemoryLogger | NullLogger | Console`) and TypeScript requires a call to satisfy every member's signature
1516
* Type `messageWithContext()`/`createLogMessage()` on `Document`, `ConverterBase`, `PathResolver`, and `Table.ParserContext` (and the static equivalents on `Parser`). These are installed at runtime by the `applyLogging()` mixin (`logging.js`) *after* the class body closes, so `tsc`'s JSDoc-based declaration emit never picked them up — `doc.messageWithContext(...)`, the pattern shown in the extensions guide, previously had no type at all on the public API surface

packages/core/src/abstract_node.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,10 @@ export class AbstractNode {
475475
* @returns {Promise<string>} a Promise resolving to a String reference or data URI.
476476
*/
477477
async imageUri(targetImage, assetDirKey = 'imagesdir') {
478-
// A data URI is already an embedded image, so use it as-is rather than reading or re-encoding it.
479-
if (targetImage.startsWith('data:')) return targetImage
478+
// A data URI is already an embedded image, so use it as-is (aside from space
479+
// encoding, which normalizeWebPath would otherwise apply) rather than reading
480+
// or re-encoding it.
481+
if (targetImage.startsWith('data:')) return encodeSpacesInUri(targetImage)
480482
const doc = this.document
481483
if (doc.safe < SafeMode.SECURE && doc.hasAttribute('data-uri')) {
482484
let imagesBase

packages/core/test/blocks.images.test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,17 @@ image::data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=[Do
793793
)
794794
})
795795

796+
test('encodes spaces in an embedded data uri image target', async () => {
797+
const input =
798+
"image::data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><text>a b</text></svg>[Dot]"
799+
const output = await convertStringToEmbedded(input)
800+
assert.ok(
801+
output.includes(
802+
"data:image/svg+xml,<svg%20xmlns='http://www.w3.org/2000/svg'><text>a%20b</text></svg>"
803+
)
804+
)
805+
})
806+
796807
test('cleans reference to ancestor directories in imagesdir before reading image if safe mode level is at least SAFE', async () => {
797808
await usingMemoryLogger(async (logger) => {
798809
const input = `\

0 commit comments

Comments
 (0)