@flocon-ai/react 0.0.0-stage → 0.0.0

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/dist/index.cjs ADDED
@@ -0,0 +1,805 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ FloconPage: () => FloconPage,
24
+ createFloconClient: () => createFloconClient,
25
+ floconLlmsTxt: () => floconLlmsTxt,
26
+ floconSitemap: () => floconSitemap,
27
+ getAllPages: () => getAllPages,
28
+ getFloconMetadata: () => getFloconMetadata,
29
+ getPage: () => getPage
30
+ });
31
+ module.exports = __toCommonJS(index_exports);
32
+
33
+ // node_modules/openapi-fetch/dist/index.mjs
34
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
35
+ var supportsRequestInitExt = () => {
36
+ return typeof process === "object" && Number.parseInt(process?.versions?.node?.substring(0, 2)) >= 18 && process.versions.undici;
37
+ };
38
+ function randomID() {
39
+ return Math.random().toString(36).slice(2, 11);
40
+ }
41
+ function createClient(clientOptions) {
42
+ let {
43
+ baseUrl = "",
44
+ Request: CustomRequest = globalThis.Request,
45
+ fetch: baseFetch = globalThis.fetch,
46
+ querySerializer: globalQuerySerializer,
47
+ bodySerializer: globalBodySerializer,
48
+ pathSerializer: globalPathSerializer,
49
+ headers: baseHeaders,
50
+ requestInitExt = void 0,
51
+ ...baseOptions
52
+ } = { ...clientOptions };
53
+ requestInitExt = supportsRequestInitExt() ? requestInitExt : void 0;
54
+ baseUrl = removeTrailingSlash(baseUrl);
55
+ const globalMiddlewares = [];
56
+ async function coreFetch(schemaPath, fetchOptions) {
57
+ const {
58
+ baseUrl: localBaseUrl,
59
+ fetch = baseFetch,
60
+ Request = CustomRequest,
61
+ headers,
62
+ params = {},
63
+ parseAs = "json",
64
+ querySerializer: requestQuerySerializer,
65
+ bodySerializer = globalBodySerializer ?? defaultBodySerializer,
66
+ pathSerializer: requestPathSerializer,
67
+ body,
68
+ middleware: requestMiddlewares = [],
69
+ ...init
70
+ } = fetchOptions || {};
71
+ let finalBaseUrl = baseUrl;
72
+ if (localBaseUrl) {
73
+ finalBaseUrl = removeTrailingSlash(localBaseUrl) ?? baseUrl;
74
+ }
75
+ let querySerializer = typeof globalQuerySerializer === "function" ? globalQuerySerializer : createQuerySerializer(globalQuerySerializer);
76
+ if (requestQuerySerializer) {
77
+ querySerializer = typeof requestQuerySerializer === "function" ? requestQuerySerializer : createQuerySerializer({
78
+ ...typeof globalQuerySerializer === "object" ? globalQuerySerializer : {},
79
+ ...requestQuerySerializer
80
+ });
81
+ }
82
+ const pathSerializer = requestPathSerializer || globalPathSerializer || defaultPathSerializer;
83
+ const serializedBody = body === void 0 ? void 0 : bodySerializer(
84
+ body,
85
+ // Note: we declare mergeHeaders() both here and below because it’s a bit of a chicken-or-egg situation:
86
+ // bodySerializer() needs all headers so we aren’t dropping ones set by the user, however,
87
+ // the result of this ALSO sets the lowest-priority content-type header. So we re-merge below,
88
+ // setting the content-type at the very beginning to be overwritten.
89
+ // Lastly, based on the way headers work, it’s not a simple “present-or-not” check becauase null intentionally un-sets headers.
90
+ mergeHeaders(baseHeaders, headers, params.header)
91
+ );
92
+ const finalHeaders = mergeHeaders(
93
+ // with no body, we should not to set Content-Type
94
+ serializedBody === void 0 || // if serialized body is FormData; browser will correctly set Content-Type & boundary expression
95
+ serializedBody instanceof FormData ? {} : {
96
+ "Content-Type": "application/json"
97
+ },
98
+ baseHeaders,
99
+ headers,
100
+ params.header
101
+ );
102
+ const finalMiddlewares = [...globalMiddlewares, ...requestMiddlewares];
103
+ const requestInit = {
104
+ redirect: "follow",
105
+ ...baseOptions,
106
+ ...init,
107
+ body: serializedBody,
108
+ headers: finalHeaders
109
+ };
110
+ let id;
111
+ let options;
112
+ let request = new Request(
113
+ createFinalURL(schemaPath, { baseUrl: finalBaseUrl, params, querySerializer, pathSerializer }),
114
+ requestInit
115
+ );
116
+ let response;
117
+ for (const key in init) {
118
+ if (!(key in request)) {
119
+ request[key] = init[key];
120
+ }
121
+ }
122
+ if (finalMiddlewares.length) {
123
+ id = randomID();
124
+ options = Object.freeze({
125
+ baseUrl: finalBaseUrl,
126
+ fetch,
127
+ parseAs,
128
+ querySerializer,
129
+ bodySerializer,
130
+ pathSerializer
131
+ });
132
+ for (const m of finalMiddlewares) {
133
+ if (m && typeof m === "object" && typeof m.onRequest === "function") {
134
+ const result = await m.onRequest({
135
+ request,
136
+ schemaPath,
137
+ params,
138
+ options,
139
+ id
140
+ });
141
+ if (result) {
142
+ if (result instanceof Request) {
143
+ request = result;
144
+ } else if (result instanceof Response) {
145
+ response = result;
146
+ break;
147
+ } else {
148
+ throw new Error("onRequest: must return new Request() or Response() when modifying the request");
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ if (!response) {
155
+ try {
156
+ response = await fetch(request, requestInitExt);
157
+ } catch (error2) {
158
+ let errorAfterMiddleware = error2;
159
+ if (finalMiddlewares.length) {
160
+ for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
161
+ const m = finalMiddlewares[i];
162
+ if (m && typeof m === "object" && typeof m.onError === "function") {
163
+ const result = await m.onError({
164
+ request,
165
+ error: errorAfterMiddleware,
166
+ schemaPath,
167
+ params,
168
+ options,
169
+ id
170
+ });
171
+ if (result) {
172
+ if (result instanceof Response) {
173
+ errorAfterMiddleware = void 0;
174
+ response = result;
175
+ break;
176
+ }
177
+ if (result instanceof Error) {
178
+ errorAfterMiddleware = result;
179
+ continue;
180
+ }
181
+ throw new Error("onError: must return new Response() or instance of Error");
182
+ }
183
+ }
184
+ }
185
+ }
186
+ if (errorAfterMiddleware) {
187
+ throw errorAfterMiddleware;
188
+ }
189
+ }
190
+ if (finalMiddlewares.length) {
191
+ for (let i = finalMiddlewares.length - 1; i >= 0; i--) {
192
+ const m = finalMiddlewares[i];
193
+ if (m && typeof m === "object" && typeof m.onResponse === "function") {
194
+ const result = await m.onResponse({
195
+ request,
196
+ response,
197
+ schemaPath,
198
+ params,
199
+ options,
200
+ id
201
+ });
202
+ if (result) {
203
+ if (!(result instanceof Response)) {
204
+ throw new Error("onResponse: must return new Response() when modifying the response");
205
+ }
206
+ response = result;
207
+ }
208
+ }
209
+ }
210
+ }
211
+ }
212
+ const contentLength = response.headers.get("Content-Length");
213
+ if (response.status === 204 || request.method === "HEAD" || contentLength === "0" && !response.headers.get("Transfer-Encoding")?.includes("chunked")) {
214
+ return response.ok ? { data: void 0, response } : { error: void 0, response };
215
+ }
216
+ if (response.ok) {
217
+ const getResponseData = async () => {
218
+ if (parseAs === "stream") {
219
+ return response.body;
220
+ }
221
+ if (parseAs === "json" && !contentLength) {
222
+ const raw = await response.text();
223
+ return raw ? JSON.parse(raw) : void 0;
224
+ }
225
+ return await response[parseAs]();
226
+ };
227
+ return { data: await getResponseData(), response };
228
+ }
229
+ let error = await response.text();
230
+ try {
231
+ error = JSON.parse(error);
232
+ } catch {
233
+ }
234
+ return { error, response };
235
+ }
236
+ return {
237
+ request(method, url, init) {
238
+ return coreFetch(url, { ...init, method: method.toUpperCase() });
239
+ },
240
+ /** Call a GET endpoint */
241
+ GET(url, init) {
242
+ return coreFetch(url, { ...init, method: "GET" });
243
+ },
244
+ /** Call a PUT endpoint */
245
+ PUT(url, init) {
246
+ return coreFetch(url, { ...init, method: "PUT" });
247
+ },
248
+ /** Call a POST endpoint */
249
+ POST(url, init) {
250
+ return coreFetch(url, { ...init, method: "POST" });
251
+ },
252
+ /** Call a DELETE endpoint */
253
+ DELETE(url, init) {
254
+ return coreFetch(url, { ...init, method: "DELETE" });
255
+ },
256
+ /** Call a OPTIONS endpoint */
257
+ OPTIONS(url, init) {
258
+ return coreFetch(url, { ...init, method: "OPTIONS" });
259
+ },
260
+ /** Call a HEAD endpoint */
261
+ HEAD(url, init) {
262
+ return coreFetch(url, { ...init, method: "HEAD" });
263
+ },
264
+ /** Call a PATCH endpoint */
265
+ PATCH(url, init) {
266
+ return coreFetch(url, { ...init, method: "PATCH" });
267
+ },
268
+ /** Call a TRACE endpoint */
269
+ TRACE(url, init) {
270
+ return coreFetch(url, { ...init, method: "TRACE" });
271
+ },
272
+ /** Register middleware */
273
+ use(...middleware) {
274
+ for (const m of middleware) {
275
+ if (!m) {
276
+ continue;
277
+ }
278
+ if (typeof m !== "object" || !("onRequest" in m || "onResponse" in m || "onError" in m)) {
279
+ throw new Error("Middleware must be an object with one of `onRequest()`, `onResponse() or `onError()`");
280
+ }
281
+ globalMiddlewares.push(m);
282
+ }
283
+ },
284
+ /** Unregister middleware */
285
+ eject(...middleware) {
286
+ for (const m of middleware) {
287
+ const i = globalMiddlewares.indexOf(m);
288
+ if (i !== -1) {
289
+ globalMiddlewares.splice(i, 1);
290
+ }
291
+ }
292
+ }
293
+ };
294
+ }
295
+ function serializePrimitiveParam(name, value, options) {
296
+ if (value === void 0 || value === null) {
297
+ return "";
298
+ }
299
+ if (typeof value === "object") {
300
+ throw new Error(
301
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
302
+ );
303
+ }
304
+ return `${name}=${options?.allowReserved === true ? value : encodeURIComponent(value)}`;
305
+ }
306
+ function serializeObjectParam(name, value, options) {
307
+ if (!value || typeof value !== "object") {
308
+ return "";
309
+ }
310
+ const values = [];
311
+ const joiner = {
312
+ simple: ",",
313
+ label: ".",
314
+ matrix: ";"
315
+ }[options.style] || "&";
316
+ if (options.style !== "deepObject" && options.explode === false) {
317
+ for (const k in value) {
318
+ values.push(k, options.allowReserved === true ? value[k] : encodeURIComponent(value[k]));
319
+ }
320
+ const final2 = values.join(",");
321
+ switch (options.style) {
322
+ case "form": {
323
+ return `${name}=${final2}`;
324
+ }
325
+ case "label": {
326
+ return `.${final2}`;
327
+ }
328
+ case "matrix": {
329
+ return `;${name}=${final2}`;
330
+ }
331
+ default: {
332
+ return final2;
333
+ }
334
+ }
335
+ }
336
+ for (const k in value) {
337
+ const finalName = options.style === "deepObject" ? `${name}[${k}]` : k;
338
+ values.push(serializePrimitiveParam(finalName, value[k], options));
339
+ }
340
+ const final = values.join(joiner);
341
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${final}` : final;
342
+ }
343
+ function serializeArrayParam(name, value, options) {
344
+ if (!Array.isArray(value)) {
345
+ return "";
346
+ }
347
+ if (options.explode === false) {
348
+ const joiner2 = { form: ",", spaceDelimited: "%20", pipeDelimited: "|" }[options.style] || ",";
349
+ const final = (options.allowReserved === true ? value : value.map((v) => encodeURIComponent(v))).join(joiner2);
350
+ switch (options.style) {
351
+ case "simple": {
352
+ return final;
353
+ }
354
+ case "label": {
355
+ return `.${final}`;
356
+ }
357
+ case "matrix": {
358
+ return `;${name}=${final}`;
359
+ }
360
+ // case "spaceDelimited":
361
+ // case "pipeDelimited":
362
+ default: {
363
+ return `${name}=${final}`;
364
+ }
365
+ }
366
+ }
367
+ const joiner = { simple: ",", label: ".", matrix: ";" }[options.style] || "&";
368
+ const values = [];
369
+ for (const v of value) {
370
+ if (options.style === "simple" || options.style === "label") {
371
+ values.push(options.allowReserved === true ? v : encodeURIComponent(v));
372
+ } else {
373
+ values.push(serializePrimitiveParam(name, v, options));
374
+ }
375
+ }
376
+ return options.style === "label" || options.style === "matrix" ? `${joiner}${values.join(joiner)}` : values.join(joiner);
377
+ }
378
+ function createQuerySerializer(options) {
379
+ return function querySerializer(queryParams) {
380
+ const search = [];
381
+ if (queryParams && typeof queryParams === "object") {
382
+ for (const name in queryParams) {
383
+ const value = queryParams[name];
384
+ if (value === void 0 || value === null) {
385
+ continue;
386
+ }
387
+ if (Array.isArray(value)) {
388
+ if (value.length === 0) {
389
+ continue;
390
+ }
391
+ search.push(
392
+ serializeArrayParam(name, value, {
393
+ style: "form",
394
+ explode: true,
395
+ ...options?.array,
396
+ allowReserved: options?.allowReserved || false
397
+ })
398
+ );
399
+ continue;
400
+ }
401
+ if (typeof value === "object") {
402
+ search.push(
403
+ serializeObjectParam(name, value, {
404
+ style: "deepObject",
405
+ explode: true,
406
+ ...options?.object,
407
+ allowReserved: options?.allowReserved || false
408
+ })
409
+ );
410
+ continue;
411
+ }
412
+ search.push(serializePrimitiveParam(name, value, options));
413
+ }
414
+ }
415
+ return search.join("&");
416
+ };
417
+ }
418
+ function defaultPathSerializer(pathname, pathParams) {
419
+ let nextURL = pathname;
420
+ for (const match of pathname.match(PATH_PARAM_RE) ?? []) {
421
+ let name = match.substring(1, match.length - 1);
422
+ let explode = false;
423
+ let style = "simple";
424
+ if (name.endsWith("*")) {
425
+ explode = true;
426
+ name = name.substring(0, name.length - 1);
427
+ }
428
+ if (name.startsWith(".")) {
429
+ style = "label";
430
+ name = name.substring(1);
431
+ } else if (name.startsWith(";")) {
432
+ style = "matrix";
433
+ name = name.substring(1);
434
+ }
435
+ if (!pathParams || pathParams[name] === void 0 || pathParams[name] === null) {
436
+ continue;
437
+ }
438
+ const value = pathParams[name];
439
+ if (Array.isArray(value)) {
440
+ nextURL = nextURL.replace(match, serializeArrayParam(name, value, { style, explode }));
441
+ continue;
442
+ }
443
+ if (typeof value === "object") {
444
+ nextURL = nextURL.replace(match, serializeObjectParam(name, value, { style, explode }));
445
+ continue;
446
+ }
447
+ if (style === "matrix") {
448
+ nextURL = nextURL.replace(match, `;${serializePrimitiveParam(name, value)}`);
449
+ continue;
450
+ }
451
+ nextURL = nextURL.replace(match, style === "label" ? `.${encodeURIComponent(value)}` : encodeURIComponent(value));
452
+ }
453
+ return nextURL;
454
+ }
455
+ function defaultBodySerializer(body, headers) {
456
+ if (body instanceof FormData) {
457
+ return body;
458
+ }
459
+ if (headers) {
460
+ const contentType = headers.get instanceof Function ? headers.get("Content-Type") ?? headers.get("content-type") : headers["Content-Type"] ?? headers["content-type"];
461
+ if (contentType === "application/x-www-form-urlencoded") {
462
+ return new URLSearchParams(body).toString();
463
+ }
464
+ }
465
+ return JSON.stringify(body);
466
+ }
467
+ function createFinalURL(pathname, options) {
468
+ let finalURL = `${options.baseUrl}${pathname}`;
469
+ if (options.params?.path) {
470
+ finalURL = options.pathSerializer(finalURL, options.params.path);
471
+ }
472
+ let search = options.querySerializer(options.params.query ?? {});
473
+ if (search.startsWith("?")) {
474
+ search = search.substring(1);
475
+ }
476
+ if (search) {
477
+ finalURL += `?${search}`;
478
+ }
479
+ return finalURL;
480
+ }
481
+ function mergeHeaders(...allHeaders) {
482
+ const finalHeaders = new Headers();
483
+ for (const h of allHeaders) {
484
+ if (!h || typeof h !== "object") {
485
+ continue;
486
+ }
487
+ const iterator = h instanceof Headers ? h.entries() : Object.entries(h);
488
+ for (const [k, v] of iterator) {
489
+ if (v === null) {
490
+ finalHeaders.delete(k);
491
+ } else if (Array.isArray(v)) {
492
+ for (const v2 of v) {
493
+ finalHeaders.append(k, v2);
494
+ }
495
+ } else if (v !== void 0) {
496
+ finalHeaders.set(k, v);
497
+ }
498
+ }
499
+ }
500
+ return finalHeaders;
501
+ }
502
+ function removeTrailingSlash(url) {
503
+ if (url.endsWith("/")) {
504
+ return url.substring(0, url.length - 1);
505
+ }
506
+ return url;
507
+ }
508
+
509
+ // src/client.ts
510
+ var PACKAGES_API_URL = "https://api.flocon-ai.com";
511
+ function createFloconClient() {
512
+ if (typeof window !== "undefined") {
513
+ throw new Error("Flocon: call this on the server only (route loader, server function), never in the browser");
514
+ }
515
+ const token = process.env.FLOCON_TOKEN;
516
+ if (!token) throw new Error("FLOCON_TOKEN is missing");
517
+ return createClient({
518
+ baseUrl: PACKAGES_API_URL,
519
+ headers: { Authorization: `Bearer ${token}` }
520
+ });
521
+ }
522
+ async function getPage({ path, locale }) {
523
+ const client = createFloconClient();
524
+ const { data: website, error: websiteError } = await client.GET("/website");
525
+ if (!website) throw new Error(`Flocon: could not load the website: ${JSON.stringify(websiteError)}`);
526
+ const res = await client.GET("/pages/{locale}/{path}", {
527
+ // The API takes the rest of the URL as the path: keep its slashes.
528
+ params: { path: { locale: locale ?? website.defaultLocale, path: path.replace(/^\//, "") } },
529
+ // openapi-fetch would encode "/" as %2F: encode each segment instead.
530
+ pathSerializer: (url, params) => url.replace("{locale}", encodeURIComponent(String(params?.locale))).replace("{path}", String(params?.path).split("/").map((s) => s === "." || s === ".." ? s.replace(/\./g, "%2E") : encodeURIComponent(s)).join("/"))
531
+ });
532
+ if (res.response.status === 404) return null;
533
+ if (!res.data) {
534
+ throw new Error(`Flocon: Packages API answered ${res.response.status}: ${JSON.stringify(res.error)}`);
535
+ }
536
+ return { ...res.data, badge: website.badge, defaultLocale: website.defaultLocale };
537
+ }
538
+
539
+ // src/pages.ts
540
+ async function getAllPages() {
541
+ const { data, error } = await createFloconClient().GET("/pages");
542
+ if (!data) throw new Error(`Flocon getAllPages failed: ${JSON.stringify(error)}`);
543
+ return data;
544
+ }
545
+ var xml = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
546
+ async function floconSitemap({ url }) {
547
+ const pages = await getAllPages();
548
+ const entries = pages.map((page) => {
549
+ const links = [page.locale, ...page.alternates].map((l) => `<xhtml:link rel="alternate" hreflang="${xml(l)}" href="${xml(url({ locale: l, path: page.path }))}"/>`).join("");
550
+ return `<url><loc>${xml(url(page))}</loc><lastmod>${xml(page.updatedAt)}</lastmod>${links}</url>`;
551
+ });
552
+ return `<?xml version="1.0" encoding="UTF-8"?>
553
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">
554
+ ` + entries.join("\n") + `
555
+ </urlset>
556
+ `;
557
+ }
558
+ async function floconLlmsTxt({ url }) {
559
+ const pages = await getAllPages();
560
+ return pages.map((page) => `- [${page.title}](${url(page)})`).join("\n") + "\n";
561
+ }
562
+
563
+ // src/markdown.tsx
564
+ var import_jsx_runtime = require("react/jsx-runtime");
565
+ var INLINE = /`([^`]+)`|\*\*(.+?)\*\*|\*(.+?)\*|\[([^\]]+)\]\(([^)\s]+)\)/;
566
+ function isSafeUrl(url) {
567
+ return /^(https?:\/\/|mailto:|\/|#)/i.test(url) && !url.startsWith("//") && !url.includes("\\");
568
+ }
569
+ function renderInline(text, key = "") {
570
+ const out = [];
571
+ let rest = text;
572
+ let i = 0;
573
+ while (rest) {
574
+ const m = INLINE.exec(rest);
575
+ if (!m) {
576
+ out.push(rest);
577
+ break;
578
+ }
579
+ if (m.index > 0) out.push(rest.slice(0, m.index));
580
+ const k = `${key}${i++}`;
581
+ if (m[1] !== void 0) out.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)("code", { children: m[1] }, k));
582
+ else if (m[2] !== void 0) out.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: renderInline(m[2], `${k}-`) }, k));
583
+ else if (m[3] !== void 0) out.push(/* @__PURE__ */ (0, import_jsx_runtime.jsx)("em", { children: renderInline(m[3], `${k}-`) }, k));
584
+ else if (isSafeUrl(m[5])) {
585
+ out.push(
586
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: m[5], children: renderInline(m[4], `${k}-`) }, k)
587
+ );
588
+ } else out.push(m[0]);
589
+ rest = rest.slice(m.index + m[0].length);
590
+ }
591
+ return out;
592
+ }
593
+
594
+ // src/styles.ts
595
+ var FLOCON_CSS = `@layer flocon{
596
+ .dark .flocon-page{color-scheme:dark}
597
+ .flocon-page{--flocon-primary:var(--primary,light-dark(#1E6EBE,#6CB2F0));--flocon-background:var(--background,transparent);--flocon-foreground:var(--foreground,light-dark(#121A24,#E8EEF4));--flocon-card:var(--card,transparent);--flocon-muted:var(--muted,light-dark(#F3F6F9,#151E28));--flocon-muted-foreground:var(--muted-foreground,light-dark(#566373,#98A6B5));--flocon-border:var(--border,light-dark(#E4E9EF,#212C38));--flocon-radius:var(--radius,14px);--flocon-font:var(--font-sans);max-width:48rem;margin:0 auto;padding:2rem 1rem;background:var(--flocon-background);color:var(--flocon-foreground);font-family:var(--flocon-font,inherit);line-height:1.7;overflow-wrap:anywhere}
598
+ .flocon-page h1{font-size:clamp(1.75rem,1.4rem + 1.5vw,2.25rem);line-height:1.2;margin:0 0 1.5rem;font-weight:700}
599
+ .flocon-page h2{font-size:clamp(1.25rem,1.1rem + .7vw,1.5rem);line-height:1.3;margin:2rem 0 .75rem;font-weight:600}
600
+ .flocon-page h3{font-size:clamp(1.1rem,1rem + .4vw,1.2rem);line-height:1.4;margin:1.5rem 0 .5rem;font-weight:600}
601
+ .flocon-page p{margin:0 0 1rem}
602
+ .flocon-page a{color:var(--flocon-primary);text-decoration:underline}
603
+ .flocon-page a:focus-visible,.flocon-page summary:focus-visible{outline:2px solid var(--flocon-primary);outline-offset:2px;border-radius:calc(var(--flocon-radius)*.4)}
604
+ .flocon-page code{background:var(--flocon-muted);border-radius:calc(var(--flocon-radius)*.4);padding:.1em .35em;font-size:.9em}
605
+ .flocon-page .flocon-description{font-size:1.15rem;color:var(--flocon-muted-foreground)}
606
+ .flocon-page ul,.flocon-page ol{margin:0 0 1rem;padding-left:1.5rem}
607
+ .flocon-page li{margin:.25rem 0}
608
+ .flocon-page .flocon-faq details{border:1px solid var(--flocon-border);border-radius:var(--flocon-radius);background:var(--flocon-card);margin:0 0 .5rem}
609
+ .flocon-page .flocon-faq summary{cursor:pointer;font-weight:600;padding:.75rem 1rem;min-height:44px;box-sizing:border-box}
610
+ .flocon-page .flocon-faq details p{margin:0;padding:0 1rem .75rem}
611
+ .flocon-page .flocon-table{overflow-x:auto;margin:0 0 1rem}
612
+ .flocon-page table{border-collapse:collapse;width:100%;font-size:.95rem;overflow-wrap:normal}
613
+ .flocon-page th,.flocon-page td{border:1px solid var(--flocon-border);padding:.5rem .75rem;text-align:left}
614
+ .flocon-page th{background:var(--flocon-muted)}
615
+ .flocon-page .flocon-space{height:2rem}
616
+ .flocon-page .flocon-related{margin-top:2rem;border-top:1px solid var(--flocon-border);padding-top:1rem}
617
+ .flocon-page .flocon-related h2{margin-top:0;font-size:1.1rem}
618
+ .flocon-page .flocon-related li{margin:0}
619
+ .flocon-page .flocon-related a{display:inline-flex;align-items:center;min-height:44px}
620
+ .flocon-page .flocon-badge{margin-top:2rem;font-size:.85rem;text-align:center}
621
+ .flocon-page .flocon-badge a{display:inline-flex;align-items:center;min-height:44px;color:var(--flocon-muted-foreground);text-decoration:none}
622
+ }
623
+ `;
624
+
625
+ // src/jsonld.ts
626
+ var offer = (o) => o ? { "@type": "Offer", price: o.price, priceCurrency: o.currency } : void 0;
627
+ function buildJsonLd(page) {
628
+ const { seo } = page;
629
+ const nodes = [];
630
+ const author = seo.author ? { "@type": "Person", name: seo.author.name, url: seo.author.url } : void 0;
631
+ for (const s of seo.schemas ?? []) {
632
+ switch (s.type) {
633
+ case "article":
634
+ nodes.push({
635
+ "@type": "Article",
636
+ headline: seo.title,
637
+ description: seo.description,
638
+ inLanguage: page.locale,
639
+ datePublished: page.createdAt,
640
+ dateModified: page.updatedAt,
641
+ author
642
+ });
643
+ break;
644
+ case "softwareApplication":
645
+ nodes.push({
646
+ "@type": "SoftwareApplication",
647
+ name: s.name,
648
+ description: seo.description,
649
+ applicationCategory: s.category,
650
+ operatingSystem: s.operatingSystem,
651
+ offers: offer(s.offers),
652
+ dateModified: page.updatedAt
653
+ });
654
+ break;
655
+ case "product":
656
+ nodes.push({
657
+ "@type": "Product",
658
+ name: s.name,
659
+ description: seo.description,
660
+ image: s.image,
661
+ offers: offer(s.offers)
662
+ });
663
+ break;
664
+ case "howTo":
665
+ nodes.push({
666
+ "@type": "HowTo",
667
+ name: s.name,
668
+ description: seo.description,
669
+ totalTime: s.totalTime,
670
+ step: s.steps.map((st) => ({ "@type": "HowToStep", name: st.name, text: st.text })),
671
+ dateModified: page.updatedAt
672
+ });
673
+ break;
674
+ case "event":
675
+ nodes.push({
676
+ "@type": "Event",
677
+ name: s.name,
678
+ description: seo.description,
679
+ startDate: s.startDate,
680
+ endDate: s.endDate,
681
+ eventAttendanceMode: s.online ? "https://schema.org/OnlineEventAttendanceMode" : s.location ? "https://schema.org/OfflineEventAttendanceMode" : void 0,
682
+ location: s.location ? { "@type": "Place", name: s.location.name, address: s.location.address } : void 0,
683
+ offers: offer(s.offers)
684
+ });
685
+ break;
686
+ case "localBusiness":
687
+ nodes.push({
688
+ "@type": "LocalBusiness",
689
+ name: s.name,
690
+ description: seo.description,
691
+ address: s.address,
692
+ telephone: s.telephone,
693
+ openingHours: s.openingHours,
694
+ priceRange: s.priceRange,
695
+ image: s.image
696
+ });
697
+ break;
698
+ }
699
+ }
700
+ const faq = page.blocks.flatMap((b) => b.type === "faq" ? b.items : []);
701
+ if (faq.length > 0) {
702
+ nodes.push({
703
+ "@type": "FAQPage",
704
+ mainEntity: faq.map((it) => ({
705
+ "@type": "Question",
706
+ name: it.question,
707
+ acceptedAnswer: { "@type": "Answer", text: it.answer }
708
+ }))
709
+ });
710
+ }
711
+ return nodes;
712
+ }
713
+ function jsonLdScript(page) {
714
+ const nodes = buildJsonLd(page);
715
+ if (nodes.length === 0) return null;
716
+ const graph = nodes.map((n) => ({ "@context": "https://schema.org", ...n }));
717
+ return JSON.stringify(graph).replace(/</g, "\\u003c");
718
+ }
719
+
720
+ // src/page.tsx
721
+ var import_jsx_runtime2 = require("react/jsx-runtime");
722
+ var STRINGS = {
723
+ en: { related: "Related pages" },
724
+ fr: { related: "Pages associ\xE9es" }
725
+ };
726
+ function FloconPage({ page, url }) {
727
+ const t = STRINGS[page.locale] ?? STRINGS.en;
728
+ const jsonLd = jsonLdScript(page);
729
+ const href = (p) => url ? url({ locale: page.locale, path: p }) : p;
730
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("article", { className: "flocon-page", lang: page.locale, children: [
731
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { dangerouslySetInnerHTML: { __html: FLOCON_CSS } }),
732
+ jsonLd && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: jsonLd } }),
733
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h1", { children: page.title }),
734
+ page.blocks.map((b, i) => {
735
+ switch (b.type) {
736
+ case "description":
737
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "flocon-description", children: renderInline(b.content) }, i);
738
+ case "heading":
739
+ return Number(b.level) === 3 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { children: b.content }, i) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: b.content }, i);
740
+ case "text":
741
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: renderInline(b.content) }, i);
742
+ case "list": {
743
+ const items = b.items.map((it, j) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: renderInline(it) }, j));
744
+ return b.ordered ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ol", { children: items }, i) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { children: items }, i);
745
+ }
746
+ case "faq":
747
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flocon-faq", children: b.items.map((it, j) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("details", { children: [
748
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("summary", { children: it.question }),
749
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { children: renderInline(it.answer) })
750
+ ] }, j)) }, i);
751
+ case "table":
752
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flocon-table", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("table", { children: [
753
+ b.headers && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: b.headers.map((h, j) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("th", { children: h }, j)) }) }),
754
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tbody", { children: b.rows.map((row, r) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("tr", { children: row.map((cell, c) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("td", { children: cell }, c)) }, r)) })
755
+ ] }) }, i);
756
+ case "related":
757
+ return b.pages.length === 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("nav", { className: "flocon-related", "aria-label": t.related, children: [
758
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { children: t.related }),
759
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { children: b.pages.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: href(p.path), children: p.title }) }, p.path)) })
760
+ ] }, i);
761
+ case "space":
762
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flocon-space", "aria-hidden": "true" }, i);
763
+ }
764
+ }),
765
+ page.badge && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "flocon-badge", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("a", { href: "https://flocon-ai.com", children: "\u2744 Made with Flocon AI" }) })
766
+ ] });
767
+ }
768
+
769
+ // src/metadata.ts
770
+ function getFloconMetadata({ page, url }) {
771
+ const locales = [page.locale, ...page.alternates];
772
+ const languages = Object.fromEntries(
773
+ locales.map((l) => [l, url({ locale: l, path: page.path })])
774
+ );
775
+ if (page.defaultLocale && locales.includes(page.defaultLocale)) {
776
+ languages["x-default"] = languages[page.defaultLocale];
777
+ }
778
+ const canonical = url({ locale: page.locale, path: page.path });
779
+ return {
780
+ title: page.seo.title,
781
+ description: page.seo.description,
782
+ keywords: page.seo.keywords,
783
+ canonical,
784
+ /** hreflang: locale (or "x-default") → URL. */
785
+ languages,
786
+ openGraph: {
787
+ type: "article",
788
+ title: page.seo.title,
789
+ description: page.seo.description,
790
+ url: canonical,
791
+ locale: page.locale
792
+ },
793
+ twitter: { card: "summary_large_image", title: page.seo.title, description: page.seo.description }
794
+ };
795
+ }
796
+ // Annotate the CommonJS export names for ESM import in node:
797
+ 0 && (module.exports = {
798
+ FloconPage,
799
+ createFloconClient,
800
+ floconLlmsTxt,
801
+ floconSitemap,
802
+ getAllPages,
803
+ getFloconMetadata,
804
+ getPage
805
+ });