Skip to content

Commit 4c59f9e

Browse files
committed
Updated Hero text
1 parent 567bb29 commit 4c59f9e

File tree

7 files changed

+220
-5
lines changed

7 files changed

+220
-5
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { JSDOM } from 'jsdom';
3+
4+
import { applyOssHomeHeroNameClipClass, OSS_HOME_HERO_NAME_CLIP_CLASS } from './ossHeroClass.ts';
5+
6+
describe('ossHeroClass', () => {
7+
it('adds oss-home-name-clip to the hero name clip span when DOCS_HOSTNAME is not mermaid.ai', () => {
8+
const { window } = new JSDOM(`
9+
<div class="VPHomeHero">
10+
<div class="main">
11+
<h1 class="heading">
12+
<span class="name clip"><span class="home-header">Mermaid.js now lives</span></span>
13+
</h1>
14+
</div>
15+
</div>
16+
`);
17+
18+
const added = applyOssHomeHeroNameClipClass({
19+
doc: window.document,
20+
hostname: 'mermaid.js.org',
21+
pathname: '/',
22+
});
23+
24+
expect(added).toBe(1);
25+
expect(
26+
window.document.querySelector('.name.clip')?.classList.contains(OSS_HOME_HERO_NAME_CLIP_CLASS)
27+
).toBe(true);
28+
});
29+
30+
it('also adds the class for other non-mermaid.ai DOCS_HOSTNAME values (e.g. localhost)', () => {
31+
const { window } = new JSDOM(`
32+
<div class="VPHomeHero">
33+
<h1 class="heading"><span class="name clip">X</span></h1>
34+
</div>
35+
`);
36+
37+
const added = applyOssHomeHeroNameClipClass({
38+
doc: window.document,
39+
hostname: 'localhost',
40+
pathname: '/',
41+
});
42+
43+
expect(added).toBe(1);
44+
expect(
45+
window.document.querySelector('.name.clip')?.classList.contains(OSS_HOME_HERO_NAME_CLIP_CLASS)
46+
).toBe(true);
47+
});
48+
49+
it('does nothing when hostname is mermaid.ai', () => {
50+
const { window } = new JSDOM(`
51+
<div class="VPHomeHero">
52+
<h1 class="heading"><span class="name clip">X</span></h1>
53+
</div>
54+
`);
55+
56+
const added = applyOssHomeHeroNameClipClass({
57+
doc: window.document,
58+
hostname: 'mermaid.ai',
59+
pathname: '/',
60+
});
61+
62+
expect(added).toBe(0);
63+
expect(
64+
window.document.querySelector('.name.clip')?.classList.contains(OSS_HOME_HERO_NAME_CLIP_CLASS)
65+
).toBe(false);
66+
});
67+
68+
it('does nothing when hostname is a mermaid.ai subdomain', () => {
69+
const { window } = new JSDOM(`
70+
<div class="VPHomeHero">
71+
<h1 class="heading"><span class="name clip">X</span></h1>
72+
</div>
73+
`);
74+
75+
const added = applyOssHomeHeroNameClipClass({
76+
doc: window.document,
77+
hostname: 'www.mermaid.ai',
78+
pathname: '/',
79+
});
80+
81+
expect(added).toBe(0);
82+
expect(
83+
window.document.querySelector('.name.clip')?.classList.contains(OSS_HOME_HERO_NAME_CLIP_CLASS)
84+
).toBe(false);
85+
});
86+
87+
it('does nothing off the homepage path', () => {
88+
const { window } = new JSDOM(`
89+
<div class="VPHomeHero">
90+
<h1 class="heading"><span class="name clip">X</span></h1>
91+
</div>
92+
`);
93+
94+
const added = applyOssHomeHeroNameClipClass({
95+
doc: window.document,
96+
hostname: 'mermaid.js.org',
97+
pathname: '/intro/',
98+
});
99+
100+
expect(added).toBe(0);
101+
});
102+
103+
it('is idempotent (does not report changes when class already exists)', () => {
104+
const { window } = new JSDOM(`
105+
<div class="VPHomeHero">
106+
<h1 class="heading"><span class="name clip">X</span></h1>
107+
</div>
108+
`);
109+
110+
const first = applyOssHomeHeroNameClipClass({
111+
doc: window.document,
112+
hostname: 'mermaid.js.org',
113+
pathname: '/',
114+
});
115+
const second = applyOssHomeHeroNameClipClass({
116+
doc: window.document,
117+
hostname: 'mermaid.js.org',
118+
pathname: '/',
119+
});
120+
121+
expect(first).toBe(1);
122+
expect(second).toBe(0);
123+
});
124+
});
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
export const OSS_HOME_HERO_NAME_CLIP_CLASS = 'oss-home-name-clip';
2+
3+
const HOME_PATHS = new Set<string>(['', '/', '/index.html']);
4+
const HERO_NAME_CLIP_SELECTOR = '.VPHomeHero .heading .name.clip';
5+
6+
function isMermaidAiHostname(hostname: string): boolean {
7+
const hn = hostname.toLowerCase();
8+
return hn === 'mermaid.ai' || hn.endsWith('.mermaid.ai');
9+
}
10+
11+
/**
12+
* Adds an extra class to the VitePress homepage hero name clip span.
13+
*
14+
* This is intentionally implemented as a small DOM helper so it can be unit tested.
15+
*/
16+
export function applyOssHomeHeroNameClipClass({
17+
doc,
18+
hostname,
19+
pathname,
20+
className = OSS_HOME_HERO_NAME_CLIP_CLASS,
21+
}: {
22+
doc: Document;
23+
hostname: string;
24+
pathname: string;
25+
className?: string;
26+
}): number {
27+
// Enabled on all deployments except mermaid.ai (and subdomains).
28+
if (isMermaidAiHostname(hostname)) {
29+
return 0;
30+
}
31+
32+
if (!HOME_PATHS.has(pathname)) {
33+
return 0;
34+
}
35+
36+
const els = doc.querySelectorAll<HTMLElement>(HERO_NAME_CLIP_SELECTOR);
37+
let added = 0;
38+
for (const el of els) {
39+
if (!el.classList.contains(className)) {
40+
el.classList.add(className);
41+
added++;
42+
}
43+
}
44+
45+
return added;
46+
}

