-
Notifications
You must be signed in to change notification settings - Fork 488
/
utils.ts
138 lines (118 loc) · 3.5 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import { IEX_DOMAIN } from "./env";
import { Theme } from "./types/theme";
import { User } from "./user-context";
const HOMEPAGE_RE = /^\/[A-Za-z-]*\/?(?:_homepage)?$/i;
const DOCS_RE = /^\/[A-Za-z-]+\/docs\/.*$/i;
const PLUS_RE = /^\/[A-Za-z-]*\/?plus(?:\/?.*)$/i;
const CATEGORIES = ["html", "javascript", "css", "api", "http"];
export function getCategoryByPathname(pathname = ""): string | null {
const [, , , webOrLearn, category] = pathname.toLowerCase().split("/");
if (webOrLearn === "learn" || webOrLearn === "web") {
if (CATEGORIES.includes(category)) {
return category;
}
return webOrLearn;
}
if (isHomePage(pathname)) {
return "home";
}
return null;
}
export function isDocs(pathname: string): boolean {
return Boolean(pathname.match(DOCS_RE));
}
export function isPlus(pathname: string): boolean {
return Boolean(pathname.match(PLUS_RE));
}
export function isHomePage(pathname: string): boolean {
return Boolean(pathname.match(HOMEPAGE_RE));
}
/**
* Posts the name of the theme we are changing to the
* interactive examples `iframe`.
* @param { Theme } theme - The theme to switch to
*/
export function postToIEx(theme: Theme) {
const iexFrame = document.querySelector(".interactive") as HTMLIFrameElement;
if (iexFrame) {
if (iexFrame.getAttribute("data-readystate") === "complete") {
const origin =
window?.mdnWorker?.settings?.preferOnline === false
? window.location.origin
: IEX_DOMAIN;
iexFrame.contentWindow?.postMessage({ theme: theme }, origin);
}
}
}
export function switchTheme(theme: Theme, set: (theme: Theme) => void) {
const html = document.documentElement;
if (window && html) {
html.className = theme;
html.style.backgroundColor = "";
setTimeout(() => {
const meta = document.querySelector<HTMLMetaElement>(
'meta[name="theme-color"]'
);
const color = getComputedStyle(document.body).backgroundColor;
if (meta && color) {
meta.content = color;
}
}, 1);
try {
window.localStorage.setItem("theme", theme);
} catch (err) {
console.warn("Unable to write theme to localStorage", err);
}
set(theme);
postToIEx(theme);
}
}
export function isPlusSubscriber(user): user is User {
if (
user?.isSubscriber &&
user?.subscriptionType &&
user?.subscriptionType.includes("plus")
) {
return true;
}
return false;
}
/**
* Makes camelCase strings wrap nicely
*/
export function camelWrap(text: string) {
return text.replace(/([^A-Z])([A-Z])/g, "$1\u200B$2");
}
export function camelUnwrap(text: string) {
return text.replace(/[\u200B]/g, "");
}
/**
* Gets the number of characters in a string.
* String.length returns the number of code units.
*/
export function charLength(string: string) {
return [...string].length;
}
/**
* Slices by characters in a string.
* String.slice slices by code units.
*/
export function charSlice(string: string, start?: number, end?: number) {
return [...string].slice(start, end).join("");
}
export function range(start: number, stop: number) {
return [...Array(Math.max(stop - start, 0)).keys()].map((n) => n + start);
}
/**
* Used by quicksearch and sidebar filters.
*/
export function splitQuery(term: string): string[] {
term = term.trim().toLowerCase();
if (term.startsWith(".") || term.endsWith(".")) {
// Dot is probably meaningful.
return term.split(/[ ,]+/);
} else {
// Dot is probably just a word separator.
return term.split(/[ ,.]+/);
}
}