Skip to content

Commit ad418ac

Browse files
theletterfMpdreamz
andauthored
Automatically use alt text as title for images when no title is provided (#1656)
* Update docs and add alt fallback * Fix override * Update src/Elastic.Markdown/Myst/Directives/Image/ImageBlock.cs Co-authored-by: Martijn Laarman <[email protected]> * Update images.md * Add example size directive --------- Co-authored-by: Martijn Laarman <[email protected]>
1 parent d37a8a3 commit ad418ac

File tree

6 files changed

+62
-26
lines changed

6 files changed

+62
-26
lines changed

docs/syntax/images.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -60,38 +60,40 @@ Here is the same image used inline ![Elasticsearch](/syntax/images/observability
6060

6161
### Inline image titles
6262

63-
Titles are optional making this the minimal syntax required
63+
Titles are optional making this the minimal syntax required:
6464

6565
```markdown
6666
![Elasticsearch](/syntax/images/observability.png)
6767
```
6868

69-
Including a title can be done by supplying it as an optional argument.
69+
For inline images, the alt text always overrides any title specified in the Markdown. This ensures consistent accessibility where both the `alt` and `title` attributes contain the same descriptive text.
7070

7171
```markdown
72-
![Elasticsearch](/syntax/images/observability.png "elasticsearch")
72+
![Elasticsearch](/syntax/images/observability.png "Different title")
7373
```
7474

75-
### Inline image sizing
75+
![Elasticsearch](/syntax/images/observability.png "Different title =50%x50%")
76+
7677

77-
Inline images are supplied at the end through the title argument.
78+
### Inline image sizing
7879

79-
This is done to maintain maximum compatibility with markdown parsers
80-
and previewers.
80+
Image sizing is specified through the title argument. You can specify just the size without needing to provide a redundant title:
8181

8282
```markdown
83-
![alt](img.png "title =WxH")
84-
![alt](img.png "title =W")
83+
![alt](img.png "=WxH")
84+
![alt](img.png "=W")
8585
```
8686

87+
In this case, the alt text will be used as both the `alt` and `title` attributes, and the size parameters will be applied.
88+
8789
`W` and `H` can be either an absolute number in pixels or a number followed by `%` to indicate relative sizing.
8890

8991
If `H` is omitted `W` is used as the height as well.
9092

9193
```markdown
92-
![alt](img.png "title =250x330")
93-
![alt](img.png "title =50%x40%")
94-
![alt](img.png "title =50%")
94+
![alt](img.png "=250x330")
95+
![alt](img.png "=50%x40%")
96+
![alt](img.png "=50%")
9597
```
9698

9799

@@ -138,7 +140,7 @@ The image carousel directive builds upon the image directive.
138140

139141
:::{image} images/applies.png
140142
:alt: Second image description
141-
:title: Second image title
143+
### Title is optional - alt text will be used as title if not specified
142144
:::
143145

144146
::::

src/Elastic.Markdown/Myst/Directives/Image/ImageBlock.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ public override void FinalizeAndValidate(ParserContext context)
7474
{
7575
Label = Prop("label", "name");
7676
Alt = Prop("alt")?.ReplaceSubstitutions(context) ?? string.Empty;
77-
Title = Prop("title")?.ReplaceSubstitutions(context);
77+
// Use Alt as Title if no explicit Title is provided
78+
var explicitTitle = Prop("title")?.ReplaceSubstitutions(context);
79+
Title = string.IsNullOrEmpty(explicitTitle) ? Alt : explicitTitle;
7880

7981
Align = Prop("align");
8082
Height = Prop("height", "h");

src/Elastic.Markdown/Myst/Renderers/HtmxLinkInlineRenderer.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ protected override void Write(HtmlRenderer renderer, LinkInline link)
2020
{
2121
if (renderer.EnableHtmlForInline && !link.IsImage)
2222
{
23-
// ReSharper disable once UnusedVariable
2423
if (link.GetData(nameof(ParserContext.CurrentUrlPath)) is not string currentUrl)
2524
{
2625
base.Write(renderer, link);
@@ -70,9 +69,42 @@ protected override void Write(HtmlRenderer renderer, LinkInline link)
7069

7170
_ = renderer.Write("</a>");
7271
}
72+
else if (link.IsImage)
73+
{
74+
// Handle inline images with ALT override logic
75+
WriteImage(renderer, link);
76+
}
7377
else
7478
base.Write(renderer, link);
7579
}
80+
81+
private static void WriteImage(HtmlRenderer renderer, LinkInline link)
82+
{
83+
_ = renderer.Write("<img src=\"");
84+
_ = renderer.WriteEscapeUrl(link.GetDynamicUrl?.Invoke() ?? link.Url);
85+
_ = renderer.Write('"');
86+
87+
// Write alt text using WriteChildren to ensure substitutions are processed
88+
if (link.FirstChild != null)
89+
{
90+
_ = renderer.Write(" alt=\"");
91+
renderer.WriteChildren(link);
92+
_ = renderer.Write('"');
93+
}
94+
95+
// Write any additional attributes (like width/height from styling instructions)
96+
_ = renderer.WriteAttributes(link);
97+
98+
// Set title to alt text for inline images (after any substitutions are processed)
99+
if (link.FirstChild != null)
100+
{
101+
_ = renderer.Write(" title=\"");
102+
renderer.WriteChildren(link);
103+
_ = renderer.Write('"');
104+
}
105+
106+
_ = renderer.Write(" />");
107+
}
76108
}
77109

78110
public static class CustomLinkInlineRendererExtensions

tests/Elastic.Markdown.Tests/Inline/SubstitutionTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ public class ReplaceInImageTitle(ITestOutputHelper output) : InlineTest(output,
203203
[Fact]
204204
public void OnlySeesGlobalVariable() =>
205205
Html.Should().NotContain("title=\"{{hello-world}}\"")
206-
.And.Contain("title=\"Hello World\"");
206+
.And.Contain("title=\"Observability\"");
207207
}
208208

209209
public class MutationOperatorTest(ITestOutputHelper output) : InlineTest(output,

tests/authoring/Blocks/ImageBlocks.fs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type ``static path to image`` () =
1818
[<Fact>]
1919
let ``validate src is anchored`` () =
2020
markdown |> convertsToContainingHtml """
21-
<img loading="lazy" alt="Elasticsearch" src="/img/observability.png" style="width: 250px;" class="screenshot">
21+
<img loading="lazy" title="Elasticsearch" alt="Elasticsearch" src="/img/observability.png" style="width: 250px;" class="screenshot">
2222
"""
2323

2424
type ``supports --url-path-prefix`` () =
@@ -45,13 +45,13 @@ type ``supports --url-path-prefix`` () =
4545
[<Fact>]
4646
let ``validate image src contains prefix`` () =
4747
docs |> convertsToContainingHtml """
48-
<img loading="lazy" alt="Elasticsearch" src="/docs/img/observability.png" style="width: 250px;" class="screenshot">
48+
<img loading="lazy" title="Elasticsearch" alt="Elasticsearch" src="/docs/img/observability.png" style="width: 250px;" class="screenshot">
4949
"""
5050

5151
[<Fact>]
5252
let ``validate image src contains prefix when referenced relatively`` () =
5353
docs |> converts "folder/relative.md" |> containsHtml """
54-
<img loading="lazy" alt="Elasticsearch" src="/docs/img/observability.png" style="width: 250px;" class="screenshot">
54+
<img loading="lazy" title="Elasticsearch" alt="Elasticsearch" src="/docs/img/observability.png" style="width: 250px;" class="screenshot">
5555
"""
5656

5757
[<Fact>]
@@ -73,7 +73,7 @@ type ``image ref out of scope`` () =
7373
[<Fact>]
7474
let ``validate image src contains prefix and is anchored to documentation scope root`` () =
7575
docs |> convertsToContainingHtml """
76-
<img loading="lazy" alt="Elasticsearch" src="/docs/img/observability.png" style="width: 250px;" class="screenshot">
76+
<img loading="lazy" title="Elasticsearch" alt="Elasticsearch" src="/docs/img/observability.png" style="width: 250px;" class="screenshot">
7777
"""
7878

7979
[<Fact>]

tests/authoring/Inline/InlineAppliesTo.fs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type ``static path to image`` () =
1515
[<Fact>]
1616
let ``validate HTML: generates link and alt attr`` () =
1717
markdown |> convertsToHtml """
18-
<p><img src="/_static/img/observability.png" alt="Elasticsearch" /></p>
18+
<p><img src="/_static/img/observability.png" alt="Elasticsearch" title="Elasticsearch" /></p>
1919
"""
2020

2121
type ``relative path to image`` () =
@@ -26,7 +26,7 @@ type ``relative path to image`` () =
2626
[<Fact>]
2727
let ``validate HTML: preserves relative path`` () =
2828
markdown |> convertsToHtml """
29-
<p><img src="/_static/img/observability.png" alt="Elasticsearch" /></p>
29+
<p><img src="/_static/img/observability.png" alt="Elasticsearch" title="Elasticsearch" /></p>
3030
"""
3131

3232
type ``supplying a tittle`` () =
@@ -37,7 +37,7 @@ type ``supplying a tittle`` () =
3737
[<Fact>]
3838
let ``validate HTML: includes title`` () =
3939
markdown |> convertsToHtml """
40-
<p><img src="/_static/img/observability.png" alt="Elasticsearch" title="Hello world" /></p>
40+
<p><img src="/_static/img/observability.png" alt="Elasticsearch" title="Elasticsearch" /></p>
4141
"""
4242

4343
type ``supplying a tittle with width and height`` () =
@@ -48,7 +48,7 @@ type ``supplying a tittle with width and height`` () =
4848
[<Fact>]
4949
let ``validate HTML: does not include width and height in title`` () =
5050
markdown |> convertsToHtml """
51-
<p><img src="/obs.png" width="250px" height="400px" alt="o" title="Title"/></p>
51+
<p><img src="/obs.png" width="250px" height="400px" alt="o" title="o"/></p>
5252
"""
5353

5454
type ``supplying a tittle with width and height in percentage`` () =
@@ -59,7 +59,7 @@ type ``supplying a tittle with width and height in percentage`` () =
5959
[<Fact>]
6060
let ``validate HTML: does not include width and height in title`` () =
6161
markdown |> convertsToHtml """
62-
<p><img src="/obs.png" width="50%" height="40%" alt="o" title="Title"/></p>
62+
<p><img src="/obs.png" width="50%" height="40%" alt="o" title="o"/></p>
6363
"""
6464
type ``supplying a tittle with width only`` () =
6565
static let markdown = Setup.Markdown """
@@ -69,5 +69,5 @@ type ``supplying a tittle with width only`` () =
6969
[<Fact>]
7070
let ``validate HTML: sets height to width if not supplied`` () =
7171
markdown |> convertsToHtml """
72-
<p><img src="/obs.png" width="30%" height="30%" alt="o" title="Title"/></p>
72+
<p><img src="/obs.png" width="30%" height="30%" alt="o" title="o"/></p>
7373
"""

0 commit comments

Comments
 (0)