From 3189db663d2e6ef07f8b2870fd96fe4f7073492d Mon Sep 17 00:00:00 2001 From: David Oliver Date: Mon, 11 Sep 2023 18:25:26 +0200 Subject: [PATCH] =?UTF-8?q?Fix=20invalid=20output=20markup=20for=20?= =?UTF-8?q?=E2=80=9Chover=20link=E2=80=9D=20headings=20which=20contain=20t?= =?UTF-8?q?heir=20own=20links=20(#1767)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids nested anchors. Also: - restores cheatsheet h3 hover link icons; - slightly increases contrast of main link underlining. --- assets/css/content/cheatsheet.css | 12 ++--- assets/css/content/general.css | 42 +++++++++++---- assets/css/custom-props/common.css | 1 + assets/css/custom-props/theme-dark.css | 2 +- assets/css/custom-props/theme-light.css | 2 +- lib/ex_doc/formatter/html/templates.ex | 4 +- .../html/templates/module_template.eex | 4 +- test/ex_doc/formatter/epub/templates_test.exs | 4 +- test/ex_doc/formatter/html/templates_test.exs | 54 +++++++++---------- test/ex_doc/formatter/html_test.exs | 4 +- 10 files changed, 74 insertions(+), 55 deletions(-) diff --git a/assets/css/content/cheatsheet.css b/assets/css/content/cheatsheet.css index 4c6b81155..65f7ecafa 100644 --- a/assets/css/content/cheatsheet.css +++ b/assets/css/content/cheatsheet.css @@ -39,16 +39,10 @@ color: var(--main); margin: 0 0 1em; font-weight: 400; - overflow: hidden; } .page-cheatmd .content-inner h3 :is(a, a:visited) { color: var(--main); - text-decoration: none; -} - -.page-cheatmd .content-inner h3.section-heading i { - display: none; } .page-cheatmd .content-inner section.h3 { @@ -58,7 +52,11 @@ break-inside: avoid; } -.page-cheatmd .content-inner h3::after { +.page-cheatmd .content-inner h3 .text { + overflow: hidden; /* Clips generated content horizontal rule */ +} + +.page-cheatmd .content-inner h3 .text::after { content: ""; margin-left: calc(var(--horizontal-space) / 2); vertical-align: baseline; diff --git a/assets/css/content/general.css b/assets/css/content/general.css index ca47e16c9..9269244e9 100644 --- a/assets/css/content/general.css +++ b/assets/css/content/general.css @@ -131,30 +131,50 @@ vertical-align: top; } -.content-inner .section-heading a { +.content-inner .section-heading { + --icon-size: 16px; + --icon-spacing: 5px; + display: grid; + grid-template: 1fr / 1fr; +} + +.content-inner .section-heading > :is(.hover-link, .text) { + grid-row: 1; + grid-column: 1; +} + +.content-inner .section-heading .hover-link { text-decoration: none; } .content-inner .section-heading i { - font-size: 16px; + font-size: var(--icon-size); margin-top: .1em; - margin-left: -21px; + margin-left: calc(-1 * (var(--icon-size) + var(--icon-spacing))); + padding-right: var(--icon-spacing); /* Avoids gap in hover area */ opacity: 0; } -.content-inner .section-heading a:is(:hover, :focus) i { - opacity: 1; +@media screen and (max-width: 768px) { + .content-inner .section-heading i { + margin-left: calc(-1 * (var(--icon-size))); + } } -blockquote .section-heading i { +.content-inner blockquote .section-heading i { display: none; } -@media screen and (max-width: 768px) { - .content-inner .section-heading i { - margin-left: -16px; - margin-right: -5px; - } +.content-inner .section-heading .hover-link:is(:hover, :focus) i { + opacity: 1; +} + +/* Allow section link to be hovered and used “through” text */ +.content-inner .section-heading .text { + pointer-events: none; +} +.content-inner .section-heading .text a { + pointer-events: all; } .content-inner .app-vsn { diff --git a/assets/css/custom-props/common.css b/assets/css/custom-props/common.css index d65b0c35d..5104aecb6 100644 --- a/assets/css/custom-props/common.css +++ b/assets/css/custom-props/common.css @@ -20,6 +20,7 @@ --gray200: hsl(210, 29%, 88% ); --gray300: hsl(210, 26%, 84% ); --gray400: hsl(210, 21%, 64% ); + --gray450: hsl(210, 21%, 49% ); --gray500: hsl(210, 21%, 34% ); --gray600: hsl(210, 27%, 26% ); --gray700: hsl(212, 35%, 17% ); diff --git a/assets/css/custom-props/theme-dark.css b/assets/css/custom-props/theme-dark.css index 887f8f537..2262fb7cd 100644 --- a/assets/css/custom-props/theme-dark.css +++ b/assets/css/custom-props/theme-dark.css @@ -10,7 +10,7 @@ body.dark { --linksVisited: var(--gray100); --linksNoUnderline: var(--main-lightened-10); --linksNoUnderlineVisited: var(--main-lightened-05); - --linksDecoration: var(--gray500); + --linksDecoration: var(--gray450); --iconAction: var(--coldGray-lightened-10); --iconActionHover: var(--white); diff --git a/assets/css/custom-props/theme-light.css b/assets/css/custom-props/theme-light.css index 608644ab9..a029dd101 100644 --- a/assets/css/custom-props/theme-light.css +++ b/assets/css/custom-props/theme-light.css @@ -10,7 +10,7 @@ --linksVisited: var(--black); --linksNoUnderline: var(--main-darkened-10); --linksNoUnderlineVisited: var(--main-darkened-20); - --linksDecoration: var(--gray400); + --linksDecoration: var(--gray450); --iconAction: var(--coldGray); --iconActionHover: var(--gray800); diff --git a/lib/ex_doc/formatter/html/templates.ex b/lib/ex_doc/formatter/html/templates.ex index 74ebc3baf..e9086201a 100644 --- a/lib/ex_doc/formatter/html/templates.ex +++ b/lib/ex_doc/formatter/html/templates.ex @@ -302,10 +302,10 @@ defmodule ExDoc.Formatter.HTML.Templates do """ <#{tag} id="#{prefix}#{id}" class="#{class_attribute}"> - + - #{title} + #{title} """ end diff --git a/lib/ex_doc/formatter/html/templates/module_template.eex b/lib/ex_doc/formatter/html/templates/module_template.eex index 195caef2b..eb60636dd 100644 --- a/lib/ex_doc/formatter/html/templates/module_template.eex +++ b/lib/ex_doc/formatter/html/templates/module_template.eex @@ -33,8 +33,8 @@

- Summary + Summary

<%= for {name, nodes} <- summary, do: summary_template(name, nodes) %> @@ -45,8 +45,8 @@

- <%= name %> + <%= name %>

<%= for node <- nodes, do: detail_template(node, module) %> diff --git a/test/ex_doc/formatter/epub/templates_test.exs b/test/ex_doc/formatter/epub/templates_test.exs index 0c9f7c300..e7359d886 100644 --- a/test/ex_doc/formatter/epub/templates_test.exs +++ b/test/ex_doc/formatter/epub/templates_test.exs @@ -60,10 +60,10 @@ defmodule ExDoc.Formatter.EPUB.TemplatesTest do assert content =~ ~r{

\s*CompiledWithDocs\s*} assert content =~ - ~r{

.*.*.*Example.*.*

}ms + ~r{

.*Example.*

}ms assert content =~ - ~r{

.*.*.*Example H3 heading.*.*

}ms + ~r{

.*Example H3 heading.*

}ms assert content =~ ~r{moduledoc.*Example.*CompiledWithDocs\.example.*}ms diff --git a/test/ex_doc/formatter/html/templates_test.exs b/test/ex_doc/formatter/html/templates_test.exs index 7d0188660..aabb9ae66 100644 --- a/test/ex_doc/formatter/html/templates_test.exs +++ b/test/ex_doc/formatter/html/templates_test.exs @@ -47,61 +47,61 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do test "generates headers with hovers" do assert Templates.link_headings("

Foo

Bar

") == """

- + - Foo + Foo

- + - Bar + Bar

""" assert Templates.link_headings("

Foo

\n

Bar

") == """

- + - Foo + Foo

- + - Bar + Bar

""" assert Templates.link_headings("

Bar

") == """

- + - Bar + Bar

""" assert Templates.link_headings("

\n

Bar

") == """

- + - Bar + Bar

""" assert Templates.link_headings("

Foo

") == String.trim_trailing("""

- + - Foo + Foo

""") @@ -109,10 +109,10 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do assert Templates.link_headings("

Foo

\n

") == String.trim_trailing("""

- + - Foo + Foo

@@ -120,10 +120,10 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do assert Templates.link_headings("

Foo

") == """

- + - Foo + Foo

""" end @@ -131,17 +131,17 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do test "generates headers with unique id's" do assert Templates.link_headings("

Foo

\n

Foo

") == """

- + - Foo + Foo

- + - Foo + Foo

""" end @@ -153,10 +153,10 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do assert Templates.link_headings(admonition_block) == """

- + - Foo + Foo

""" @@ -471,10 +471,10 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do ~r{moduledoc.*Example.*CompiledWithDocs\.example.*}ms assert content =~ - ~r{

.*.*.*Example.*.*

}ms + ~r{

.*.*.*.*Example ☃ Unicode > escaping.*

}ms assert content =~ - ~r{

.*.*.*Example H3 heading.*.*

}ms + ~r{

.*.*.*.*Example H3 heading.*

}ms # Summaries assert content =~ ~r{example/2.*Some example}ms @@ -567,7 +567,7 @@ defmodule ExDoc.Formatter.HTML.TemplatesTest do content = get_module_page([CompiledWithDocs], context) assert content =~ - ~r{

.*.*.*Examples.*.*

}ms + ~r{

.*.*.*.*Examples.*

}ms end test "do not output overlapping functions, causing duplicate IDs", context do diff --git a/test/ex_doc/formatter/html_test.exs b/test/ex_doc/formatter/html_test.exs index 03490d5f4..98e3c64e8 100644 --- a/test/ex_doc/formatter/html_test.exs +++ b/test/ex_doc/formatter/html_test.exs @@ -365,10 +365,10 @@ defmodule ExDoc.Formatter.HTMLTest do assert content =~ ~r{README [^<]*} assert content =~ - ~r{

.*.*.*Header sample.*.*

}ms + ~r{

.*.*.*.*Header sample.*

}ms assert content =~ - ~r{

.*.*.*more > than.*.*

}ms + ~r{

.*.*.*.*more > than.*

}ms assert content =~ ~r{RandomError}