diff --git a/build.mjs b/build.mjs index 5fed98a..ed897f0 100644 --- a/build.mjs +++ b/build.mjs @@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url'; import { Marked } from 'marked'; -import { docShell, esc, GITHUB_URL, highlightTokens, SITE_URL } from './src/layout.mjs'; +import { docShell, esc, EXT_ATTRS, GITHUB_URL, highlightTokens, SITE_URL } from './src/layout.mjs'; import { renderLanding } from './src/landing.mjs'; import { renderImpressum } from './src/impressum.mjs'; import { renderLicense } from './src/license.mjs'; @@ -128,7 +128,7 @@ const marked = new Marked({ const text = this.parser.parseInline(tokens); const t = title ? ` title="${esc(title)}"` : ''; const url = rewriteHref(href); - const ext = /^https?:/.test(url) ? ' rel="external"' : ''; + const ext = /^https?:/.test(url) ? EXT_ATTRS : ''; return `${text}`; }, code({ text, lang }) { diff --git a/src/impressum.mjs b/src/impressum.mjs index d40d5ee..db812de 100644 --- a/src/impressum.mjs +++ b/src/impressum.mjs @@ -1,6 +1,6 @@ // Legal notice (Impressum) - a fully static, hand-written page. Required to be // reachable from every page under German law (§5 DDG); linked from the footer. -import { esc, pageShell } from './layout.mjs'; +import { esc, EXT_ATTRS, pageShell } from './layout.mjs'; export function renderImpressum({ version }) { const body = `
@@ -22,7 +22,7 @@ Email: mentorfilou@gmail.com

Editorial responsibility

-Lennard Solterbeck and the flashtrace team +Lennard Solterbeck and the flashtrace team
`; diff --git a/src/landing.mjs b/src/landing.mjs index 12ccb6f..358dc4d 100644 --- a/src/landing.mjs +++ b/src/landing.mjs @@ -1,7 +1,7 @@ // The landing page: hero with a CSS-built IDE mock, how-it-works, features, // curated interactive examples, install snippets. All static HTML. import { colorizeReport, examples, heroTerminal } from './examples.mjs'; -import { esc, GITHUB_URL, highlightTokens, pageShell } from './layout.mjs'; +import { esc, EXT_ATTRS, GITHUB_URL, highlightTokens, pageShell } from './layout.mjs'; // --- hero IDE mock ----------------------------------------------------------- @@ -215,7 +215,7 @@ npx flashtrace" aria-label="Copy install commands">Copy

Vendored, zero install

-

Download dist/flashtrace.mjs into your repository and run it directly.

+

Download dist/flashtrace.mjs into your repository and run it directly.

node flashtrace.mjs
@@ -233,7 +233,7 @@ export function renderLanding({ version, gitRef }) {

flashtrace verifies that every requirement in your Markdown specs is covered by the code and tests it demands - with zero runtime dependencies, anywhere Node.js runs.

Get started - View on GitHub + View on GitHub
${ideMock()} diff --git a/src/layout.mjs b/src/layout.mjs index b4937ce..72a790f 100644 --- a/src/layout.mjs +++ b/src/layout.mjs @@ -4,6 +4,10 @@ export const SITE_URL = 'https://flashtrace.github.io'; export const GITHUB_URL = 'https://github.com/flashtrace/flashtrace'; export const DISCUSSIONS_URL = 'https://github.com/flashtrace/flashtrace/discussions'; +// Attributes for links leaving the site: open a new tab. Links that should +// also show the "↗" marker add class="ext-mark" (styled in site.css). +export const EXT_ATTRS = ' target="_blank" rel="external noopener"'; + export function esc(s) { return String(s) .replaceAll('&', '&') @@ -49,13 +53,13 @@ function topBar({ version, active, withSidebar }) { flashtrace - ${esc(version)} + ${esc(version)}
- ${githubIcon} + ${githubIcon} @@ -73,8 +77,8 @@ function footer({ version }) {
diff --git a/src/license.mjs b/src/license.mjs index 6fd569f..aa92455 100644 --- a/src/license.mjs +++ b/src/license.mjs @@ -3,7 +3,7 @@ // recognized as Apache 2.0, a GitHub-style summary panel is shown above it; // an unrecognized license falls back to the raw text alone rather than // risking a wrong summary. -import { esc, pageShell } from './layout.mjs'; +import { esc, EXT_ATTRS, pageShell } from './layout.mjs'; // Octicons (MIT): law, check, x, info. const lawIcon = ``; @@ -31,7 +31,7 @@ ${col('Permissions', 'lic-ok', checkIcon, ['Commercial use', 'Modification', 'Di ${col('Limitations', 'lic-no', xIcon, ['Trademark use', 'Liability', 'Warranty'])} ${col('Conditions', 'lic-info', infoIcon, ['License and copyright notice', 'State changes'])} -

This is not legal advice. Learn more about the Apache License 2.0.

+

This is not legal advice. Learn more about the Apache License 2.0.

`; } diff --git a/src/styles/site.css b/src/styles/site.css index c42c66c..ddadce0 100644 --- a/src/styles/site.css +++ b/src/styles/site.css @@ -118,6 +118,14 @@ a:hover { text-decoration: underline; } +/* Opt-in "↗" marker for external links; the arrow-worthy ones add this class + next to EXT_ATTRS (\FE0E forces text over emoji presentation). */ +.ext-mark::after { + content: '\2197\FE0E'; + font-size: 0.75em; + margin-left: 0.15em; +} + img { max-width: 100%; }