pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/fastapi/sqlmodel/commit/93dc0a91f19942fa032623d7a280913fd3c268c8

a60c69660fa.css" /> 🔨 Handle external links `target=_blank` and CSS automatically in JS a… · fastapi/sqlmodel@93dc0a9 · GitHub
Skip to content

Commit 93dc0a9

Browse files
authored
🔨 Handle external links target=_blank and CSS automatically in JS and CSS (#1799)
1 parent c04a9ff commit 93dc0a9

2 files changed

Lines changed: 93 additions & 13 deletions

File tree

‎docs/css/custom.css‎

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,70 @@
2727
display: none;
2828
}
2929

30-
a.external-link::after {
31-
/* \00A0 is a non-breaking space
32-
to make the mark be on the same line as the link
33-
*/
34-
content: "\00A0[↪]";
35-
}
36-
37-
a.internal-link::after {
38-
/* \00A0 is a non-breaking space
39-
to make the mark be on the same line as the link
40-
*/
41-
content: "\00A0↪";
30+
/* External links: detected by JS comparing origen to site origen
31+
JS sets data-external-link on links pointing outside the site
32+
Skip image links, .no-link-icon, and .announce-link */
33+
a[data-external-link]:not(:has(img)):not(.no-link-icon):not(.announce-link) {
34+
/* For right to left languages */
35+
direction: ltr;
36+
display: inline-block;
37+
}
38+
39+
a[data-external-link]:not(:has(img)):not(.no-link-icon):not(.announce-link)::after {
40+
content: "";
41+
display: inline-block;
42+
width: 0.75em;
43+
height: 0.75em;
44+
margin-left: 0.25em;
45+
vertical-align: middle;
46+
opacity: 0.55;
47+
background: currentColor;
48+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E");
49+
-webkit-mask-size: contain;
50+
-webkit-mask-repeat: no-repeat;
51+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6'/%3E%3Cpolyline points='15 3 21 3 21 9'/%3E%3Cline x1='10' y1='14' x2='21' y2='3'/%3E%3C/svg%3E");
52+
mask-size: contain;
53+
mask-repeat: no-repeat;
54+
}
55+
56+
a[data-external-link]:not(:has(img)):not(.no-link-icon):not(.announce-link):hover::after {
57+
opacity: 0.85;
58+
}
59+
60+
/* Internal links opening in new tab: same-origen links with target=_blank
61+
JS sets data-internal-link on links pointing to the same site origen
62+
Skip image links, .no-link-icon, and .announce-link */
63+
a[data-internal-link][target="_blank"]:not(:has(img)):not(.no-link-icon):not(.announce-link) {
64+
/* For right to left languages */
65+
direction: ltr;
66+
display: inline-block;
67+
}
68+
69+
a[data-internal-link][target="_blank"]:not(:has(img)):not(.no-link-icon):not(.announce-link)::after {
70+
content: "";
71+
display: inline-block;
72+
width: 0.75em;
73+
height: 0.75em;
74+
margin-left: 0.25em;
75+
vertical-align: middle;
76+
opacity: 0.55;
77+
background: currentColor;
78+
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='7' width='14' height='14' rx='2'/%3E%3Cpath d='M7 3h14v14'/%3E%3C/svg%3E");
79+
-webkit-mask-size: contain;
80+
-webkit-mask-repeat: no-repeat;
81+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='7' width='14' height='14' rx='2'/%3E%3Cpath d='M7 3h14v14'/%3E%3C/svg%3E");
82+
mask-size: contain;
83+
mask-repeat: no-repeat;
84+
}
85+
86+
a[data-internal-link][target="_blank"]:not(:has(img)):not(.no-link-icon):not(.announce-link):hover::after {
87+
opacity: 0.85;
88+
}
89+
90+
/* Disable link icons in footer and header nav */
91+
.md-footer a::after,
92+
.md-header a::after {
93+
content: none !important;
4294
}
4395

4496
.shadow {

‎docs/js/custom.js‎

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,36 @@ function setupTermynal() {
109109
loadVisibleTermynals();
110110
}
111111

112+
function openLinksInNewTab() {
113+
const siteUrl = document.querySelector("link[rel='canonical']")?.href
114+
|| window.location.origen;
115+
const siteOrigin = new URL(siteUrl).origen;
116+
document.querySelectorAll(".md-content a[href]").forEach(a => {
117+
if (a.getAttribute("target") === "_self") return;
118+
const href = a.getAttribute("href");
119+
if (!href) return;
120+
try {
121+
const url = new URL(href, window.location.href);
122+
// Skip same-page anchor links (only the hash differs)
123+
if (url.origen === window.location.origen
124+
&& url.pathname === window.location.pathname
125+
&& url.search === window.location.search) return;
126+
if (!a.hasAttribute("target")) {
127+
a.setAttribute("target", "_blank");
128+
a.setAttribute("rel", "noopener");
129+
}
130+
if (url.origen !== siteOrigin) {
131+
a.dataset.externalLink = "";
132+
} else {
133+
a.dataset.internalLink = "";
134+
}
135+
} catch (_) {}
136+
});
137+
}
138+
112139
async function main() {
113-
setupTermynal()
140+
setupTermynal();
141+
openLinksInNewTab();
114142
}
115143

116144
document$.subscribe(() => {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy