coherent-docs-theme 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/icons/native.png +0 -0
- package/assets/icons/unity.png +0 -0
- package/assets/icons/unreal.png +0 -0
- package/components/GallerySlider.astro +50 -15
- package/components/GamefaceDocsSidebar.astro +7 -0
- package/components/Highlight.astro +30 -0
- package/components/Link.astro +19 -0
- package/components/LinkCardGrid.astro +63 -0
- package/components/NativeLink.astro +24 -0
- package/components/Summary.astro +18 -0
- package/components/index.ts +23 -0
- package/index.ts +92 -22
- package/internal/themeConfig.ts +33 -3
- package/internal-components/BreadcrumbArrow.astro +12 -0
- package/internal-components/NavLinks.astro +15 -4
- package/internal-components/TopicSwitcher.astro +207 -0
- package/overrides/Footer.astro +133 -3
- package/overrides/MarkdownContent.astro +14 -0
- package/overrides/PageTitle.astro +341 -0
- package/overrides/Search.astro +28 -3
- package/package.json +8 -5
- package/remark-directives/apiRefFixLinks.ts +39 -0
- package/remark-directives/fixAbsoluteLinks.ts +54 -0
- package/remark-directives/index.ts +5 -1
- package/remark-directives/productName.ts +29 -0
- package/styles.css +1 -1
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
---
|
|
2
|
+
import DefaultPageTitle from "@astrojs/starlight/components/PageTitle.astro";
|
|
3
|
+
import SidebarSublist from "@astrojs/starlight/components/SidebarSublist.astro";
|
|
4
|
+
import getThemeConfig from "../internal/themeConfig";
|
|
5
|
+
import readingTime from "reading-time";
|
|
6
|
+
import BreadcrumbArrow from "../internal-components/BreadcrumbArrow.astro";
|
|
7
|
+
|
|
8
|
+
const { breadcrumbs: showBreadcrumbs } = getThemeConfig();
|
|
9
|
+
//@ts-ignore
|
|
10
|
+
const routeData = Astro.locals.starlightRoute ?? Astro.props;
|
|
11
|
+
const { sidebar, entry } = routeData;
|
|
12
|
+
|
|
13
|
+
//@ts-ignore
|
|
14
|
+
function findActiveTrail(entries, currentTrail = []) {
|
|
15
|
+
if (!entries) return null;
|
|
16
|
+
|
|
17
|
+
for (const item of entries) {
|
|
18
|
+
if (item.type === "link" && item.isCurrent) {
|
|
19
|
+
return [...currentTrail, item];
|
|
20
|
+
}
|
|
21
|
+
if (item.type === "group") {
|
|
22
|
+
//@ts-ignore
|
|
23
|
+
const trail = findActiveTrail(item.entries, [
|
|
24
|
+
//@ts-ignore
|
|
25
|
+
...currentTrail,
|
|
26
|
+
//@ts-ignore
|
|
27
|
+
item,
|
|
28
|
+
]);
|
|
29
|
+
if (trail) return trail;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const activeTrail = findActiveTrail(sidebar) || [];
|
|
36
|
+
const base = import.meta.env.BASE_URL.replace(/\/$/, "");
|
|
37
|
+
|
|
38
|
+
const stats = readingTime(entry?.body || "");
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
showBreadcrumbs && activeTrail.length > 0 && (
|
|
43
|
+
<div class="breadcrumb-header">
|
|
44
|
+
<nav aria-label="Breadcrumb" class="breadcrumbs">
|
|
45
|
+
<ol>
|
|
46
|
+
<li>
|
|
47
|
+
<a href={`${base}/`} class="link">
|
|
48
|
+
Home
|
|
49
|
+
</a>
|
|
50
|
+
</li>
|
|
51
|
+
|
|
52
|
+
{activeTrail
|
|
53
|
+
.slice(0, -1)
|
|
54
|
+
.map((group: any, index: number) => (
|
|
55
|
+
<li class="dropdown-wrapper sidebar-content">
|
|
56
|
+
<details class="crumb-details">
|
|
57
|
+
<summary class="crumb-summary link">
|
|
58
|
+
{group.label}
|
|
59
|
+
<BreadcrumbArrow />
|
|
60
|
+
</summary>
|
|
61
|
+
|
|
62
|
+
<div
|
|
63
|
+
class="dropdown-menu"
|
|
64
|
+
data-menu-id={`menu-${index}`}
|
|
65
|
+
>
|
|
66
|
+
<SidebarSublist
|
|
67
|
+
sublist={group.entries}
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
</details>
|
|
71
|
+
{index === activeTrail.length - 1 && (
|
|
72
|
+
<BreadcrumbArrow />
|
|
73
|
+
)}
|
|
74
|
+
</li>
|
|
75
|
+
))}
|
|
76
|
+
|
|
77
|
+
<li class="end-label">
|
|
78
|
+
<BreadcrumbArrow />
|
|
79
|
+
<span class="current" aria-current="page">
|
|
80
|
+
{activeTrail[activeTrail.length - 1]?.label ||
|
|
81
|
+
entry?.data?.title ||
|
|
82
|
+
"Page"}
|
|
83
|
+
</span>
|
|
84
|
+
</li>
|
|
85
|
+
</ol>
|
|
86
|
+
</nav>
|
|
87
|
+
<div class="read-time">
|
|
88
|
+
<svg
|
|
89
|
+
width="14"
|
|
90
|
+
height="14"
|
|
91
|
+
viewBox="0 0 24 24"
|
|
92
|
+
fill="none"
|
|
93
|
+
stroke="currentColor"
|
|
94
|
+
stroke-width="2"
|
|
95
|
+
stroke-linecap="round"
|
|
96
|
+
stroke-linejoin="round"
|
|
97
|
+
>
|
|
98
|
+
<circle cx="12" cy="12" r="10" />
|
|
99
|
+
<polyline points="12 6 12 12 16 14" />
|
|
100
|
+
</svg>
|
|
101
|
+
READ TIME: {Math.ceil(stats.minutes)} MIN
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
<DefaultPageTitle {...Astro.props} />
|
|
108
|
+
|
|
109
|
+
<script>
|
|
110
|
+
const detailsElements = document.querySelectorAll(".crumb-details");
|
|
111
|
+
|
|
112
|
+
document.addEventListener("click", (e) => {
|
|
113
|
+
const target = e.target as HTMLElement;
|
|
114
|
+
if (!target.closest(".dropdown-wrapper")) {
|
|
115
|
+
detailsElements.forEach((details) => {
|
|
116
|
+
details.removeAttribute("open");
|
|
117
|
+
details
|
|
118
|
+
.closest(".dropdown-wrapper")
|
|
119
|
+
?.classList.remove("is-ready", "is-overflowing");
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
detailsElements.forEach((details) => {
|
|
125
|
+
const summary = details.querySelector(".crumb-summary") as HTMLElement;
|
|
126
|
+
const wrapper = details.closest(".dropdown-wrapper") as HTMLElement;
|
|
127
|
+
const menu = details.querySelector(".dropdown-menu") as HTMLElement;
|
|
128
|
+
|
|
129
|
+
summary.addEventListener("click", (e) => {
|
|
130
|
+
e.preventDefault();
|
|
131
|
+
|
|
132
|
+
const isOpen = details.hasAttribute("open");
|
|
133
|
+
|
|
134
|
+
if (isOpen) {
|
|
135
|
+
details.removeAttribute("open");
|
|
136
|
+
wrapper.classList.remove("is-ready", "is-overflowing");
|
|
137
|
+
} else {
|
|
138
|
+
detailsElements.forEach((otherDetails) => {
|
|
139
|
+
if (
|
|
140
|
+
otherDetails !== details &&
|
|
141
|
+
otherDetails.hasAttribute("open")
|
|
142
|
+
) {
|
|
143
|
+
otherDetails.removeAttribute("open");
|
|
144
|
+
otherDetails
|
|
145
|
+
.closest(".dropdown-wrapper")
|
|
146
|
+
?.classList.remove("is-ready", "is-overflowing");
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
details.setAttribute("open", "");
|
|
151
|
+
wrapper.classList.remove("is-overflowing", "is-ready");
|
|
152
|
+
|
|
153
|
+
const rect = menu.getBoundingClientRect();
|
|
154
|
+
|
|
155
|
+
if (rect.right > window.innerWidth - 20) {
|
|
156
|
+
wrapper.classList.add("is-overflowing");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
wrapper.classList.add("is-ready");
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
window.addEventListener("resize", () => {
|
|
165
|
+
detailsElements.forEach((details) => {
|
|
166
|
+
if (details.hasAttribute("open")) {
|
|
167
|
+
const wrapper = details.closest(
|
|
168
|
+
".dropdown-wrapper",
|
|
169
|
+
) as HTMLElement;
|
|
170
|
+
const menu = details.querySelector(
|
|
171
|
+
".dropdown-menu",
|
|
172
|
+
) as HTMLElement;
|
|
173
|
+
|
|
174
|
+
wrapper.classList.remove("is-overflowing");
|
|
175
|
+
const rect = menu.getBoundingClientRect();
|
|
176
|
+
|
|
177
|
+
if (rect.right > window.innerWidth - 20) {
|
|
178
|
+
wrapper.classList.add("is-overflowing");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
</script>
|
|
184
|
+
|
|
185
|
+
<style>
|
|
186
|
+
.breadcrumb-header {
|
|
187
|
+
display: flex;
|
|
188
|
+
justify-content: space-between;
|
|
189
|
+
align-items: flex-end;
|
|
190
|
+
gap: 1rem;
|
|
191
|
+
margin-bottom: 1.5rem;
|
|
192
|
+
position: relative;
|
|
193
|
+
flex-wrap: wrap-reverse;
|
|
194
|
+
z-index: 10;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.breadcrumbs {
|
|
198
|
+
font-size: 0.85rem;
|
|
199
|
+
color: var(--sl-color-gray-3);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.read-time {
|
|
203
|
+
display: flex;
|
|
204
|
+
align-items: center;
|
|
205
|
+
gap: 0.35rem;
|
|
206
|
+
font-size: 0.8rem;
|
|
207
|
+
color: var(--sl-color-gray-2);
|
|
208
|
+
white-space: nowrap;
|
|
209
|
+
padding-top: 0.1rem;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.breadcrumbs ol {
|
|
213
|
+
list-style: none;
|
|
214
|
+
padding: 0;
|
|
215
|
+
margin: 0;
|
|
216
|
+
display: flex;
|
|
217
|
+
flex-wrap: wrap;
|
|
218
|
+
align-items: center;
|
|
219
|
+
gap: 0.5rem;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.breadcrumbs > ol > li {
|
|
223
|
+
display: flex;
|
|
224
|
+
align-items: center;
|
|
225
|
+
gap: 0.5rem;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.breadcrumbs .link,
|
|
229
|
+
.crumb-summary {
|
|
230
|
+
color: var(--sl-color-gray-3);
|
|
231
|
+
text-decoration: none;
|
|
232
|
+
transition: color 0.2s ease;
|
|
233
|
+
cursor: pointer;
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
gap: 0.25rem;
|
|
237
|
+
user-select: none;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.breadcrumbs .link:hover,
|
|
241
|
+
.breadcrumbs .link:focus,
|
|
242
|
+
.crumb-summary:hover,
|
|
243
|
+
.crumb-summary:focus {
|
|
244
|
+
color: var(--sl-color-white);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.breadcrumbs .current {
|
|
248
|
+
color: var(--sl-color-white);
|
|
249
|
+
font-weight: 800;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.breadcrumbs .separator {
|
|
253
|
+
color: var(--sl-color-gray-4);
|
|
254
|
+
user-select: none;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.breadcrumbs :global(svg) {
|
|
258
|
+
transition: transform 0.2s ease-in-out;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.crumb-summary::marker,
|
|
262
|
+
.crumb-summary::-webkit-details-marker {
|
|
263
|
+
display: none;
|
|
264
|
+
content: "";
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.crumb-summary :global(svg),
|
|
268
|
+
.breadcrumbs .end-label :global(svg) {
|
|
269
|
+
transform: rotate(-90deg);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.crumb-details[open] .crumb-summary :global(svg) {
|
|
273
|
+
transform: rotate(0deg);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.dropdown-wrapper {
|
|
277
|
+
position: relative;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.dropdown-menu {
|
|
281
|
+
position: absolute;
|
|
282
|
+
top: calc(100% + 0.5rem);
|
|
283
|
+
left: 0;
|
|
284
|
+
background-color: var(--sl-color-black);
|
|
285
|
+
border: 1px solid var(--sl-color-hairline);
|
|
286
|
+
border-radius: 0.5rem;
|
|
287
|
+
padding: 0.5rem 0.5rem 0.5rem 0rem;
|
|
288
|
+
min-width: 15rem;
|
|
289
|
+
width: max-content;
|
|
290
|
+
max-height: 50vh;
|
|
291
|
+
overflow-y: auto;
|
|
292
|
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
|
|
293
|
+
z-index: 20;
|
|
294
|
+
visibility: hidden;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.dropdown-wrapper.is-ready .dropdown-menu {
|
|
298
|
+
visibility: visible;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
.dropdown-wrapper.is-overflowing {
|
|
302
|
+
position: static;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.dropdown-wrapper.is-overflowing .dropdown-menu {
|
|
306
|
+
left: 0;
|
|
307
|
+
width: 100%;
|
|
308
|
+
max-width: 100%;
|
|
309
|
+
min-width: 0;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.dropdown-menu :global(ul) {
|
|
313
|
+
margin-top: 0 !important;
|
|
314
|
+
padding-inline-start: 0 !important;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.dropdown-menu :global(.top-level > li) {
|
|
318
|
+
margin-inline-start: 0 !important;
|
|
319
|
+
}
|
|
320
|
+
.dropdown-menu :global(li) {
|
|
321
|
+
margin-top: 0rem !important;
|
|
322
|
+
margin-inline-start: calc(
|
|
323
|
+
var(--sl-sidebar-item-padding-inline) + (1rem / 2)
|
|
324
|
+
) !important;
|
|
325
|
+
display: block !important;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.dropdown-menu :global(a) {
|
|
329
|
+
font-weight: normal !important;
|
|
330
|
+
font-size: 0.9rem !important;
|
|
331
|
+
padding: 0.2rem 0.5rem !important;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
.dropdown-menu :global(details) {
|
|
335
|
+
margin-top: 0 !important;
|
|
336
|
+
}
|
|
337
|
+
.dropdown-menu :global(summary) {
|
|
338
|
+
font-weight: normal !important;
|
|
339
|
+
padding: 0.2rem 0.5rem !important;
|
|
340
|
+
}
|
|
341
|
+
</style>
|
package/overrides/Search.astro
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import DefaultSearch from '@astrojs/starlight/components/Search.astro';
|
|
3
3
|
|
|
4
4
|
import getThemeConfig from "../internal/themeConfig";
|
|
5
|
-
const { documentationSearchTag } = getThemeConfig();
|
|
5
|
+
const { documentationSearchTag, tagManagerId } = getThemeConfig();
|
|
6
6
|
const isDev = import.meta.env.DEV;
|
|
7
|
+
const baseUrl = import.meta.env.BASE_URL === '/' ? '' : import.meta.env.BASE_URL;
|
|
8
|
+
|
|
7
9
|
---
|
|
8
10
|
|
|
9
11
|
<DefaultSearch {...Astro.props} />
|
|
@@ -93,7 +95,7 @@ const isDev = import.meta.env.DEV;
|
|
|
93
95
|
</style>
|
|
94
96
|
|
|
95
97
|
{!isDev &&
|
|
96
|
-
<script is:inline define:vars={{documentationSearchTag}}>
|
|
98
|
+
<script is:inline define:vars={{documentationSearchTag, baseUrl, tagManagerId}}>
|
|
97
99
|
const badgesConfig = {
|
|
98
100
|
"frontend-tools.coherent-labs.com/e2e": { text: "UI Tools | Gameface E2E", color: "#007aaa" },
|
|
99
101
|
"frontend-tools.coherent-labs.com/interaction-manager": { text: "UI Tools | Interaction Manager", color: "#007abb" },
|
|
@@ -102,6 +104,8 @@ const isDev = import.meta.env.DEV;
|
|
|
102
104
|
"frontend-tools.coherent-labs.com/data-binding-autocomplete": { text: "UI Tools | Data Binding Autocomplete", color: "#007aee" },
|
|
103
105
|
"frontend-tools.coherent-labs.com": { text: "UI Tools", color: "#007aff" },
|
|
104
106
|
"gameface-ui.coherent-labs.com": { text: "Gameface UI", color: "#e24a4a" },
|
|
107
|
+
"docs.coherent-labs.com/unreal-gameface": { text: "Gameface Unreal", color: "#C35A1C" },
|
|
108
|
+
"docs.coherent-labs.com/unreal-prysm": { text: "Prysm Unreal", color: "#00897B" },
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
function setupSearchInputListener(searchInput, pagefind) {
|
|
@@ -199,8 +203,29 @@ const isDev = import.meta.env.DEV;
|
|
|
199
203
|
const searchContainer = document.getElementById("starlight__search");
|
|
200
204
|
if (!searchContainer) return;
|
|
201
205
|
|
|
206
|
+
if (tagManagerId) {
|
|
207
|
+
searchContainer.addEventListener("click", (event) => {
|
|
208
|
+
const searchResult = event.target?.closest(".pagefind-ui__result");
|
|
209
|
+
if (!searchResult) return;
|
|
210
|
+
|
|
211
|
+
const searchInput = searchContainer.querySelector(".pagefind-ui__search-input");
|
|
212
|
+
const searchTerm = searchInput ? searchInput.value : "";
|
|
213
|
+
|
|
214
|
+
const titleElement = searchResult.querySelector(".pagefind-ui__result-title a") || searchResult.querySelector(".pagefind-ui__result-link");
|
|
215
|
+
const clickedTitle = titleElement ? titleElement.textContent.trim() : "";
|
|
216
|
+
const clickedUrl = titleElement ? titleElement.href : "";
|
|
217
|
+
window.dataLayer = window.dataLayer || [];
|
|
218
|
+
window.dataLayer.push({
|
|
219
|
+
event: "liveSearch",
|
|
220
|
+
searchTerm: searchTerm,
|
|
221
|
+
clickedResult: clickedTitle,
|
|
222
|
+
clickedUrl: clickedUrl
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
202
227
|
try {
|
|
203
|
-
const pagefind = await import(
|
|
228
|
+
const pagefind = await import(`${baseUrl}/pagefind/pagefind.js`);
|
|
204
229
|
window.__pagefindTrueCounts = {};
|
|
205
230
|
|
|
206
231
|
let frameRequested = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coherent-docs-theme",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Theme for all the coherent documentations",
|
|
6
6
|
"author": "CoherentLabs",
|
|
@@ -11,21 +11,24 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": "./index.ts",
|
|
13
13
|
"./styles": "./styles.css",
|
|
14
|
+
"./components": "./components/index.ts",
|
|
14
15
|
"./components/*.astro": "./components/*.astro",
|
|
15
16
|
"./overrides/*.astro": "./overrides/*.astro",
|
|
16
17
|
"./assets/*": "./assets/*"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@astrojs/starlight": "0.37.6",
|
|
20
|
-
"astro": "5.17.1",
|
|
21
21
|
"@types/mdast": "^4.0.4",
|
|
22
|
-
"@types/unist": "^3.0.3"
|
|
22
|
+
"@types/unist": "^3.0.3",
|
|
23
|
+
"astro": "5.17.1"
|
|
23
24
|
},
|
|
24
25
|
"dependencies": {
|
|
26
|
+
"gray-matter": "^4.0.3",
|
|
27
|
+
"reading-time": "^1.5.0",
|
|
25
28
|
"starlight-heading-badges": "0.6.1",
|
|
26
29
|
"starlight-sidebar-topics": "0.6.2",
|
|
27
30
|
"starlight-sidebar-topics-dropdown": "0.5.2",
|
|
28
|
-
"
|
|
31
|
+
"vanilla-cookieconsent": "^3.1.0"
|
|
29
32
|
},
|
|
30
33
|
"peerDependencies": {
|
|
31
34
|
"@astrojs/starlight": ">=0.37.6",
|
|
@@ -46,4 +49,4 @@
|
|
|
46
49
|
"url": "https://github.com/CoherentLabs/frontend-tools/coherent-docs-theme.git",
|
|
47
50
|
"directory": "packages/coherent-docs-theme"
|
|
48
51
|
}
|
|
49
|
-
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import type { Root } from 'mdast';
|
|
3
|
+
|
|
4
|
+
export function remarkFixDoxybookLinks() {
|
|
5
|
+
return (tree: Root, file: any) => {
|
|
6
|
+
if (!file?.history?.[0].includes('API_reference')) return;
|
|
7
|
+
|
|
8
|
+
visit(tree, 'link', (node: any) => {
|
|
9
|
+
if (node.url && node.url.includes('#')) {
|
|
10
|
+
let [base, hash] = node.url.split('#');
|
|
11
|
+
|
|
12
|
+
const linkText = node.children
|
|
13
|
+
.map((c: any) => c.value || '')
|
|
14
|
+
.join('');
|
|
15
|
+
|
|
16
|
+
if (linkText) {
|
|
17
|
+
const wordsWithUnderscores = linkText.match(/[a-zA-Z0-9_]*_[a-zA-Z0-9_]*/g) || [];
|
|
18
|
+
const uniqueWords = [...new Set(wordsWithUnderscores)];
|
|
19
|
+
|
|
20
|
+
//@ts-ignore
|
|
21
|
+
uniqueWords.forEach((word: string) => {
|
|
22
|
+
const correctStr = word.toLowerCase();
|
|
23
|
+
const brokenStr = correctStr.replace(/_/g, '-');
|
|
24
|
+
hash = hash.split(brokenStr).join(correctStr);
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
hash = hash.replace(/~/g, '')
|
|
29
|
+
.replace(/\(\)/g, '')
|
|
30
|
+
.replace(/=/g, '')
|
|
31
|
+
.replace(/</g, '')
|
|
32
|
+
.replace(/>/g, '')
|
|
33
|
+
.replace(/@/g, '')
|
|
34
|
+
.replace(/-+/g, '-')
|
|
35
|
+
node.url = base ? `${base}#${hash}` : `#${hash}`;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import type { Root } from 'mdast';
|
|
3
|
+
|
|
4
|
+
function processUrl(base: string, url: string) {
|
|
5
|
+
if (!url || !url.startsWith('/') || url.startsWith('//')) return url;
|
|
6
|
+
|
|
7
|
+
let newUrl = url;
|
|
8
|
+
|
|
9
|
+
if (!newUrl.startsWith(base + '/')) {
|
|
10
|
+
newUrl = `${base}${newUrl}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const [pathPart, hashPart] = newUrl.split('#');
|
|
14
|
+
//@ts-ignore
|
|
15
|
+
const hasExtension = /\.[a-zA-Z0-9]+$/.test(pathPart);
|
|
16
|
+
|
|
17
|
+
//@ts-ignore
|
|
18
|
+
if (!hasExtension && !pathPart.endsWith('/')) {
|
|
19
|
+
newUrl = `${pathPart}/` + (hashPart !== undefined ? `#${hashPart}` : '');
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return newUrl;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function remarkFixAbsoluteLinks(options: { basePath: string }) {
|
|
26
|
+
return (tree: Root) => {
|
|
27
|
+
if (!options || !options.basePath || options.basePath === '/') return;
|
|
28
|
+
const base = options.basePath.replace(/\/$/, '');
|
|
29
|
+
|
|
30
|
+
visit(tree, ['link', 'image'], (node: any) => {
|
|
31
|
+
node.url = processUrl(base, node.url);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
visit(tree, 'html', (node: any) => {
|
|
35
|
+
if (node.value) {
|
|
36
|
+
node.value = node.value.replace(/(src|href)="(\/[^"]+)"/g, (_: string, attr: string, p1: string) => {
|
|
37
|
+
return `${attr}="${processUrl(base, p1)}"`;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node: any) => {
|
|
43
|
+
if (node.name === 'NativeLink') return;
|
|
44
|
+
|
|
45
|
+
if (node.attributes) {
|
|
46
|
+
for (const attr of node.attributes) {
|
|
47
|
+
if ((attr.name === 'src' || attr.name === 'href') && typeof attr.value === 'string') {
|
|
48
|
+
attr.value = processUrl(base, attr.value);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
}
|
|
@@ -3,11 +3,15 @@ import { remarkIfDirective } from "./if";
|
|
|
3
3
|
import { remarkIncludeSnippets } from "./includeSnippets";
|
|
4
4
|
import { remarkReleaseDirective } from './release';
|
|
5
5
|
import { remarkInternalDirective } from './internal';
|
|
6
|
+
import { remarkProductNameDirective } from './productName';
|
|
7
|
+
import { remarkFixDoxybookLinks } from './apiRefFixLinks';
|
|
6
8
|
|
|
7
9
|
export const directives = [
|
|
8
10
|
remarkDirective,
|
|
9
11
|
remarkIfDirective,
|
|
10
12
|
remarkInternalDirective,
|
|
11
13
|
remarkReleaseDirective,
|
|
12
|
-
remarkIncludeSnippets
|
|
14
|
+
remarkIncludeSnippets,
|
|
15
|
+
remarkProductNameDirective,
|
|
16
|
+
remarkFixDoxybookLinks
|
|
13
17
|
];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { visit } from 'unist-util-visit';
|
|
2
|
+
import type { Root } from 'mdast';
|
|
3
|
+
|
|
4
|
+
const currentProduct = process.env.DOCS_PRODUCT || 'Gameface';
|
|
5
|
+
let productName = currentProduct;
|
|
6
|
+
if (currentProduct) productName = currentProduct.charAt(0).toUpperCase() + currentProduct.slice(1);
|
|
7
|
+
|
|
8
|
+
const productNameRegex = /<ProductName\s*\/?>|<ProductName>\s*<\/ProductName>/g;
|
|
9
|
+
|
|
10
|
+
export function remarkProductNameDirective() {
|
|
11
|
+
return (tree: Root) => {
|
|
12
|
+
|
|
13
|
+
visit(tree, ['mdxJsxFlowElement', 'mdxJsxTextElement'], (node: any, index, parent) => {
|
|
14
|
+
if (node.name === 'ProductName' && parent && index !== undefined) {
|
|
15
|
+
parent.children.splice(index, 1, {
|
|
16
|
+
type: 'text',
|
|
17
|
+
value: productName
|
|
18
|
+
});
|
|
19
|
+
return index;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
visit(tree, ['text', 'inlineCode', 'code', 'html'], (node: any) => {
|
|
24
|
+
if (typeof node.value === 'string') {
|
|
25
|
+
node.value = node.value.replace(productNameRegex, productName);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
}
|
package/styles.css
CHANGED