@fecommunity/reactpress-toolkit 3.1.0 → 4.0.0-beta.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/LICENSE +21 -0
- package/dist/.source-fingerprint-toolkit +1 -0
- package/dist/app/createReactPressApp.d.ts +4 -84
- package/dist/app/createReactPressApp.js +3 -0
- package/dist/app/createThemeApp.d.ts +8 -6
- package/dist/app/createThemeApp.js +5 -1
- package/dist/plugin/admin/index.d.ts +2 -0
- package/dist/plugin/admin/index.js +2 -0
- package/dist/plugin/admin/plugin-admin.d.ts +43 -0
- package/dist/plugin/admin/plugin-admin.js +41 -0
- package/dist/plugin/admin/slots.d.ts +36 -0
- package/dist/plugin/admin/slots.js +16 -0
- package/dist/plugin/client/runtime.d.ts +6 -1
- package/dist/plugin/extension/index.d.ts +4 -0
- package/dist/plugin/extension/index.js +20 -0
- package/dist/plugin/extension/plugin-admin-locale.d.ts +21 -0
- package/dist/plugin/extension/plugin-admin-locale.io.d.ts +2 -0
- package/dist/plugin/extension/plugin-admin-locale.io.js +54 -0
- package/dist/plugin/extension/plugin-admin-locale.js +60 -0
- package/dist/plugin/extension/plugin.d.ts +82 -0
- package/dist/plugin/extension/plugin.js +146 -0
- package/dist/plugin/extension/security.d.ts +7 -0
- package/dist/plugin/extension/security.js +74 -0
- package/dist/plugin/extension/validate.d.ts +8 -0
- package/dist/plugin/extension/validate.js +55 -0
- package/dist/plugin/index.d.ts +4 -0
- package/dist/plugin/index.js +5 -1
- package/dist/plugin/node.d.ts +2 -0
- package/dist/plugin/node.js +6 -0
- package/dist/plugin/react/index.d.ts +1 -0
- package/dist/plugin/react/index.js +1 -0
- package/dist/plugin/react/plugin-admin-ui.d.ts +23 -0
- package/dist/plugin/react/plugin-admin-ui.js +38 -0
- package/dist/plugin/server/hook-reject.d.ts +12 -0
- package/dist/plugin/server/hook-reject.js +39 -0
- package/dist/plugin/server/index.d.ts +2 -0
- package/dist/plugin/server/index.js +18 -0
- package/dist/plugin/server/types.d.ts +34 -0
- package/dist/plugin/server/types.js +3 -0
- package/dist/theme/build/next-config.d.ts +4 -6
- package/dist/theme/build/next-config.js +0 -37
- package/dist/theme/build/node.d.ts +1 -1
- package/dist/theme/build/node.js +1 -1
- package/dist/theme/content/assets.js +33 -1
- package/dist/theme/extension/theme.d.ts +1 -1
- package/dist/theme/extension/theme.js +1 -1
- package/dist/theme/ssr/fetch.d.ts +3 -0
- package/dist/theme/ssr/pageProps.d.ts +5 -4
- package/dist/theme/ssr/pageProps.js +20 -3
- package/dist/theme/ssr/setting.d.ts +1 -0
- package/dist/theme/ssr/setting.js +3 -0
- package/dist/theme/ssr/templates.js +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/ui/components/SiteAnalytics.d.ts +1 -1
- package/package.json +43 -15
|
@@ -10,9 +10,18 @@ const PUBLIC_PATH_ALIASES = {
|
|
|
10
10
|
'/favicon.png': '/public/favicon.png',
|
|
11
11
|
'/favicon.ico': '/public/favicon.ico',
|
|
12
12
|
};
|
|
13
|
+
/** Theme Next rewrites serve alias keys (e.g. `/logo.png`), not `/public/*` API paths. */
|
|
14
|
+
const THEME_LOCAL_PUBLIC_PATHS = Object.fromEntries(Object.entries(PUBLIC_PATH_ALIASES).map(([themePath, apiPath]) => [apiPath, themePath]));
|
|
13
15
|
function normalizePublicAssetPath(path) {
|
|
14
16
|
return PUBLIC_PATH_ALIASES[path] ?? path;
|
|
15
17
|
}
|
|
18
|
+
function toThemeServablePath(apiPath) {
|
|
19
|
+
return THEME_LOCAL_PUBLIC_PATHS[apiPath] ?? apiPath;
|
|
20
|
+
}
|
|
21
|
+
/** Paths proxied by theme `next.config` rewrites — keep relative, never bake absolute API URLs. */
|
|
22
|
+
function isThemeRewritePath(path) {
|
|
23
|
+
return path in THEME_LOCAL_PUBLIC_PATHS || path.startsWith('/public/') || path.startsWith('/uploads/');
|
|
24
|
+
}
|
|
16
25
|
/** Whether a configured asset path is likely to resolve (skip broken defaults like `/logo.png`). */
|
|
17
26
|
function isLikelyValidAssetPath(url) {
|
|
18
27
|
const trimmed = (url ?? '').trim();
|
|
@@ -44,6 +53,26 @@ function resolvePublicSiteOrigin() {
|
|
|
44
53
|
'http://localhost:3002/api';
|
|
45
54
|
return serverApi.replace(/\/api\/?$/, '').replace(/\/$/, '');
|
|
46
55
|
}
|
|
56
|
+
/** Visitor site origin — differs from API origin during SSR (theme :3001 vs API :3002). */
|
|
57
|
+
function resolveThemeSiteOrigin() {
|
|
58
|
+
if (typeof window !== 'undefined') {
|
|
59
|
+
return window.location.origin;
|
|
60
|
+
}
|
|
61
|
+
const clientSite = process.env.CLIENT_SITE_URL?.trim();
|
|
62
|
+
if (clientSite) {
|
|
63
|
+
try {
|
|
64
|
+
return new URL(clientSite).origin;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return clientSite.replace(/\/$/, '');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const clientPort = process.env.CLIENT_PORT?.trim() || process.env.PORT?.trim();
|
|
71
|
+
if (clientPort) {
|
|
72
|
+
return `http://127.0.0.1:${clientPort}`;
|
|
73
|
+
}
|
|
74
|
+
return resolvePublicSiteOrigin();
|
|
75
|
+
}
|
|
47
76
|
/** Resolve media / logo URLs for theme pages. */
|
|
48
77
|
function resolvePublicAssetUrl(url) {
|
|
49
78
|
const trimmed = (url ?? '').trim();
|
|
@@ -57,8 +86,11 @@ function resolvePublicAssetUrl(url) {
|
|
|
57
86
|
}
|
|
58
87
|
if (trimmed.startsWith('/')) {
|
|
59
88
|
const normalized = normalizePublicAssetPath(trimmed);
|
|
89
|
+
if (isThemeRewritePath(normalized)) {
|
|
90
|
+
return toThemeServablePath(normalized);
|
|
91
|
+
}
|
|
60
92
|
const origin = resolvePublicSiteOrigin();
|
|
61
|
-
const themeOrigin =
|
|
93
|
+
const themeOrigin = resolveThemeSiteOrigin();
|
|
62
94
|
if (origin === themeOrigin) {
|
|
63
95
|
return normalized;
|
|
64
96
|
}
|
|
@@ -71,7 +71,7 @@ export interface SiteThemeState {
|
|
|
71
71
|
mods: Record<string, ThemeMods>;
|
|
72
72
|
previewThemeId?: string;
|
|
73
73
|
}
|
|
74
|
-
export declare const DEFAULT_ACTIVE_THEME = "
|
|
74
|
+
export declare const DEFAULT_ACTIVE_THEME = "hello-world";
|
|
75
75
|
export declare const defaultSiteThemeState: SiteThemeState;
|
|
76
76
|
export interface GlobalSettingWithTheme {
|
|
77
77
|
zh?: unknown;
|
|
@@ -19,7 +19,7 @@ Object.defineProperty(exports, "appearancePrimaryColorForMode", { enumerable: tr
|
|
|
19
19
|
function appearancePrimaryColor(mods, fallback = '#f44336') {
|
|
20
20
|
return (0, twentytwentyfive_vars_1.appearancePrimaryColorForMode)(mods, false, fallback);
|
|
21
21
|
}
|
|
22
|
-
exports.DEFAULT_ACTIVE_THEME = '
|
|
22
|
+
exports.DEFAULT_ACTIVE_THEME = 'hello-world';
|
|
23
23
|
exports.defaultSiteThemeState = {
|
|
24
24
|
activeTheme: exports.DEFAULT_ACTIVE_THEME,
|
|
25
25
|
installedThemes: [exports.DEFAULT_ACTIVE_THEME],
|
|
@@ -73,7 +73,10 @@ export declare function fetchTagArchive(api: ThemeApi, tag: string): Promise<{
|
|
|
73
73
|
export type ThemeArticlePage = {
|
|
74
74
|
id: string;
|
|
75
75
|
title: string;
|
|
76
|
+
slug?: string;
|
|
76
77
|
summary?: string;
|
|
78
|
+
seoDescription?: string;
|
|
79
|
+
seoKeywords?: string;
|
|
77
80
|
html?: string;
|
|
78
81
|
cover?: string;
|
|
79
82
|
publishAt?: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ThemeApi } from '../api/api';
|
|
2
2
|
import { type CarouselArticle, type ListArticle } from '../content/articleSlim';
|
|
3
3
|
import { type ArchiveTree } from '../content/archiveSlim';
|
|
4
|
-
import type { IArticle, ICategory, IKnowledge, ITag } from '../../types';
|
|
4
|
+
import type { IArticle, ICategory, IKnowledge, IPage, ITag } from '../../types';
|
|
5
5
|
export type HomePageProps = {
|
|
6
6
|
articles: ListArticle[];
|
|
7
7
|
total: number;
|
|
@@ -52,9 +52,10 @@ export declare function fetchKnowledgeChapterPageProps(api: ThemeApi, pId: strin
|
|
|
52
52
|
}>;
|
|
53
53
|
/** Site search results for `/search?keyword=`. */
|
|
54
54
|
export declare function fetchSearchPageProps(api: ThemeApi, keyword: string): Promise<SearchPageProps>;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
export type CmsPageProps = Pick<IPage, 'id' | 'name' | 'path' | 'html' | 'toc' | 'status' | 'publishAt' | 'views'>;
|
|
56
|
+
/** CMS static page by id or path slug (admin → 页面). */
|
|
57
|
+
export declare function fetchCmsPageProps(api: ThemeApi, idOrPath: string | undefined): Promise<{
|
|
58
|
+
page: CmsPageProps | null;
|
|
58
59
|
}>;
|
|
59
60
|
/** Single article by id (full entity from API). */
|
|
60
61
|
export declare function fetchArticleDetailProps(api: ThemeApi, id: string): Promise<{
|
|
@@ -15,6 +15,7 @@ const api_data_1 = require("../api/api-data");
|
|
|
15
15
|
const articleSlim_1 = require("../content/articleSlim");
|
|
16
16
|
const archiveSlim_1 = require("../content/archiveSlim");
|
|
17
17
|
const carouselArticles_1 = require("../content/carouselArticles");
|
|
18
|
+
const assets_1 = require("../content/assets");
|
|
18
19
|
const fetch_1 = require("./fetch");
|
|
19
20
|
const DEFAULT_PAGE_SIZE = 12;
|
|
20
21
|
function fallbackCategory(value) {
|
|
@@ -128,9 +129,25 @@ async function fetchSearchPageProps(api, keyword) {
|
|
|
128
129
|
const articles = (0, api_data_1.unpackList)(response).filter((article) => article.status === 'publish');
|
|
129
130
|
return { keyword: trimmed, articles };
|
|
130
131
|
}
|
|
131
|
-
/** CMS static page by id. */
|
|
132
|
-
async function fetchCmsPageProps(api,
|
|
133
|
-
|
|
132
|
+
/** CMS static page by id or path slug (admin → 页面). */
|
|
133
|
+
async function fetchCmsPageProps(api, idOrPath) {
|
|
134
|
+
if (!idOrPath?.trim())
|
|
135
|
+
return { page: null };
|
|
136
|
+
const raw = (0, api_data_1.unpackOne)(await api.page.findById(idOrPath.trim()));
|
|
137
|
+
if (!raw || raw.status !== 'publish')
|
|
138
|
+
return { page: null };
|
|
139
|
+
return {
|
|
140
|
+
page: {
|
|
141
|
+
id: raw.id,
|
|
142
|
+
name: raw.name,
|
|
143
|
+
path: raw.path,
|
|
144
|
+
html: raw.html ? (0, assets_1.rewriteArticleHtmlAssets)(raw.html) : raw.html,
|
|
145
|
+
toc: raw.toc,
|
|
146
|
+
status: raw.status,
|
|
147
|
+
publishAt: raw.publishAt,
|
|
148
|
+
views: raw.views,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
134
151
|
}
|
|
135
152
|
/** Single article by id (full entity from API). */
|
|
136
153
|
async function fetchArticleDetailProps(api, id) {
|
|
@@ -31,6 +31,9 @@ function parseSiteMeta(row) {
|
|
|
31
31
|
siteName: String(row.systemTitle ?? 'ReactPress Site').trim() || exports.DEFAULT_SITE_META.siteName,
|
|
32
32
|
siteDescription: String(row.systemSubTitle ?? exports.DEFAULT_SITE_META.siteDescription).trim() ||
|
|
33
33
|
exports.DEFAULT_SITE_META.siteDescription,
|
|
34
|
+
siteKeywords: row.seoKeyword != null && String(row.seoKeyword).trim()
|
|
35
|
+
? String(row.seoKeyword).trim()
|
|
36
|
+
: undefined,
|
|
34
37
|
siteUrl: row.systemUrl != null ? String(row.systemUrl).trim() || undefined : undefined,
|
|
35
38
|
siteLogo: row.systemLogo != null && String(row.systemLogo).trim()
|
|
36
39
|
? String(row.systemLogo).trim()
|
|
@@ -34,7 +34,7 @@ exports.ThemeTemplate = {
|
|
|
34
34
|
exports.DEFAULT_TEMPLATE_FILES = {
|
|
35
35
|
[exports.ThemeTemplate.HOME]: 'pages/index.tsx',
|
|
36
36
|
[exports.ThemeTemplate.SINGLE]: 'pages/article/[id].tsx',
|
|
37
|
-
[exports.ThemeTemplate.PAGE]: 'pages/
|
|
37
|
+
[exports.ThemeTemplate.PAGE]: 'pages/[path].tsx',
|
|
38
38
|
[exports.ThemeTemplate.ARCHIVE_CATEGORY]: 'pages/category/[category].tsx',
|
|
39
39
|
[exports.ThemeTemplate.ARCHIVE_TAG]: 'pages/tag/[tag].tsx',
|
|
40
40
|
[exports.ThemeTemplate.SEARCH]: 'pages/search.tsx',
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export interface SiteAnalyticsProps {
|
|
|
2
2
|
children?: React.ReactNode;
|
|
3
3
|
}
|
|
4
4
|
/** Inject Google Analytics / Baidu Tongji scripts from site settings. */
|
|
5
|
-
export declare function SiteAnalytics({ children }: SiteAnalyticsProps): string | number | boolean | import("react").ReactElement<
|
|
5
|
+
export declare function SiteAnalytics({ children }: SiteAnalyticsProps): string | number | bigint | boolean | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | import("react").ReactPortal | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<import("react").ReactNode> | null | undefined> | null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fecommunity/reactpress-toolkit",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0-beta.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -79,6 +79,18 @@
|
|
|
79
79
|
"./plugin/dev": {
|
|
80
80
|
"types": "./dist/plugin/dev/index.d.ts",
|
|
81
81
|
"default": "./dist/plugin/dev/index.js"
|
|
82
|
+
},
|
|
83
|
+
"./plugin/extension": {
|
|
84
|
+
"types": "./dist/plugin/extension/index.d.ts",
|
|
85
|
+
"default": "./dist/plugin/extension/index.js"
|
|
86
|
+
},
|
|
87
|
+
"./plugin/server": {
|
|
88
|
+
"types": "./dist/plugin/server/index.d.ts",
|
|
89
|
+
"default": "./dist/plugin/server/index.js"
|
|
90
|
+
},
|
|
91
|
+
"./plugin/node": {
|
|
92
|
+
"types": "./dist/plugin/node.d.ts",
|
|
93
|
+
"default": "./dist/plugin/node.js"
|
|
82
94
|
}
|
|
83
95
|
},
|
|
84
96
|
"peerDependencies": {
|
|
@@ -92,19 +104,30 @@
|
|
|
92
104
|
"viewerjs": ">=1"
|
|
93
105
|
},
|
|
94
106
|
"peerDependenciesMeta": {
|
|
95
|
-
"@tanstack/react-query": {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
"
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
"
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
"
|
|
107
|
+
"@tanstack/react-query": {
|
|
108
|
+
"optional": true
|
|
109
|
+
},
|
|
110
|
+
"@ant-design/cssinjs": {
|
|
111
|
+
"optional": true
|
|
112
|
+
},
|
|
113
|
+
"highlight.js": {
|
|
114
|
+
"optional": true
|
|
115
|
+
},
|
|
116
|
+
"next": {
|
|
117
|
+
"optional": true
|
|
118
|
+
},
|
|
119
|
+
"nprogress": {
|
|
120
|
+
"optional": true
|
|
121
|
+
},
|
|
122
|
+
"react": {
|
|
123
|
+
"optional": true
|
|
124
|
+
},
|
|
125
|
+
"react-dom": {
|
|
126
|
+
"optional": true
|
|
127
|
+
},
|
|
128
|
+
"viewerjs": {
|
|
129
|
+
"optional": true
|
|
130
|
+
}
|
|
108
131
|
},
|
|
109
132
|
"files": [
|
|
110
133
|
"dist"
|
|
@@ -145,5 +168,10 @@
|
|
|
145
168
|
"react": "^18.3.1",
|
|
146
169
|
"react-dom": "^18.3.1",
|
|
147
170
|
"typescript": "^5.7.3"
|
|
171
|
+
},
|
|
172
|
+
"scripts": {
|
|
173
|
+
"generate": "node scripts/generate-swagger.js",
|
|
174
|
+
"build": "tsc && rm -rf dist/config/locales && cp -r src/config/locales dist/config/locales",
|
|
175
|
+
"typecheck": "tsc --noEmit"
|
|
148
176
|
}
|
|
149
|
-
}
|
|
177
|
+
}
|