fumapress 0.5.4 → 0.5.5
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/css/generated.css +3 -0
- package/dist/components/blog.js +1 -1
- package/dist/components/flexsearch-static.js +5 -1
- package/dist/components/image.js +4 -3
- package/dist/components/orama-search-static.js +3 -1
- package/dist/layouts/blog.index.js +1 -1
- package/dist/layouts/blog.js +1 -1
- package/dist/lib/pathname.js +9 -2
- package/dist/plugins/blog.js +1 -1
- package/dist/plugins/image/cloudflare.client.js +1 -1
- package/dist/plugins/image/self-hosted.client.js +2 -1
- package/dist/plugins/image/self-hosted.utils.js +2 -2
- package/dist/plugins/openapi.js +8 -3
- package/package.json +1 -1
package/css/generated.css
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
@source inline("@orama/orama");
|
|
7
7
|
@source inline("a");
|
|
8
8
|
@source inline("above");
|
|
9
|
+
@source inline("absolute");
|
|
9
10
|
@source inline("absolutePath");
|
|
10
11
|
@source inline("accepts");
|
|
11
12
|
@source inline("active:scale-95");
|
|
@@ -374,6 +375,7 @@
|
|
|
374
375
|
@source inline("requests");
|
|
375
376
|
@source inline("resolution");
|
|
376
377
|
@source inline("resolve");
|
|
378
|
+
@source inline("resolveBaseUrl");
|
|
377
379
|
@source inline("resolved");
|
|
378
380
|
@source inline("rest");
|
|
379
381
|
@source inline("result");
|
|
@@ -512,6 +514,7 @@
|
|
|
512
514
|
@source inline("width");
|
|
513
515
|
@source inline("widths");
|
|
514
516
|
@source inline("will");
|
|
517
|
+
@source inline("with");
|
|
515
518
|
@source inline("without");
|
|
516
519
|
@source inline("would");
|
|
517
520
|
@source inline("wrapper");
|
package/dist/components/blog.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Link } from "./link.js";
|
|
2
|
+
import { joinPathname } from "../lib/pathname.js";
|
|
2
3
|
import { getCreationDate, getPressContext } from "../lib/shared.js";
|
|
3
4
|
import { cn } from "../lib/cn.js";
|
|
4
5
|
import { I18nLabel } from "./i18n.js";
|
|
5
|
-
import { joinPathname } from "../lib/pathname.js";
|
|
6
6
|
import { getBlogContext } from "../plugins/blog.js";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { CornerLeftUpIcon } from "lucide-react";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { resolveBaseUrl } from "../lib/pathname.js";
|
|
2
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
import { useI18n } from "fumadocs-ui/contexts/i18n";
|
|
4
5
|
import { SearchDialog, SearchDialogClose, SearchDialogContent, SearchDialogHeader, SearchDialogIcon, SearchDialogInput, SearchDialogList, SearchDialogOverlay } from "fumadocs-ui/components/dialog/search";
|
|
@@ -7,7 +8,10 @@ import { flexsearchStaticClient } from "fumadocs-core/search/client/flexsearch-s
|
|
|
7
8
|
//#region src/components/flexsearch-static.tsx
|
|
8
9
|
function DefaultSearchDialog(props) {
|
|
9
10
|
const { locale } = useI18n();
|
|
10
|
-
const { search, setSearch, query } = useDocsSearch({ client: flexsearchStaticClient({
|
|
11
|
+
const { search, setSearch, query } = useDocsSearch({ client: flexsearchStaticClient({
|
|
12
|
+
locale,
|
|
13
|
+
from: resolveBaseUrl(import.meta.env.BASE_URL, "/api/search")
|
|
14
|
+
}) });
|
|
11
15
|
return /* @__PURE__ */ jsxs(SearchDialog, {
|
|
12
16
|
search,
|
|
13
17
|
onSearchChange: setSearch,
|
package/dist/components/image.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { resolveBaseUrl } from "../lib/pathname.js";
|
|
2
3
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
import { createContext, use, useMemo } from "react";
|
|
4
5
|
import ReactDOM from "react-dom";
|
|
@@ -11,14 +12,14 @@ function parseLength(v) {
|
|
|
11
12
|
return parsed;
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
|
-
* resolve src to a full pathname
|
|
15
|
+
* resolve src to a full pathname with base URL included (or keep absolute URLs as-is)
|
|
15
16
|
*/
|
|
16
17
|
function normalizeSrc(src, basePathname) {
|
|
17
|
-
if (src.startsWith("http://") || src.startsWith("https://")) return src;
|
|
18
|
+
if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("data:")) return src;
|
|
18
19
|
const base = new URL(basePathname, "http://localhost");
|
|
19
20
|
const resolved = new URL(src, base);
|
|
20
21
|
if (resolved.hostname !== base.hostname) throw new Error(`The src attribute "${src}" is not a valid relative path`);
|
|
21
|
-
return resolved.pathname;
|
|
22
|
+
return resolveBaseUrl(import.meta.env.BASE_URL, resolved.pathname);
|
|
22
23
|
}
|
|
23
24
|
const ImageContext = createContext(null);
|
|
24
25
|
function ImageProvider({ provider, children }) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { resolveBaseUrl } from "../lib/pathname.js";
|
|
2
3
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
import { useI18n } from "fumadocs-ui/contexts/i18n";
|
|
4
5
|
import { SearchDialog, SearchDialogClose, SearchDialogContent, SearchDialogHeader, SearchDialogIcon, SearchDialogInput, SearchDialogList, SearchDialogOverlay } from "fumadocs-ui/components/dialog/search";
|
|
@@ -16,7 +17,8 @@ function DefaultSearchDialog(props) {
|
|
|
16
17
|
const { search, setSearch, query } = useDocsSearch({
|
|
17
18
|
type: "static",
|
|
18
19
|
initOrama,
|
|
19
|
-
locale
|
|
20
|
+
locale,
|
|
21
|
+
from: resolveBaseUrl(import.meta.env.BASE_URL, "/api/search")
|
|
20
22
|
});
|
|
21
23
|
return /* @__PURE__ */ jsxs(SearchDialog, {
|
|
22
24
|
search,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Link } from "../components/link.js";
|
|
2
|
+
import { joinPathname } from "../lib/pathname.js";
|
|
2
3
|
import { getPressContext } from "../lib/shared.js";
|
|
3
4
|
import { cn } from "../lib/cn.js";
|
|
4
5
|
import { I18nLabel } from "../components/i18n.js";
|
|
5
|
-
import { joinPathname } from "../lib/pathname.js";
|
|
6
6
|
import { getBlogContext } from "../plugins/blog.js";
|
|
7
7
|
import { OrderedBlogGrid } from "../components/blog.js";
|
|
8
8
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
package/dist/layouts/blog.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Link } from "../components/link.js";
|
|
2
|
+
import { joinPathname } from "../lib/pathname.js";
|
|
2
3
|
import { getCreationDate, getPressContext, renderBody, renderPageMeta, renderToc } from "../lib/shared.js";
|
|
3
4
|
import { BlogPanel, BlogProvider } from "../components/blog-panel.js";
|
|
4
5
|
import { getTags } from "../lib/shared/blog.js";
|
|
5
|
-
import { joinPathname } from "../lib/pathname.js";
|
|
6
6
|
import { createHomeLayout } from "./home.js";
|
|
7
7
|
import { getBlogContext } from "../plugins/blog.js";
|
|
8
8
|
import { LinkToHome } from "../components/blog.js";
|
package/dist/lib/pathname.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
//#region src/lib/pathname.ts
|
|
2
|
+
/** Join multiple (full) pathnames */
|
|
2
3
|
function joinPathname(...paths) {
|
|
3
4
|
const segs = [];
|
|
4
5
|
for (let p of paths) {
|
|
@@ -10,8 +11,14 @@ function joinPathname(...paths) {
|
|
|
10
11
|
}
|
|
11
12
|
const PATHNAME_SEGMENT_REGEX = /^[A-Za-z0-9\-._~!$&'()*+,;=:@]+$/;
|
|
12
13
|
/** Check if the string is a full pathname (one that does not include `.` or `..`) */
|
|
13
|
-
function
|
|
14
|
+
function isFullPathname(s) {
|
|
14
15
|
return s.startsWith("/") && s.slice(1).split("/").every((seg) => seg !== "." && seg !== ".." && PATHNAME_SEGMENT_REGEX.test(seg));
|
|
15
16
|
}
|
|
17
|
+
/** add base URL to pathname */
|
|
18
|
+
function resolveBaseUrl(base, pathname) {
|
|
19
|
+
if (base.endsWith("/")) base = base.slice(0, -1);
|
|
20
|
+
if (pathname.startsWith("/")) pathname = pathname.slice(1);
|
|
21
|
+
return `${base}/${pathname}`;
|
|
22
|
+
}
|
|
16
23
|
//#endregion
|
|
17
|
-
export {
|
|
24
|
+
export { isFullPathname, joinPathname, resolveBaseUrl };
|
package/dist/plugins/blog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { groupTags, groupTagsI18n } from "../lib/shared/blog.js";
|
|
2
1
|
import { joinPathname } from "../lib/pathname.js";
|
|
2
|
+
import { groupTags, groupTagsI18n } from "../lib/shared/blog.js";
|
|
3
3
|
import { createBlogLayout, createBlogLayoutPage } from "../layouts/blog.js";
|
|
4
4
|
import { createBlogTagPage, createBlogTagsPage } from "../layouts/blog.tags.js";
|
|
5
5
|
import { createBlogIndexPage } from "../layouts/blog.index.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { ImageProvider } from "../../components/image.js";
|
|
3
2
|
import { joinPathname } from "../../lib/pathname.js";
|
|
3
|
+
import { ImageProvider } from "../../components/image.js";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
import { useMemo } from "react";
|
|
6
6
|
//#region src/plugins/image/cloudflare.client.tsx
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { resolveBaseUrl } from "../../lib/pathname.js";
|
|
2
3
|
import { ImageProvider } from "../../components/image.js";
|
|
3
4
|
import { validateImageSrc } from "./self-hosted.utils.js";
|
|
4
5
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -16,7 +17,7 @@ function createProvider(config) {
|
|
|
16
17
|
width: String(width),
|
|
17
18
|
quality: String(quality)
|
|
18
19
|
});
|
|
19
|
-
return `${config.path}?${params.toString()}`;
|
|
20
|
+
return `${resolveBaseUrl(import.meta.env.BASE_URL, config.path)}?${params.toString()}`;
|
|
20
21
|
},
|
|
21
22
|
validate(src) {
|
|
22
23
|
if (import.meta.env.DEV) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __toESM } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
-
import {
|
|
2
|
+
import { isFullPathname } from "../../lib/pathname.js";
|
|
3
3
|
import { require_http_cache_semantics } from "../../node_modules/.pnpm/http-cache-semantics@4.2.0/node_modules/http-cache-semantics/index.js";
|
|
4
4
|
//#region src/plugins/image/self-hosted.utils.ts
|
|
5
5
|
var import_http_cache_semantics = /* @__PURE__ */ __toESM(require_http_cache_semantics(), 1);
|
|
@@ -253,7 +253,7 @@ function validateImageSrc(config, src) {
|
|
|
253
253
|
};
|
|
254
254
|
return { allowed: true };
|
|
255
255
|
}
|
|
256
|
-
if (
|
|
256
|
+
if (isFullPathname(src)) return { allowed: true };
|
|
257
257
|
return {
|
|
258
258
|
allowed: false,
|
|
259
259
|
reason: `Image URL "${src}" is not normalized`
|
package/dist/plugins/openapi.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isFullPathname, resolveBaseUrl } from "../lib/pathname.js";
|
|
2
2
|
import { PayloadProvider, WithPayload } from "../components/openapi.payload.js";
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { openapiTranslations } from "fumadocs-openapi/i18n";
|
|
@@ -16,9 +16,14 @@ function openapiPlugin(options) {
|
|
|
16
16
|
}
|
|
17
17
|
async function ServerPayloadProvider({ children }) {
|
|
18
18
|
const payload = {};
|
|
19
|
+
let clientProxyUrl;
|
|
20
|
+
if (typeof server.options.proxyUrl === "string") {
|
|
21
|
+
const proxyUrl = server.options.proxyUrl;
|
|
22
|
+
clientProxyUrl = isFullPathname(proxyUrl) ? resolveBaseUrl(import.meta.env.BASE_URL, proxyUrl) : proxyUrl;
|
|
23
|
+
}
|
|
19
24
|
for (const [schemaId, schema] of Object.entries(await server.getSchemas())) payload[schemaId] = {
|
|
20
25
|
bundled: schema.bundled,
|
|
21
|
-
proxyUrl:
|
|
26
|
+
proxyUrl: clientProxyUrl
|
|
22
27
|
};
|
|
23
28
|
return /* @__PURE__ */ jsx(PayloadProvider, {
|
|
24
29
|
payload: JSON.stringify(payload),
|
|
@@ -46,7 +51,7 @@ function openapiPlugin(options) {
|
|
|
46
51
|
},
|
|
47
52
|
async createPages({ createApi }) {
|
|
48
53
|
const proxyUrl = server.options.proxyUrl;
|
|
49
|
-
const { createProxy = typeof proxyUrl === "string" &&
|
|
54
|
+
const { createProxy = typeof proxyUrl === "string" && isFullPathname(proxyUrl) } = options;
|
|
50
55
|
if (createProxy) {
|
|
51
56
|
if (!proxyUrl) throw new Error(`[Fumapress] The "proxyUrl" option in createOpenAPI() is required to create proxy server`);
|
|
52
57
|
if (this.mode === "static") throw new Error(`[Fumapress] static mode is not compatible with proxy server`);
|