packages/mermaid/src/docs/.vitepress/style/main.css

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,13 @@ img.resizable-img {
7676
}
7777
}
7878

79-
a.link-home {
79+
a.home-link {
8080
text-decoration: underline;
8181
color: var(--vp-c-brand-1);
82-
font-size: larger;
82+
}
83+
84+
.VPHomeHero .heading .name.clip.oss-home-name-clip {
85+
--vp-home-hero-name-color: var(--vp-c-text-1);
86+
--vp-home-hero-name-background: none;
87+
color: var(--vp-c-text-1);
8388
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { defineComponent, nextTick, onMounted } from 'vue';
2+
3+
import { applyOssHomeHeroNameClipClass } from '../ossHeroClass.js';
4+
5+
/**
6+
* Option B: a small Home-only component that applies `oss-home-name-clip`
7+
* to VitePress' hero name wrapper after mount.
8+
*/
9+
export default defineComponent({
10+
name: 'OssHomeHeroNameClipApplier',
11+
setup() {
12+
const run = async () => {
13+
// Client-only.
14+
if (typeof window === 'undefined') {
15+
return;
16+
}
17+
18+
// Ensure DOM is flushed.
19+
await nextTick();
20+
21+
applyOssHomeHeroNameClipClass({
22+
doc: document,
23+
hostname: window.location.hostname,
24+
pathname: window.location.pathname,
25+
});
26+
};
27+
28+
onMounted(() => {
29+
void run();
30+
});
31+
32+
// No markup needed.
33+
return () => null;
34+
},
35+
});

packages/mermaid/src/docs/.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import HomePage from '../components/HomePage.vue';
66
import TopBar from '../components/TopBar.vue';
77
import './custom.css';
88
import Mermaid from './Mermaid.vue';
9+
import OssHomeHeroNameClipApplier from './OssHomeHeroNameClipApplier.js';
910
import { getRedirect } from './redirect.js';
1011
import Tooltip from './Tooltip.vue';
1112
// @ts-ignore Type not available
@@ -21,6 +22,7 @@ export default {
2122
return h(Theme.Layout, null, {
2223
'home-features-after': () => h(HomePage),
2324
'home-hero-before': () => h(TopBar),
25+
'home-hero-after': () => h(OssHomeHeroNameClipApplier),
2426
'doc-before': () => h(TopBar),
2527
'layout-bottom': () => h(Tooltip),
2628
'layout-top': () => h(EditorSelectionModal),

packages/mermaid/src/docs/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ sidebar: false
55
title: Mermaid
66
titleTemplate: Diagramming and charting tool
77
hero:
8-
name: <a href="https://Mermaid.ai/open-source?utm_medium=hero&utm_campaign=variant_a&utm_source=mermaid_js">Mermaid</a>
9-
text: Has a New Home
10-
tagline: The Mermaid ecosystem — including the open-source diagramming library and our commercial platform for teams — now lives at <a class="link-home"href="https://Mermaid.ai/open-source?utm_medium=hero&utm_campaign=variant_a&utm_source=mermaid_js">mermaid.ai</a>. This legacy site will remain available.
8+
name: <span class="home-header">Mermaid.js now lives</span>
9+
text: at <a href="https://Mermaid.ai/open-source?utm_medium=hero&utm_campaign=variant_a&utm_source=mermaid_js" class="home-link">mermaid.ai</a>
10+
tagline: One home for the open-source library and the platform built around it. More resources for the project, a clearer path for contributors, and a team committed to keeping Mermaid open, always.
1111

1212
image:
1313
light: /hero-chart.svg

packages/mermaid/src/docs/vite.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const virtualModuleId = 'virtual:mermaid-config';
1313
const resolvedVirtualModuleId = '\0' + virtualModuleId;
1414

1515
export default defineConfig({
16+
define: {
17+
__DOCS_HOSTNAME__: JSON.stringify(process.env.DOCS_HOSTNAME ?? 'mermaid.js.org'),
18+
},
1619
build: {
1720
// Vite v7 changes the default target and drops old browser support
1821
target: 'modules',

0 commit comments

Comments
 (0)