react-client-seo 1.0.0 → 1.1.1
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/README.md +165 -64
- package/dist/Seo.d.ts +1 -1
- package/dist/Seo.d.ts.map +1 -1
- package/dist/index.cjs +12 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +238 -114
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/useSeo.d.ts.map +1 -1
- package/dist/utils.d.ts +17 -1
- package/dist/utils.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,189 +1,313 @@
|
|
|
1
|
-
import { useEffect as
|
|
2
|
-
function
|
|
1
|
+
import { useEffect as pe, useCallback as te } from "react";
|
|
2
|
+
function k(e, t) {
|
|
3
3
|
const i = `meta[${e}="${t}"]`;
|
|
4
|
-
let
|
|
5
|
-
return
|
|
4
|
+
let r = document.querySelector(i);
|
|
5
|
+
return r || (r = document.createElement("meta"), r.setAttribute(e, t), document.head.appendChild(r)), r;
|
|
6
6
|
}
|
|
7
|
-
function
|
|
7
|
+
function n(e, t) {
|
|
8
8
|
if (!t) return;
|
|
9
|
-
|
|
9
|
+
k("name", e).setAttribute("content", t);
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function l(e, t) {
|
|
12
12
|
if (t == null || t === "") return;
|
|
13
|
-
|
|
13
|
+
k("property", e).setAttribute("content", String(t));
|
|
14
14
|
}
|
|
15
|
-
function
|
|
15
|
+
function ne(e) {
|
|
16
16
|
e && (document.title = e);
|
|
17
17
|
}
|
|
18
|
-
function
|
|
18
|
+
function re(e) {
|
|
19
19
|
if (!e) return;
|
|
20
20
|
let t = document.querySelector('link[rel="canonical"]');
|
|
21
21
|
t || (t = document.createElement("link"), t.setAttribute("rel", "canonical"), document.head.appendChild(t)), t.setAttribute("href", e);
|
|
22
22
|
}
|
|
23
|
-
function
|
|
23
|
+
function ge() {
|
|
24
24
|
const e = document.querySelector('link[rel="canonical"]');
|
|
25
25
|
e && e.remove();
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
e && (e.title &&
|
|
27
|
+
function ae(e) {
|
|
28
|
+
e && (e.title && l("og:title", e.title), e.description && l("og:description", e.description), e.type && l("og:type", e.type), e.url && l("og:url", e.url), e.image && l("og:image", e.image), e.imageWidth && l("og:image:width", e.imageWidth), e.imageHeight && l("og:image:height", e.imageHeight), e.imageAlt && l("og:image:alt", e.imageAlt), e.siteName && l("og:site_name", e.siteName), e.locale && l("og:locale", e.locale), Object.keys(e).forEach((t) => {
|
|
29
29
|
if (t.startsWith("og:") && t !== "og:title" && t !== "og:description" && t !== "og:type" && t !== "og:url" && t !== "og:image" && t !== "og:imageWidth" && t !== "og:imageHeight" && t !== "og:imageAlt" && t !== "og:siteName" && t !== "og:locale") {
|
|
30
30
|
const i = e[t];
|
|
31
|
-
i != null && i !== "" &&
|
|
31
|
+
i != null && i !== "" && l(t, i);
|
|
32
32
|
}
|
|
33
33
|
}));
|
|
34
34
|
}
|
|
35
|
-
function
|
|
36
|
-
e && (e.card &&
|
|
35
|
+
function ce(e) {
|
|
36
|
+
e && (e.card && n("twitter:card", e.card), e.site && n("twitter:site", e.site), e.creator && n("twitter:creator", e.creator), e.title && n("twitter:title", e.title), e.description && n("twitter:description", e.description), e.image && n("twitter:image", e.image), e.imageAlt && n("twitter:image:alt", e.imageAlt), Object.keys(e).forEach((t) => {
|
|
37
37
|
if (t.startsWith("twitter:") && t !== "twitter:card" && t !== "twitter:site" && t !== "twitter:creator" && t !== "twitter:title" && t !== "twitter:description" && t !== "twitter:image" && t !== "twitter:imageAlt") {
|
|
38
38
|
const i = e[t];
|
|
39
|
-
i != null && i !== "" &&
|
|
39
|
+
i != null && i !== "" && n(t, String(i));
|
|
40
40
|
}
|
|
41
41
|
}));
|
|
42
42
|
}
|
|
43
|
-
function
|
|
43
|
+
function oe(e) {
|
|
44
44
|
!e || !Array.isArray(e) || e.forEach((t) => {
|
|
45
45
|
if (!t.content) return;
|
|
46
46
|
let i = null;
|
|
47
47
|
if (t.name)
|
|
48
|
-
i =
|
|
48
|
+
i = k("name", t.name);
|
|
49
49
|
else if (t.property)
|
|
50
|
-
i =
|
|
50
|
+
i = k("property", t.property);
|
|
51
51
|
else if (t.httpEquiv) {
|
|
52
|
-
const
|
|
53
|
-
i = document.querySelector(
|
|
52
|
+
const r = `meta[http-equiv="${t.httpEquiv}"]`;
|
|
53
|
+
i = document.querySelector(r), i || (i = document.createElement("meta"), i.setAttribute("http-equiv", t.httpEquiv), document.head.appendChild(i));
|
|
54
54
|
} else if (t.charset) {
|
|
55
|
-
let
|
|
56
|
-
|
|
55
|
+
let r = document.querySelector("meta[charset]");
|
|
56
|
+
r || (r = document.createElement("meta"), r.setAttribute("charset", t.charset), document.head.insertBefore(r, document.head.firstChild));
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
59
|
i && i.setAttribute("content", t.content);
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
|
-
function
|
|
62
|
+
function fe(e, t) {
|
|
63
63
|
const i = document.createElement("script");
|
|
64
64
|
i.type = "application/ld+json";
|
|
65
65
|
{
|
|
66
66
|
i.id = t;
|
|
67
|
-
const
|
|
68
|
-
|
|
67
|
+
const r = document.getElementById(t);
|
|
68
|
+
r && r.remove();
|
|
69
69
|
}
|
|
70
70
|
return i.textContent = JSON.stringify(e), document.head.appendChild(i), () => {
|
|
71
71
|
i.remove();
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
|
-
function
|
|
74
|
+
function he(e) {
|
|
75
75
|
const t = document.getElementById(e);
|
|
76
76
|
t && t.getAttribute("type") === "application/ld+json" && t.remove();
|
|
77
77
|
}
|
|
78
|
-
function
|
|
78
|
+
function se(e) {
|
|
79
79
|
return e ? Array.isArray(e) ? e.join(", ") : e : "";
|
|
80
80
|
}
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
function y(e) {
|
|
82
|
+
const t = document.getElementById(e);
|
|
83
|
+
t && t.tagName === "SCRIPT" && t.remove();
|
|
84
|
+
}
|
|
85
|
+
function le(e) {
|
|
86
|
+
const t = "react-client-seo-ga", i = "react-client-seo-ga-config";
|
|
87
|
+
y(t), y(i);
|
|
88
|
+
const r = document.createElement("script");
|
|
89
|
+
r.id = t, r.async = !0, r.src = `https://www.googletagmanager.com/gtag/js?id=${e}`, document.head.appendChild(r);
|
|
90
|
+
const a = document.createElement("script");
|
|
91
|
+
return a.id = i, a.textContent = `
|
|
92
|
+
window.dataLayer = window.dataLayer || [];
|
|
93
|
+
function gtag(){dataLayer.push(arguments);}
|
|
94
|
+
gtag('js', new Date());
|
|
95
|
+
gtag('config', '${e}');
|
|
96
|
+
`, document.head.appendChild(a), () => {
|
|
97
|
+
y(t), y(i);
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function de(e) {
|
|
101
|
+
const t = "react-client-seo-gtm", i = "react-client-seo-gtm-noscript";
|
|
102
|
+
y(t);
|
|
103
|
+
const r = document.getElementById(i);
|
|
104
|
+
r && r.remove();
|
|
105
|
+
const a = document.createElement("script");
|
|
106
|
+
a.id = t, a.textContent = `
|
|
107
|
+
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
|
108
|
+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
|
109
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|
110
|
+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
|
111
|
+
})(window,document,'script','dataLayer','${e}');
|
|
112
|
+
`, document.head.appendChild(a);
|
|
113
|
+
const d = document.createElement("noscript");
|
|
114
|
+
return d.id = i, d.innerHTML = `<iframe src="https://www.googletagmanager.com/ns.html?id=${e}" height="0" width="0" style="display:none;visibility:hidden"></iframe>`, document.head.appendChild(d), () => {
|
|
115
|
+
y(t);
|
|
116
|
+
const u = document.getElementById(i);
|
|
117
|
+
u && u.remove();
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function ue(e) {
|
|
121
|
+
if (!e.src && !e.content)
|
|
122
|
+
return console.warn("CustomScript must have either src or content"), () => {
|
|
123
|
+
};
|
|
124
|
+
const t = e.id || `react-client-seo-custom-${Date.now()}`;
|
|
125
|
+
e.id && y(e.id);
|
|
126
|
+
const i = document.createElement("script");
|
|
127
|
+
return i.id = t, e.src && (i.src = e.src), e.content && (i.textContent = e.content), e.type ? i.type = e.type : i.type = "text/javascript", (e.strategy === "async" || e.async) && (i.async = !0), (e.strategy === "defer" || e.defer) && (i.defer = !0), document.head.appendChild(i), () => {
|
|
128
|
+
y(t);
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
const ye = "react-client-seo-jsonld";
|
|
132
|
+
function we({
|
|
83
133
|
title: e,
|
|
84
134
|
description: t,
|
|
85
135
|
keywords: i,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
136
|
+
author: r,
|
|
137
|
+
robots: a,
|
|
138
|
+
language: d,
|
|
139
|
+
viewport: u,
|
|
140
|
+
generator: w,
|
|
141
|
+
revisitAfter: E,
|
|
142
|
+
rating: v,
|
|
143
|
+
distribution: A,
|
|
144
|
+
copyright: b,
|
|
145
|
+
themeColor: j,
|
|
146
|
+
referrer: S,
|
|
147
|
+
formatDetection: T,
|
|
148
|
+
mobileWebAppCapable: N,
|
|
149
|
+
appleMobileWebAppCapable: O,
|
|
150
|
+
geoRegion: _,
|
|
151
|
+
geoPlacename: D,
|
|
152
|
+
geoPosition: I,
|
|
153
|
+
icbm: C,
|
|
154
|
+
canonical: m,
|
|
155
|
+
ogImage: p,
|
|
156
|
+
ogType: q,
|
|
157
|
+
ogUrl: g,
|
|
158
|
+
ogTitle: h,
|
|
159
|
+
ogDescription: B,
|
|
160
|
+
ogSiteName: G,
|
|
161
|
+
ogLocale: L,
|
|
162
|
+
twitterCard: $,
|
|
163
|
+
twitterSite: x,
|
|
164
|
+
twitterCreator: J,
|
|
165
|
+
twitterTitle: M,
|
|
166
|
+
twitterDescription: H,
|
|
167
|
+
twitterImage: P,
|
|
168
|
+
twitterImageAlt: R,
|
|
169
|
+
jsonLd: W,
|
|
170
|
+
customMeta: F,
|
|
171
|
+
openGraph: V,
|
|
172
|
+
twitter: X,
|
|
173
|
+
googleAnalyticsId: K,
|
|
174
|
+
googleTagManagerId: Y,
|
|
175
|
+
customScripts: z
|
|
105
176
|
}) {
|
|
106
|
-
return
|
|
107
|
-
e &&
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
const
|
|
111
|
-
...
|
|
177
|
+
return pe(() => {
|
|
178
|
+
e && ne(e), t && n("description", t);
|
|
179
|
+
const Z = se(i);
|
|
180
|
+
Z && n("keywords", Z), r && n("author", r), a && n("robots", a), d && (n("language", d), n("content-language", d)), u && n("viewport", u), w && n("generator", w), E && n("revisit-after", E), v && n("rating", v), A && n("distribution", A), b && n("copyright", b), j && n("theme-color", j), S && n("referrer", S), T && n("format-detection", T), N && n("mobile-web-app-capable", N), O && n("apple-mobile-web-app-capable", O), _ && n("geo.region", _), D && n("geo.placename", D), I && n("geo.position", I), C && n("ICBM", C), m && re(m);
|
|
181
|
+
const s = {
|
|
182
|
+
...V
|
|
112
183
|
};
|
|
113
|
-
(
|
|
114
|
-
const
|
|
115
|
-
...
|
|
184
|
+
(h || e) && (s.title = h || e), (B || t) && (s.description = B || t), q && (s.type = q), (g || m) && (s.url = g || m), p && (s.image = p), G && (s.siteName = G), L && (s.locale = L), Object.keys(s).length > 0 && ae(s);
|
|
185
|
+
const c = {
|
|
186
|
+
...X
|
|
116
187
|
};
|
|
117
|
-
|
|
118
|
-
let
|
|
119
|
-
|
|
120
|
-
|
|
188
|
+
$ && (c.card = $), x && (c.site = x), J && (c.creator = J), (M || e) && (c.title = M || e), (H || t) && (c.description = H || t), (P || p) && (c.image = P || p), R && (c.imageAlt = R), Object.keys(c).length > 0 && ce(c), F && oe(F);
|
|
189
|
+
let Q = null;
|
|
190
|
+
W && (Q = fe(W, ye));
|
|
191
|
+
let o = null;
|
|
192
|
+
K && (o = le(K));
|
|
193
|
+
let f = null;
|
|
194
|
+
Y && (f = de(Y));
|
|
195
|
+
const U = [];
|
|
196
|
+
return z && Array.isArray(z) && z.forEach((ee) => {
|
|
197
|
+
const me = ue(ee);
|
|
198
|
+
U.push(me);
|
|
199
|
+
}), () => {
|
|
200
|
+
Q && Q(), o && o(), f && f(), U.forEach((ee) => ee());
|
|
121
201
|
};
|
|
122
202
|
}, [
|
|
123
203
|
e,
|
|
124
204
|
t,
|
|
125
205
|
i,
|
|
126
|
-
n,
|
|
127
206
|
r,
|
|
128
|
-
|
|
129
|
-
u,
|
|
130
|
-
m,
|
|
207
|
+
a,
|
|
131
208
|
d,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
209
|
+
u,
|
|
210
|
+
w,
|
|
211
|
+
E,
|
|
212
|
+
v,
|
|
135
213
|
A,
|
|
136
214
|
b,
|
|
137
|
-
v,
|
|
138
|
-
E,
|
|
139
|
-
S,
|
|
140
215
|
j,
|
|
141
|
-
|
|
142
|
-
|
|
216
|
+
S,
|
|
217
|
+
T,
|
|
143
218
|
N,
|
|
144
|
-
|
|
219
|
+
O,
|
|
220
|
+
_,
|
|
221
|
+
D,
|
|
222
|
+
I,
|
|
223
|
+
C,
|
|
224
|
+
m,
|
|
225
|
+
p,
|
|
226
|
+
q,
|
|
227
|
+
g,
|
|
228
|
+
h,
|
|
229
|
+
B,
|
|
230
|
+
G,
|
|
231
|
+
L,
|
|
232
|
+
$,
|
|
233
|
+
x,
|
|
234
|
+
J,
|
|
235
|
+
M,
|
|
236
|
+
H,
|
|
237
|
+
P,
|
|
238
|
+
R,
|
|
239
|
+
W,
|
|
240
|
+
F,
|
|
241
|
+
V,
|
|
242
|
+
X,
|
|
243
|
+
K,
|
|
244
|
+
Y,
|
|
245
|
+
z
|
|
145
246
|
]), null;
|
|
146
247
|
}
|
|
147
|
-
const
|
|
148
|
-
function
|
|
149
|
-
const e =
|
|
248
|
+
const ie = "react-client-seo-jsonld";
|
|
249
|
+
function ve() {
|
|
250
|
+
const e = te((i) => {
|
|
150
251
|
const {
|
|
151
|
-
title:
|
|
152
|
-
description:
|
|
153
|
-
keywords:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
252
|
+
title: r,
|
|
253
|
+
description: a,
|
|
254
|
+
keywords: d,
|
|
255
|
+
author: u,
|
|
256
|
+
robots: w,
|
|
257
|
+
language: E,
|
|
258
|
+
viewport: v,
|
|
259
|
+
generator: A,
|
|
260
|
+
revisitAfter: b,
|
|
261
|
+
rating: j,
|
|
262
|
+
distribution: S,
|
|
263
|
+
copyright: T,
|
|
264
|
+
themeColor: N,
|
|
265
|
+
referrer: O,
|
|
266
|
+
formatDetection: _,
|
|
267
|
+
mobileWebAppCapable: D,
|
|
268
|
+
appleMobileWebAppCapable: I,
|
|
269
|
+
geoRegion: C,
|
|
270
|
+
geoPlacename: m,
|
|
271
|
+
geoPosition: p,
|
|
272
|
+
icbm: q,
|
|
273
|
+
canonical: g,
|
|
274
|
+
ogImage: h,
|
|
275
|
+
ogType: B,
|
|
276
|
+
ogUrl: G,
|
|
277
|
+
ogTitle: L,
|
|
278
|
+
ogDescription: $,
|
|
279
|
+
ogSiteName: x,
|
|
280
|
+
ogLocale: J,
|
|
281
|
+
twitterCard: M,
|
|
282
|
+
twitterSite: H,
|
|
283
|
+
twitterCreator: P,
|
|
284
|
+
twitterTitle: R,
|
|
285
|
+
twitterDescription: W,
|
|
286
|
+
twitterImage: F,
|
|
287
|
+
twitterImageAlt: V,
|
|
288
|
+
jsonLd: X,
|
|
289
|
+
customMeta: K,
|
|
290
|
+
openGraph: Y,
|
|
291
|
+
twitter: z,
|
|
292
|
+
googleAnalyticsId: Z,
|
|
293
|
+
googleTagManagerId: s,
|
|
294
|
+
customScripts: c
|
|
173
295
|
} = i;
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
const
|
|
178
|
-
...
|
|
296
|
+
r && ne(r), a && n("description", a);
|
|
297
|
+
const Q = se(d);
|
|
298
|
+
Q && n("keywords", Q), u && n("author", u), w && n("robots", w), E && (n("language", E), n("content-language", E)), v && n("viewport", v), A && n("generator", A), b && n("revisit-after", b), j && n("rating", j), S && n("distribution", S), T && n("copyright", T), N && n("theme-color", N), O && n("referrer", O), _ && n("format-detection", _), D && n("mobile-web-app-capable", D), I && n("apple-mobile-web-app-capable", I), C && n("geo.region", C), m && n("geo.placename", m), p && n("geo.position", p), q && n("ICBM", q), g && re(g);
|
|
299
|
+
const o = {
|
|
300
|
+
...Y
|
|
179
301
|
};
|
|
180
|
-
(
|
|
181
|
-
const
|
|
182
|
-
...
|
|
302
|
+
(L || r) && (o.title = L || r), ($ || a) && (o.description = $ || a), B && (o.type = B), (G || g) && (o.url = G || g), h && (o.image = h), x && (o.siteName = x), J && (o.locale = J), Object.keys(o).length > 0 && ae(o);
|
|
303
|
+
const f = {
|
|
304
|
+
...z
|
|
183
305
|
};
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
306
|
+
M && (f.card = M), H && (f.site = H), P && (f.creator = P), (R || r) && (f.title = R || r), (W || a) && (f.description = W || a), (F || h) && (f.image = F || h), V && (f.imageAlt = V), Object.keys(f).length > 0 && ce(f), K && oe(K), X && fe(X, ie), Z && le(Z), s && de(s), c && Array.isArray(c) && c.forEach((U) => {
|
|
307
|
+
ue(U);
|
|
308
|
+
});
|
|
309
|
+
}, []), t = te(() => {
|
|
310
|
+
ge(), he(ie);
|
|
187
311
|
}, []);
|
|
188
312
|
return {
|
|
189
313
|
updateSeo: e,
|
|
@@ -191,7 +315,7 @@ function V() {
|
|
|
191
315
|
};
|
|
192
316
|
}
|
|
193
317
|
export {
|
|
194
|
-
|
|
195
|
-
|
|
318
|
+
we as Seo,
|
|
319
|
+
ve as useSeo
|
|
196
320
|
};
|
|
197
321
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/utils.ts","../src/Seo.tsx","../src/useSeo.ts"],"sourcesContent":["import type { CustomMeta, JsonLd, OpenGraphMeta, TwitterCardMeta } from './types';\r\n\r\n/**\r\n * Get or create a meta tag element\r\n */\r\nfunction getOrCreateMetaTag(attribute: 'name' | 'property', value: string): HTMLMetaElement {\r\n const selector = `meta[${attribute}=\"${value}\"]`;\r\n let element = document.querySelector<HTMLMetaElement>(selector);\r\n\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute(attribute, value);\r\n document.head.appendChild(element);\r\n }\r\n\r\n return element;\r\n}\r\n\r\n/**\r\n * Set a meta tag by name\r\n */\r\nexport function setMetaTag(name: string, content: string): void {\r\n if (!content) return;\r\n\r\n const element = getOrCreateMetaTag('name', name);\r\n element.setAttribute('content', content);\r\n}\r\n\r\n/**\r\n * Set a meta tag by property (for Open Graph)\r\n */\r\nexport function setMetaProperty(property: string, content: string | number): void {\r\n if (content === undefined || content === null || content === '') return;\r\n\r\n const element = getOrCreateMetaTag('property', property);\r\n element.setAttribute('content', String(content));\r\n}\r\n\r\n/**\r\n * Set the page title\r\n */\r\nexport function setTitle(title: string): void {\r\n if (!title) return;\r\n document.title = title;\r\n}\r\n\r\n/**\r\n * Set canonical URL\r\n */\r\nexport function setCanonical(url: string): void {\r\n if (!url) return;\r\n\r\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (!link) {\r\n link = document.createElement('link');\r\n link.setAttribute('rel', 'canonical');\r\n document.head.appendChild(link);\r\n }\r\n link.setAttribute('href', url);\r\n}\r\n\r\n/**\r\n * Remove canonical URL\r\n */\r\nexport function removeCanonical(): void {\r\n const link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (link) {\r\n link.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Set Open Graph meta tags\r\n */\r\nexport function setOpenGraphTags(og: OpenGraphMeta): void {\r\n if (!og) return;\r\n\r\n // Standard Open Graph properties\r\n if (og.title) setMetaProperty('og:title', og.title);\r\n if (og.description) setMetaProperty('og:description', og.description);\r\n if (og.type) setMetaProperty('og:type', og.type);\r\n if (og.url) setMetaProperty('og:url', og.url);\r\n if (og.image) setMetaProperty('og:image', og.image);\r\n if (og.imageWidth) setMetaProperty('og:image:width', og.imageWidth);\r\n if (og.imageHeight) setMetaProperty('og:image:height', og.imageHeight);\r\n if (og.imageAlt) setMetaProperty('og:image:alt', og.imageAlt);\r\n if (og.siteName) setMetaProperty('og:site_name', og.siteName);\r\n if (og.locale) setMetaProperty('og:locale', og.locale);\r\n\r\n // Handle additional custom og:* properties\r\n Object.keys(og).forEach((key) => {\r\n if (key.startsWith('og:') && key !== 'og:title' && key !== 'og:description' && \r\n key !== 'og:type' && key !== 'og:url' && key !== 'og:image' && \r\n key !== 'og:imageWidth' && key !== 'og:imageHeight' && \r\n key !== 'og:imageAlt' && key !== 'og:siteName' && key !== 'og:locale') {\r\n const value = og[key as keyof OpenGraphMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaProperty(key, value as string | number);\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set Twitter Card meta tags\r\n */\r\nexport function setTwitterCardTags(twitter: TwitterCardMeta): void {\r\n if (!twitter) return;\r\n\r\n if (twitter.card) setMetaTag('twitter:card', twitter.card);\r\n if (twitter.site) setMetaTag('twitter:site', twitter.site);\r\n if (twitter.creator) setMetaTag('twitter:creator', twitter.creator);\r\n if (twitter.title) setMetaTag('twitter:title', twitter.title);\r\n if (twitter.description) setMetaTag('twitter:description', twitter.description);\r\n if (twitter.image) setMetaTag('twitter:image', twitter.image);\r\n if (twitter.imageAlt) setMetaTag('twitter:image:alt', twitter.imageAlt);\r\n\r\n // Handle additional custom twitter:* properties\r\n Object.keys(twitter).forEach((key) => {\r\n if (key.startsWith('twitter:') && key !== 'twitter:card' && key !== 'twitter:site' && \r\n key !== 'twitter:creator' && key !== 'twitter:title' && \r\n key !== 'twitter:description' && key !== 'twitter:image' && \r\n key !== 'twitter:imageAlt') {\r\n const value = twitter[key as keyof TwitterCardMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaTag(key, String(value));\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set custom meta tags\r\n */\r\nexport function setCustomMetaTags(customMeta: CustomMeta[]): void {\r\n if (!customMeta || !Array.isArray(customMeta)) return;\r\n\r\n customMeta.forEach((meta) => {\r\n if (!meta.content) return;\r\n\r\n let element: HTMLMetaElement | null = null;\r\n\r\n if (meta.name) {\r\n element = getOrCreateMetaTag('name', meta.name);\r\n } else if (meta.property) {\r\n element = getOrCreateMetaTag('property', meta.property);\r\n } else if (meta.httpEquiv) {\r\n const selector = `meta[http-equiv=\"${meta.httpEquiv}\"]`;\r\n element = document.querySelector<HTMLMetaElement>(selector);\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute('http-equiv', meta.httpEquiv);\r\n document.head.appendChild(element);\r\n }\r\n } else if (meta.charset) {\r\n let charsetElement = document.querySelector<HTMLMetaElement>('meta[charset]');\r\n if (!charsetElement) {\r\n charsetElement = document.createElement('meta');\r\n charsetElement.setAttribute('charset', meta.charset);\r\n document.head.insertBefore(charsetElement, document.head.firstChild);\r\n }\r\n return;\r\n }\r\n\r\n if (element) {\r\n element.setAttribute('content', meta.content);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Inject JSON-LD structured data\r\n */\r\nexport function injectJsonLd(data: JsonLd, id?: string): () => void {\r\n const script = document.createElement('script');\r\n script.type = 'application/ld+json';\r\n if (id) {\r\n script.id = id;\r\n // Remove existing script with same id\r\n const existing = document.getElementById(id);\r\n if (existing) {\r\n existing.remove();\r\n }\r\n }\r\n script.textContent = JSON.stringify(data);\r\n document.head.appendChild(script);\r\n\r\n // Return cleanup function\r\n return () => {\r\n script.remove();\r\n };\r\n}\r\n\r\n/**\r\n * Remove JSON-LD script by id\r\n */\r\nexport function removeJsonLd(id: string): void {\r\n const script = document.getElementById(id);\r\n if (script && script.getAttribute('type') === 'application/ld+json') {\r\n script.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Format keywords as string\r\n */\r\nexport function formatKeywords(keywords: string | string[] | undefined): string {\r\n if (!keywords) return '';\r\n if (Array.isArray(keywords)) {\r\n return keywords.join(', ');\r\n }\r\n return keywords;\r\n}\r\n\r\n","import { useEffect } from 'react';\r\nimport type { SeoProps } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * SEO Component\r\n * \r\n * Renders and updates SEO meta tags in the document head.\r\n * Returns null (no UI rendering).\r\n * \r\n * @example\r\n * ```tsx\r\n * <Seo\r\n * title=\"My Page Title\"\r\n * description=\"Page description\"\r\n * keywords={['react', 'seo']}\r\n * canonical=\"https://example.com/page\"\r\n * ogImage=\"https://example.com/image.jpg\"\r\n * jsonLd={{ \"@context\": \"https://schema.org\", \"@type\": \"WebPage\" }}\r\n * />\r\n * ```\r\n */\r\nexport function Seo({\r\n title,\r\n description,\r\n keywords,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n}: SeoProps) {\r\n useEffect(() => {\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n let cleanupJsonLd: (() => void) | null = null;\r\n if (jsonLd) {\r\n cleanupJsonLd = injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n\r\n // Cleanup function\r\n return () => {\r\n if (cleanupJsonLd) {\r\n cleanupJsonLd();\r\n }\r\n };\r\n }, [\r\n title,\r\n description,\r\n keywords,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n ]);\r\n\r\n return null;\r\n}\r\n\r\n","import { useCallback } from 'react';\r\nimport type { SeoProps, UseSeoReturn } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n removeCanonical,\r\n removeJsonLd,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * useSeo Hook\r\n * \r\n * Hook-based API for managing SEO meta tags.\r\n * \r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { updateSeo } = useSeo();\r\n * \r\n * useEffect(() => {\r\n * updateSeo({\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * });\r\n * }, []);\r\n * \r\n * return <div>Content</div>;\r\n * }\r\n * ```\r\n */\r\nexport function useSeo(): UseSeoReturn {\r\n const updateSeo = useCallback((props: SeoProps) => {\r\n const {\r\n title,\r\n description,\r\n keywords,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n } = props;\r\n\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n if (jsonLd) {\r\n injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n }, []);\r\n\r\n const clearSeo = useCallback(() => {\r\n // Note: We don't clear title, description, keywords as they might be set by other means\r\n // Only clear what we manage\r\n removeCanonical();\r\n removeJsonLd(JSON_LD_ID);\r\n }, []);\r\n\r\n return {\r\n updateSeo,\r\n clearSeo,\r\n };\r\n}\r\n\r\n"],"names":["getOrCreateMetaTag","attribute","value","selector","element","setMetaTag","name","content","setMetaProperty","property","setTitle","title","setCanonical","url","link","removeCanonical","setOpenGraphTags","og","key","setTwitterCardTags","twitter","setCustomMetaTags","customMeta","meta","charsetElement","injectJsonLd","data","id","script","existing","removeJsonLd","formatKeywords","keywords","JSON_LD_ID","Seo","description","canonical","ogImage","ogType","ogUrl","ogTitle","ogDescription","ogSiteName","ogLocale","twitterCard","twitterSite","twitterCreator","twitterTitle","twitterDescription","twitterImage","twitterImageAlt","jsonLd","openGraph","useEffect","keywordsStr","ogData","twitterData","cleanupJsonLd","useSeo","updateSeo","useCallback","props","clearSeo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/utils.ts","../src/Seo.tsx","../src/useSeo.ts"],"sourcesContent":["import type { CustomMeta, CustomScript, JsonLd, OpenGraphMeta, TwitterCardMeta } from './types';\r\n\r\n/**\r\n * Get or create a meta tag element\r\n */\r\nfunction getOrCreateMetaTag(attribute: 'name' | 'property', value: string): HTMLMetaElement {\r\n const selector = `meta[${attribute}=\"${value}\"]`;\r\n let element = document.querySelector<HTMLMetaElement>(selector);\r\n\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute(attribute, value);\r\n document.head.appendChild(element);\r\n }\r\n\r\n return element;\r\n}\r\n\r\n/**\r\n * Set a meta tag by name\r\n */\r\nexport function setMetaTag(name: string, content: string): void {\r\n if (!content) return;\r\n\r\n const element = getOrCreateMetaTag('name', name);\r\n element.setAttribute('content', content);\r\n}\r\n\r\n/**\r\n * Set a meta tag by property (for Open Graph)\r\n */\r\nexport function setMetaProperty(property: string, content: string | number): void {\r\n if (content === undefined || content === null || content === '') return;\r\n\r\n const element = getOrCreateMetaTag('property', property);\r\n element.setAttribute('content', String(content));\r\n}\r\n\r\n/**\r\n * Set the page title\r\n */\r\nexport function setTitle(title: string): void {\r\n if (!title) return;\r\n document.title = title;\r\n}\r\n\r\n/**\r\n * Set canonical URL\r\n */\r\nexport function setCanonical(url: string): void {\r\n if (!url) return;\r\n\r\n let link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (!link) {\r\n link = document.createElement('link');\r\n link.setAttribute('rel', 'canonical');\r\n document.head.appendChild(link);\r\n }\r\n link.setAttribute('href', url);\r\n}\r\n\r\n/**\r\n * Remove canonical URL\r\n */\r\nexport function removeCanonical(): void {\r\n const link = document.querySelector<HTMLLinkElement>('link[rel=\"canonical\"]');\r\n if (link) {\r\n link.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Set Open Graph meta tags\r\n */\r\nexport function setOpenGraphTags(og: OpenGraphMeta): void {\r\n if (!og) return;\r\n\r\n // Standard Open Graph properties\r\n if (og.title) setMetaProperty('og:title', og.title);\r\n if (og.description) setMetaProperty('og:description', og.description);\r\n if (og.type) setMetaProperty('og:type', og.type);\r\n if (og.url) setMetaProperty('og:url', og.url);\r\n if (og.image) setMetaProperty('og:image', og.image);\r\n if (og.imageWidth) setMetaProperty('og:image:width', og.imageWidth);\r\n if (og.imageHeight) setMetaProperty('og:image:height', og.imageHeight);\r\n if (og.imageAlt) setMetaProperty('og:image:alt', og.imageAlt);\r\n if (og.siteName) setMetaProperty('og:site_name', og.siteName);\r\n if (og.locale) setMetaProperty('og:locale', og.locale);\r\n\r\n // Handle additional custom og:* properties\r\n Object.keys(og).forEach((key) => {\r\n if (key.startsWith('og:') && key !== 'og:title' && key !== 'og:description' && \r\n key !== 'og:type' && key !== 'og:url' && key !== 'og:image' && \r\n key !== 'og:imageWidth' && key !== 'og:imageHeight' && \r\n key !== 'og:imageAlt' && key !== 'og:siteName' && key !== 'og:locale') {\r\n const value = og[key as keyof OpenGraphMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaProperty(key, value as string | number);\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set Twitter Card meta tags\r\n */\r\nexport function setTwitterCardTags(twitter: TwitterCardMeta): void {\r\n if (!twitter) return;\r\n\r\n if (twitter.card) setMetaTag('twitter:card', twitter.card);\r\n if (twitter.site) setMetaTag('twitter:site', twitter.site);\r\n if (twitter.creator) setMetaTag('twitter:creator', twitter.creator);\r\n if (twitter.title) setMetaTag('twitter:title', twitter.title);\r\n if (twitter.description) setMetaTag('twitter:description', twitter.description);\r\n if (twitter.image) setMetaTag('twitter:image', twitter.image);\r\n if (twitter.imageAlt) setMetaTag('twitter:image:alt', twitter.imageAlt);\r\n\r\n // Handle additional custom twitter:* properties\r\n Object.keys(twitter).forEach((key) => {\r\n if (key.startsWith('twitter:') && key !== 'twitter:card' && key !== 'twitter:site' && \r\n key !== 'twitter:creator' && key !== 'twitter:title' && \r\n key !== 'twitter:description' && key !== 'twitter:image' && \r\n key !== 'twitter:imageAlt') {\r\n const value = twitter[key as keyof TwitterCardMeta];\r\n if (value !== undefined && value !== null && value !== '') {\r\n setMetaTag(key, String(value));\r\n }\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Set custom meta tags\r\n */\r\nexport function setCustomMetaTags(customMeta: CustomMeta[]): void {\r\n if (!customMeta || !Array.isArray(customMeta)) return;\r\n\r\n customMeta.forEach((meta) => {\r\n if (!meta.content) return;\r\n\r\n let element: HTMLMetaElement | null = null;\r\n\r\n if (meta.name) {\r\n element = getOrCreateMetaTag('name', meta.name);\r\n } else if (meta.property) {\r\n element = getOrCreateMetaTag('property', meta.property);\r\n } else if (meta.httpEquiv) {\r\n const selector = `meta[http-equiv=\"${meta.httpEquiv}\"]`;\r\n element = document.querySelector<HTMLMetaElement>(selector);\r\n if (!element) {\r\n element = document.createElement('meta');\r\n element.setAttribute('http-equiv', meta.httpEquiv);\r\n document.head.appendChild(element);\r\n }\r\n } else if (meta.charset) {\r\n let charsetElement = document.querySelector<HTMLMetaElement>('meta[charset]');\r\n if (!charsetElement) {\r\n charsetElement = document.createElement('meta');\r\n charsetElement.setAttribute('charset', meta.charset);\r\n document.head.insertBefore(charsetElement, document.head.firstChild);\r\n }\r\n return;\r\n }\r\n\r\n if (element) {\r\n element.setAttribute('content', meta.content);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * Inject JSON-LD structured data\r\n */\r\nexport function injectJsonLd(data: JsonLd, id?: string): () => void {\r\n const script = document.createElement('script');\r\n script.type = 'application/ld+json';\r\n if (id) {\r\n script.id = id;\r\n // Remove existing script with same id\r\n const existing = document.getElementById(id);\r\n if (existing) {\r\n existing.remove();\r\n }\r\n }\r\n script.textContent = JSON.stringify(data);\r\n document.head.appendChild(script);\r\n\r\n // Return cleanup function\r\n return () => {\r\n script.remove();\r\n };\r\n}\r\n\r\n/**\r\n * Remove JSON-LD script by id\r\n */\r\nexport function removeJsonLd(id: string): void {\r\n const script = document.getElementById(id);\r\n if (script && script.getAttribute('type') === 'application/ld+json') {\r\n script.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Format keywords as string\r\n */\r\nexport function formatKeywords(keywords: string | string[] | undefined): string {\r\n if (!keywords) return '';\r\n if (Array.isArray(keywords)) {\r\n return keywords.join(', ');\r\n }\r\n return keywords;\r\n}\r\n\r\n/**\r\n * Remove script by id\r\n */\r\nexport function removeScript(id: string): void {\r\n const script = document.getElementById(id);\r\n if (script && script.tagName === 'SCRIPT') {\r\n script.remove();\r\n }\r\n}\r\n\r\n/**\r\n * Inject Google Analytics script\r\n */\r\nexport function injectGoogleAnalytics(id: string): () => void {\r\n const GA_SCRIPT_ID = 'react-client-seo-ga';\r\n const GA_CONFIG_ID = 'react-client-seo-ga-config';\r\n\r\n // Remove existing scripts if present\r\n removeScript(GA_SCRIPT_ID);\r\n removeScript(GA_CONFIG_ID);\r\n\r\n // Inject gtag.js script\r\n const script = document.createElement('script');\r\n script.id = GA_SCRIPT_ID;\r\n script.async = true;\r\n script.src = `https://www.googletagmanager.com/gtag/js?id=${id}`;\r\n document.head.appendChild(script);\r\n\r\n // Inject gtag config script\r\n const configScript = document.createElement('script');\r\n configScript.id = GA_CONFIG_ID;\r\n configScript.textContent = `\r\n window.dataLayer = window.dataLayer || [];\r\n function gtag(){dataLayer.push(arguments);}\r\n gtag('js', new Date());\r\n gtag('config', '${id}');\r\n `;\r\n document.head.appendChild(configScript);\r\n\r\n // Return cleanup function\r\n return () => {\r\n removeScript(GA_SCRIPT_ID);\r\n removeScript(GA_CONFIG_ID);\r\n };\r\n}\r\n\r\n/**\r\n * Inject Google Tag Manager script\r\n */\r\nexport function injectGoogleTagManager(id: string): () => void {\r\n const GTM_SCRIPT_ID = 'react-client-seo-gtm';\r\n const GTM_NOSCRIPT_ID = 'react-client-seo-gtm-noscript';\r\n\r\n // Remove existing scripts if present\r\n removeScript(GTM_SCRIPT_ID);\r\n const existingNoscript = document.getElementById(GTM_NOSCRIPT_ID);\r\n if (existingNoscript) {\r\n existingNoscript.remove();\r\n }\r\n\r\n // Inject GTM script\r\n const script = document.createElement('script');\r\n script.id = GTM_SCRIPT_ID;\r\n script.textContent = `\r\n (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':\r\n new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],\r\n j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=\r\n 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);\r\n })(window,document,'script','dataLayer','${id}');\r\n `;\r\n document.head.appendChild(script);\r\n\r\n // Inject GTM noscript (in body, but we'll add it to head with a marker)\r\n // Note: GTM noscript should ideally be in body, but for client-side rendering\r\n // we'll inject it and let the user know they may need to add it to body manually\r\n const noscript = document.createElement('noscript');\r\n noscript.id = GTM_NOSCRIPT_ID;\r\n noscript.innerHTML = `<iframe src=\"https://www.googletagmanager.com/ns.html?id=${id}\" height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"></iframe>`;\r\n document.head.appendChild(noscript);\r\n\r\n // Return cleanup function\r\n return () => {\r\n removeScript(GTM_SCRIPT_ID);\r\n const noscriptEl = document.getElementById(GTM_NOSCRIPT_ID);\r\n if (noscriptEl) {\r\n noscriptEl.remove();\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * Inject custom script\r\n */\r\nexport function injectCustomScript(scriptConfig: CustomScript): () => void {\r\n if (!scriptConfig.src && !scriptConfig.content) {\r\n console.warn('CustomScript must have either src or content');\r\n return () => {};\r\n }\r\n\r\n const scriptId = scriptConfig.id || `react-client-seo-custom-${Date.now()}`;\r\n\r\n // Remove existing script if present\r\n if (scriptConfig.id) {\r\n removeScript(scriptConfig.id);\r\n }\r\n\r\n const script = document.createElement('script');\r\n script.id = scriptId;\r\n\r\n if (scriptConfig.src) {\r\n script.src = scriptConfig.src;\r\n }\r\n\r\n if (scriptConfig.content) {\r\n script.textContent = scriptConfig.content;\r\n }\r\n\r\n // Set script attributes\r\n if (scriptConfig.type) {\r\n script.type = scriptConfig.type;\r\n } else {\r\n script.type = 'text/javascript';\r\n }\r\n\r\n if (scriptConfig.strategy === 'async' || scriptConfig.async) {\r\n script.async = true;\r\n }\r\n\r\n if (scriptConfig.strategy === 'defer' || scriptConfig.defer) {\r\n script.defer = true;\r\n }\r\n\r\n document.head.appendChild(script);\r\n\r\n // Return cleanup function\r\n return () => {\r\n removeScript(scriptId);\r\n };\r\n}\r\n","import { useEffect } from 'react';\r\nimport type { SeoProps } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n injectGoogleAnalytics,\r\n injectGoogleTagManager,\r\n injectCustomScript,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * SEO Component\r\n * \r\n * Renders and updates SEO meta tags in the document head.\r\n * Returns null (no UI rendering).\r\n * \r\n * @example\r\n * ```tsx\r\n * <Seo\r\n * title=\"My Page Title\"\r\n * description=\"Page description\"\r\n * keywords={['react', 'seo']}\r\n * canonical=\"https://example.com/page\"\r\n * ogImage=\"https://example.com/image.jpg\"\r\n * jsonLd={{ \"@context\": \"https://schema.org\", \"@type\": \"WebPage\" }}\r\n * />\r\n * ```\r\n */\r\nexport function Seo({\r\n title,\r\n description,\r\n keywords,\r\n author,\r\n robots,\r\n language,\r\n viewport,\r\n generator,\r\n revisitAfter,\r\n rating,\r\n distribution,\r\n copyright,\r\n themeColor,\r\n referrer,\r\n formatDetection,\r\n mobileWebAppCapable,\r\n appleMobileWebAppCapable,\r\n geoRegion,\r\n geoPlacename,\r\n geoPosition,\r\n icbm,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n googleAnalyticsId,\r\n googleTagManagerId,\r\n customScripts,\r\n}: SeoProps) {\r\n useEffect(() => {\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set author\r\n if (author) {\r\n setMetaTag('author', author);\r\n }\r\n\r\n // Set robots\r\n if (robots) {\r\n setMetaTag('robots', robots);\r\n }\r\n\r\n // Set language\r\n if (language) {\r\n setMetaTag('language', language);\r\n setMetaTag('content-language', language);\r\n }\r\n\r\n // Set viewport\r\n if (viewport) {\r\n setMetaTag('viewport', viewport);\r\n }\r\n\r\n // Set generator\r\n if (generator) {\r\n setMetaTag('generator', generator);\r\n }\r\n\r\n // Set revisit-after\r\n if (revisitAfter) {\r\n setMetaTag('revisit-after', revisitAfter);\r\n }\r\n\r\n // Set rating\r\n if (rating) {\r\n setMetaTag('rating', rating);\r\n }\r\n\r\n // Set distribution\r\n if (distribution) {\r\n setMetaTag('distribution', distribution);\r\n }\r\n\r\n // Set copyright\r\n if (copyright) {\r\n setMetaTag('copyright', copyright);\r\n }\r\n\r\n // Set theme-color\r\n if (themeColor) {\r\n setMetaTag('theme-color', themeColor);\r\n }\r\n\r\n // Set referrer\r\n if (referrer) {\r\n setMetaTag('referrer', referrer);\r\n }\r\n\r\n // Set format-detection\r\n if (formatDetection) {\r\n setMetaTag('format-detection', formatDetection);\r\n }\r\n\r\n // Set mobile-web-app-capable\r\n if (mobileWebAppCapable) {\r\n setMetaTag('mobile-web-app-capable', mobileWebAppCapable);\r\n }\r\n\r\n // Set apple-mobile-web-app-capable\r\n if (appleMobileWebAppCapable) {\r\n setMetaTag('apple-mobile-web-app-capable', appleMobileWebAppCapable);\r\n }\r\n\r\n // Set geo tags\r\n if (geoRegion) {\r\n setMetaTag('geo.region', geoRegion);\r\n }\r\n if (geoPlacename) {\r\n setMetaTag('geo.placename', geoPlacename);\r\n }\r\n if (geoPosition) {\r\n setMetaTag('geo.position', geoPosition);\r\n }\r\n if (icbm) {\r\n setMetaTag('ICBM', icbm);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n let cleanupJsonLd: (() => void) | null = null;\r\n if (jsonLd) {\r\n cleanupJsonLd = injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n\r\n // Inject Google Analytics\r\n let cleanupGA: (() => void) | null = null;\r\n if (googleAnalyticsId) {\r\n cleanupGA = injectGoogleAnalytics(googleAnalyticsId);\r\n }\r\n\r\n // Inject Google Tag Manager\r\n let cleanupGTM: (() => void) | null = null;\r\n if (googleTagManagerId) {\r\n cleanupGTM = injectGoogleTagManager(googleTagManagerId);\r\n }\r\n\r\n // Inject custom scripts\r\n const cleanupCustomScripts: (() => void)[] = [];\r\n if (customScripts && Array.isArray(customScripts)) {\r\n customScripts.forEach((scriptConfig) => {\r\n const cleanup = injectCustomScript(scriptConfig);\r\n cleanupCustomScripts.push(cleanup);\r\n });\r\n }\r\n\r\n // Cleanup function\r\n return () => {\r\n if (cleanupJsonLd) {\r\n cleanupJsonLd();\r\n }\r\n if (cleanupGA) {\r\n cleanupGA();\r\n }\r\n if (cleanupGTM) {\r\n cleanupGTM();\r\n }\r\n cleanupCustomScripts.forEach((cleanup) => cleanup());\r\n };\r\n }, [\r\n title,\r\n description,\r\n keywords,\r\n author,\r\n robots,\r\n language,\r\n viewport,\r\n generator,\r\n revisitAfter,\r\n rating,\r\n distribution,\r\n copyright,\r\n themeColor,\r\n referrer,\r\n formatDetection,\r\n mobileWebAppCapable,\r\n appleMobileWebAppCapable,\r\n geoRegion,\r\n geoPlacename,\r\n geoPosition,\r\n icbm,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n googleAnalyticsId,\r\n googleTagManagerId,\r\n customScripts,\r\n ]);\r\n\r\n return null;\r\n}\r\n\r\n","import { useCallback } from 'react';\r\nimport type { SeoProps, UseSeoReturn } from './types';\r\nimport {\r\n setTitle,\r\n setMetaTag,\r\n setCanonical,\r\n setOpenGraphTags,\r\n setTwitterCardTags,\r\n setCustomMetaTags,\r\n injectJsonLd,\r\n formatKeywords,\r\n removeCanonical,\r\n removeJsonLd,\r\n injectGoogleAnalytics,\r\n injectGoogleTagManager,\r\n injectCustomScript,\r\n} from './utils';\r\n\r\nconst JSON_LD_ID = 'react-client-seo-jsonld';\r\n\r\n/**\r\n * useSeo Hook\r\n * \r\n * Hook-based API for managing SEO meta tags.\r\n * \r\n * @example\r\n * ```tsx\r\n * function MyComponent() {\r\n * const { updateSeo } = useSeo();\r\n * \r\n * useEffect(() => {\r\n * updateSeo({\r\n * title: 'My Page',\r\n * description: 'Page description',\r\n * });\r\n * }, []);\r\n * \r\n * return <div>Content</div>;\r\n * }\r\n * ```\r\n */\r\nexport function useSeo(): UseSeoReturn {\r\n const updateSeo = useCallback((props: SeoProps) => {\r\n const {\r\n title,\r\n description,\r\n keywords,\r\n author,\r\n robots,\r\n language,\r\n viewport,\r\n generator,\r\n revisitAfter,\r\n rating,\r\n distribution,\r\n copyright,\r\n themeColor,\r\n referrer,\r\n formatDetection,\r\n mobileWebAppCapable,\r\n appleMobileWebAppCapable,\r\n geoRegion,\r\n geoPlacename,\r\n geoPosition,\r\n icbm,\r\n canonical,\r\n ogImage,\r\n ogType,\r\n ogUrl,\r\n ogTitle,\r\n ogDescription,\r\n ogSiteName,\r\n ogLocale,\r\n twitterCard,\r\n twitterSite,\r\n twitterCreator,\r\n twitterTitle,\r\n twitterDescription,\r\n twitterImage,\r\n twitterImageAlt,\r\n jsonLd,\r\n customMeta,\r\n openGraph,\r\n twitter,\r\n googleAnalyticsId,\r\n googleTagManagerId,\r\n customScripts,\r\n } = props;\r\n\r\n // Set title\r\n if (title) {\r\n setTitle(title);\r\n }\r\n\r\n // Set description\r\n if (description) {\r\n setMetaTag('description', description);\r\n }\r\n\r\n // Set keywords\r\n const keywordsStr = formatKeywords(keywords);\r\n if (keywordsStr) {\r\n setMetaTag('keywords', keywordsStr);\r\n }\r\n\r\n // Set author\r\n if (author) {\r\n setMetaTag('author', author);\r\n }\r\n\r\n // Set robots\r\n if (robots) {\r\n setMetaTag('robots', robots);\r\n }\r\n\r\n // Set language\r\n if (language) {\r\n setMetaTag('language', language);\r\n setMetaTag('content-language', language);\r\n }\r\n\r\n // Set viewport\r\n if (viewport) {\r\n setMetaTag('viewport', viewport);\r\n }\r\n\r\n // Set generator\r\n if (generator) {\r\n setMetaTag('generator', generator);\r\n }\r\n\r\n // Set revisit-after\r\n if (revisitAfter) {\r\n setMetaTag('revisit-after', revisitAfter);\r\n }\r\n\r\n // Set rating\r\n if (rating) {\r\n setMetaTag('rating', rating);\r\n }\r\n\r\n // Set distribution\r\n if (distribution) {\r\n setMetaTag('distribution', distribution);\r\n }\r\n\r\n // Set copyright\r\n if (copyright) {\r\n setMetaTag('copyright', copyright);\r\n }\r\n\r\n // Set theme-color\r\n if (themeColor) {\r\n setMetaTag('theme-color', themeColor);\r\n }\r\n\r\n // Set referrer\r\n if (referrer) {\r\n setMetaTag('referrer', referrer);\r\n }\r\n\r\n // Set format-detection\r\n if (formatDetection) {\r\n setMetaTag('format-detection', formatDetection);\r\n }\r\n\r\n // Set mobile-web-app-capable\r\n if (mobileWebAppCapable) {\r\n setMetaTag('mobile-web-app-capable', mobileWebAppCapable);\r\n }\r\n\r\n // Set apple-mobile-web-app-capable\r\n if (appleMobileWebAppCapable) {\r\n setMetaTag('apple-mobile-web-app-capable', appleMobileWebAppCapable);\r\n }\r\n\r\n // Set geo tags\r\n if (geoRegion) {\r\n setMetaTag('geo.region', geoRegion);\r\n }\r\n if (geoPlacename) {\r\n setMetaTag('geo.placename', geoPlacename);\r\n }\r\n if (geoPosition) {\r\n setMetaTag('geo.position', geoPosition);\r\n }\r\n if (icbm) {\r\n setMetaTag('ICBM', icbm);\r\n }\r\n\r\n // Set canonical URL\r\n if (canonical) {\r\n setCanonical(canonical);\r\n }\r\n\r\n // Build Open Graph object\r\n const ogData: any = {\r\n ...openGraph,\r\n };\r\n\r\n if (ogTitle || title) {\r\n ogData.title = ogTitle || title;\r\n }\r\n if (ogDescription || description) {\r\n ogData.description = ogDescription || description;\r\n }\r\n if (ogType) {\r\n ogData.type = ogType;\r\n }\r\n if (ogUrl || canonical) {\r\n ogData.url = ogUrl || canonical;\r\n }\r\n if (ogImage) {\r\n ogData.image = ogImage;\r\n }\r\n if (ogSiteName) {\r\n ogData.siteName = ogSiteName;\r\n }\r\n if (ogLocale) {\r\n ogData.locale = ogLocale;\r\n }\r\n\r\n if (Object.keys(ogData).length > 0) {\r\n setOpenGraphTags(ogData);\r\n }\r\n\r\n // Build Twitter Card object\r\n const twitterData: any = {\r\n ...twitter,\r\n };\r\n\r\n if (twitterCard) {\r\n twitterData.card = twitterCard;\r\n }\r\n if (twitterSite) {\r\n twitterData.site = twitterSite;\r\n }\r\n if (twitterCreator) {\r\n twitterData.creator = twitterCreator;\r\n }\r\n if (twitterTitle || title) {\r\n twitterData.title = twitterTitle || title;\r\n }\r\n if (twitterDescription || description) {\r\n twitterData.description = twitterDescription || description;\r\n }\r\n if (twitterImage || ogImage) {\r\n twitterData.image = twitterImage || ogImage;\r\n }\r\n if (twitterImageAlt) {\r\n twitterData.imageAlt = twitterImageAlt;\r\n }\r\n\r\n if (Object.keys(twitterData).length > 0) {\r\n setTwitterCardTags(twitterData);\r\n }\r\n\r\n // Set custom meta tags\r\n if (customMeta) {\r\n setCustomMetaTags(customMeta);\r\n }\r\n\r\n // Inject JSON-LD\r\n if (jsonLd) {\r\n injectJsonLd(jsonLd, JSON_LD_ID);\r\n }\r\n\r\n // Inject Google Analytics\r\n if (googleAnalyticsId) {\r\n injectGoogleAnalytics(googleAnalyticsId);\r\n }\r\n\r\n // Inject Google Tag Manager\r\n if (googleTagManagerId) {\r\n injectGoogleTagManager(googleTagManagerId);\r\n }\r\n\r\n // Inject custom scripts\r\n if (customScripts && Array.isArray(customScripts)) {\r\n customScripts.forEach((scriptConfig) => {\r\n injectCustomScript(scriptConfig);\r\n });\r\n }\r\n }, []);\r\n\r\n const clearSeo = useCallback(() => {\r\n // Note: We don't clear title, description, keywords as they might be set by other means\r\n // Only clear what we manage\r\n removeCanonical();\r\n removeJsonLd(JSON_LD_ID);\r\n }, []);\r\n\r\n return {\r\n updateSeo,\r\n clearSeo,\r\n };\r\n}\r\n\r\n"],"names":["getOrCreateMetaTag","attribute","value","selector","element","setMetaTag","name","content","setMetaProperty","property","setTitle","title","setCanonical","url","link","removeCanonical","setOpenGraphTags","og","key","setTwitterCardTags","twitter","setCustomMetaTags","customMeta","meta","charsetElement","injectJsonLd","data","id","script","existing","removeJsonLd","formatKeywords","keywords","removeScript","injectGoogleAnalytics","GA_SCRIPT_ID","GA_CONFIG_ID","configScript","injectGoogleTagManager","GTM_SCRIPT_ID","GTM_NOSCRIPT_ID","existingNoscript","noscript","noscriptEl","injectCustomScript","scriptConfig","scriptId","JSON_LD_ID","Seo","description","author","robots","language","viewport","generator","revisitAfter","rating","distribution","copyright","themeColor","referrer","formatDetection","mobileWebAppCapable","appleMobileWebAppCapable","geoRegion","geoPlacename","geoPosition","icbm","canonical","ogImage","ogType","ogUrl","ogTitle","ogDescription","ogSiteName","ogLocale","twitterCard","twitterSite","twitterCreator","twitterTitle","twitterDescription","twitterImage","twitterImageAlt","jsonLd","openGraph","googleAnalyticsId","googleTagManagerId","customScripts","useEffect","keywordsStr","ogData","twitterData","cleanupJsonLd","cleanupGA","cleanupGTM","cleanupCustomScripts","cleanup","useSeo","updateSeo","useCallback","props","clearSeo"],"mappings":"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"}
|