@fecommunity/reactpress-toolkit 3.1.0 → 3.7.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.
Files changed (68) hide show
  1. package/LICENSE +21 -0
  2. package/dist/.source-fingerprint-toolkit +1 -0
  3. package/dist/app/createReactPressApp.d.ts +4 -84
  4. package/dist/app/createReactPressApp.js +3 -0
  5. package/dist/app/createThemeApp.d.ts +8 -6
  6. package/dist/app/createThemeApp.js +5 -1
  7. package/dist/plugin/admin/plugin-admin.d.ts +37 -0
  8. package/dist/plugin/admin/plugin-admin.js +41 -0
  9. package/dist/plugin/admin/slots.d.ts +36 -0
  10. package/dist/plugin/admin/slots.js +16 -0
  11. package/dist/plugin/extension/index.d.ts +4 -0
  12. package/dist/plugin/extension/index.js +20 -0
  13. package/dist/plugin/extension/plugin-admin-locale.d.ts +21 -0
  14. package/dist/plugin/extension/plugin-admin-locale.io.d.ts +2 -0
  15. package/dist/plugin/extension/plugin-admin-locale.io.js +54 -0
  16. package/dist/plugin/extension/plugin-admin-locale.js +60 -0
  17. package/dist/plugin/extension/plugin.d.ts +82 -0
  18. package/dist/plugin/extension/plugin.js +146 -0
  19. package/dist/plugin/extension/security.d.ts +7 -0
  20. package/dist/plugin/extension/security.js +74 -0
  21. package/dist/plugin/extension/validate.d.ts +8 -0
  22. package/dist/plugin/extension/validate.js +55 -0
  23. package/dist/plugin/node.d.ts +2 -0
  24. package/dist/plugin/node.js +6 -0
  25. package/dist/plugin/react/plugin-admin-ui.d.ts +23 -0
  26. package/dist/plugin/react/plugin-admin-ui.js +38 -0
  27. package/dist/plugin/server/hook-reject.d.ts +12 -0
  28. package/dist/plugin/server/hook-reject.js +39 -0
  29. package/dist/plugin/server/index.d.ts +2 -0
  30. package/dist/plugin/server/index.js +18 -0
  31. package/dist/plugin/server/types.d.ts +34 -0
  32. package/dist/plugin/server/types.js +3 -0
  33. package/dist/theme/build/next-config.d.ts +4 -6
  34. package/dist/theme/build/next-config.js +0 -37
  35. package/dist/theme/build/node.d.ts +1 -1
  36. package/dist/theme/build/node.js +1 -1
  37. package/dist/ui/components/ArchiveEmptyState.d.ts +1 -1
  38. package/dist/ui/components/ArchivePageLayout.d.ts +1 -1
  39. package/dist/ui/components/ArticleCard.d.ts +1 -1
  40. package/dist/ui/components/ArticleList.d.ts +1 -1
  41. package/dist/ui/components/BaseGlobalStyles.d.ts +2 -1
  42. package/dist/ui/components/LocaleSwitcher.d.ts +1 -1
  43. package/dist/ui/components/NavMenu.d.ts +1 -1
  44. package/dist/ui/components/NotFoundPanel.d.ts +1 -1
  45. package/dist/ui/components/PageHeader.d.ts +1 -1
  46. package/dist/ui/components/SiteBranding.d.ts +2 -1
  47. package/dist/ui/components/SiteDocument.d.ts +1 -1
  48. package/dist/ui/components/SiteDocumentFallback.d.ts +1 -1
  49. package/dist/ui/components/SiteLogo.d.ts +2 -1
  50. package/dist/ui/components/SiteSeo.d.ts +1 -1
  51. package/dist/ui/components/SiteTagline.d.ts +2 -1
  52. package/dist/ui/components/TaxonomyList.d.ts +1 -1
  53. package/dist/ui/components/ThemeCssVars.d.ts +2 -1
  54. package/dist/ui/components/ThemeLayout.d.ts +1 -1
  55. package/dist/ui/components/content/ArticleReader.d.ts +1 -1
  56. package/dist/ui/components/content/ArticleToc.d.ts +1 -1
  57. package/dist/ui/components/content/HtmlContent.d.ts +2 -1
  58. package/dist/ui/components/content/Image.d.ts +1 -1
  59. package/dist/ui/components/content/LocaleTime.d.ts +2 -1
  60. package/dist/ui/components/toolbar/LocaleToggleButton.d.ts +1 -1
  61. package/dist/ui/components/toolbar/ThemeToggleButton.d.ts +1 -1
  62. package/dist/ui/components/toolbar/ToolbarIconButton.d.ts +1 -1
  63. package/dist/ui/components/toolbar/icons.d.ts +7 -7
  64. package/dist/ui/context/LocaleContext.d.ts +1 -1
  65. package/dist/ui/context/ReactPressProvider.d.ts +2 -1
  66. package/dist/ui/context/SiteCatalogContext.d.ts +1 -1
  67. package/dist/ui/context/ThemeRuntimeContext.d.ts +1 -1
  68. package/package.json +31 -15
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024–2026 fecommunity
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ fd5270adee7bc50a2dc021d6042bae6d01a27818a2f651724412ac8c6e1ecc14
@@ -1,88 +1,8 @@
1
1
  /**
2
2
  * Full-featured theme `_app` factory (UI-framework agnostic).
3
3
  * Alias: `createCatalogThemeApp` (deprecated name).
4
+ * @param {Record<string, unknown>} manifest
5
+ * @param {Record<string, unknown>} [options]
6
+ * @returns {unknown}
4
7
  */
5
- export function createReactPressApp(manifest: any, options?: {}): {
6
- new (props: any): {
7
- state: {
8
- locale: string;
9
- user: null;
10
- /** Keep SSR and the first client render identical; sync from storage in componentDidMount. */
11
- theme: string;
12
- collapsed: boolean;
13
- setting: null;
14
- /** Full locale catalog — SSR may ship only the active locale to shrink `__NEXT_DATA__`. */
15
- i18n: null;
16
- };
17
- prefetchRemainingI18nLocales: () => void;
18
- changeLocale: (key: any) => void;
19
- setUser: (user: any) => void;
20
- removeUser: () => void;
21
- changeTheme: (nextTheme: any) => void;
22
- getSetting: () => void;
23
- toggleCollapse: () => void;
24
- componentDidMount(): void;
25
- componentDidUpdate(_prevProps: any, prevState: any): void;
26
- render(): React.DetailedReactHTMLElement<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
27
- context: unknown;
28
- setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
29
- forceUpdate(callback?: (() => void) | undefined): void;
30
- readonly props: Readonly<any>;
31
- refs: {
32
- [key: string]: React.ReactInstance;
33
- };
34
- shouldComponentUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): boolean;
35
- componentWillUnmount?(): void;
36
- componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
37
- getSnapshotBeforeUpdate?(prevProps: Readonly<any>, prevState: Readonly<any>): any;
38
- componentWillMount?(): void;
39
- UNSAFE_componentWillMount?(): void;
40
- componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
41
- UNSAFE_componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
42
- componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
43
- UNSAFE_componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
44
- };
45
- new (props: any, context: any): {
46
- state: {
47
- locale: string;
48
- user: null;
49
- /** Keep SSR and the first client render identical; sync from storage in componentDidMount. */
50
- theme: string;
51
- collapsed: boolean;
52
- setting: null;
53
- /** Full locale catalog — SSR may ship only the active locale to shrink `__NEXT_DATA__`. */
54
- i18n: null;
55
- };
56
- prefetchRemainingI18nLocales: () => void;
57
- changeLocale: (key: any) => void;
58
- setUser: (user: any) => void;
59
- removeUser: () => void;
60
- changeTheme: (nextTheme: any) => void;
61
- getSetting: () => void;
62
- toggleCollapse: () => void;
63
- componentDidMount(): void;
64
- componentDidUpdate(_prevProps: any, prevState: any): void;
65
- render(): React.DetailedReactHTMLElement<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>;
66
- context: unknown;
67
- setState<K extends string | number | symbol>(state: any, callback?: (() => void) | undefined): void;
68
- forceUpdate(callback?: (() => void) | undefined): void;
69
- readonly props: Readonly<any>;
70
- refs: {
71
- [key: string]: React.ReactInstance;
72
- };
73
- shouldComponentUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): boolean;
74
- componentWillUnmount?(): void;
75
- componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
76
- getSnapshotBeforeUpdate?(prevProps: Readonly<any>, prevState: Readonly<any>): any;
77
- componentWillMount?(): void;
78
- UNSAFE_componentWillMount?(): void;
79
- componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
80
- UNSAFE_componentWillReceiveProps?(nextProps: Readonly<any>, nextContext: any): void;
81
- componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
82
- UNSAFE_componentWillUpdate?(nextProps: Readonly<any>, nextState: Readonly<any>, nextContext: any): void;
83
- };
84
- getInitialProps: (appContext: any) => Promise<any>;
85
- origGetInitialProps: ({ Component, ctx, }: import("next/app").AppContext) => Promise<import("next/app").AppInitialProps>;
86
- contextType?: React.Context<any> | undefined;
87
- };
88
- import React = require("react");
8
+ export function createReactPressApp(manifest: Record<string, unknown>, options?: Record<string, unknown>): unknown;
@@ -44,6 +44,9 @@ function ViewStatisticsBridge() {
44
44
  /**
45
45
  * Full-featured theme `_app` factory (UI-framework agnostic).
46
46
  * Alias: `createCatalogThemeApp` (deprecated name).
47
+ * @param {Record<string, unknown>} manifest
48
+ * @param {Record<string, unknown>} [options]
49
+ * @returns {unknown}
47
50
  */
48
51
  function createReactPressApp(manifest, options = {}) {
49
52
  var _a;
@@ -1,6 +1,8 @@
1
- /** Minimal theme `_app` — hello-world style, ReactPressProvider + ThemeCssVars only. */
2
- export function createThemeApp(manifest: any): ({ Component, pageProps }: {
3
- Component: any;
4
- pageProps: any;
5
- }) => React.FunctionComponentElement<import("../ui").ReactPressProviderProps>;
6
- import React = require("react");
1
+ /**
2
+ * Minimal theme `_app` — hello-world style, ReactPressProvider + ThemeCssVars only.
3
+ * @param {{ id: string }} manifest
4
+ * @returns {unknown}
5
+ */
6
+ export function createThemeApp(manifest: {
7
+ id: string;
8
+ }): unknown;
@@ -12,7 +12,11 @@ function readPreviewTokenFromBrowser() {
12
12
  return '';
13
13
  return new URLSearchParams(window.location.search).get(PREVIEW_TOKEN_QUERY_KEY)?.trim() ?? '';
14
14
  }
15
- /** Minimal theme `_app` — hello-world style, ReactPressProvider + ThemeCssVars only. */
15
+ /**
16
+ * Minimal theme `_app` — hello-world style, ReactPressProvider + ThemeCssVars only.
17
+ * @param {{ id: string }} manifest
18
+ * @returns {unknown}
19
+ */
16
20
  function createThemeApp(manifest) {
17
21
  function ThemeApp({ Component, pageProps }) {
18
22
  const { reactPress, ...rest } = pageProps;
@@ -0,0 +1,37 @@
1
+ import type { AdminSlotId } from './slots';
2
+ export interface PluginAdminContext {
3
+ id: string;
4
+ config: Record<string, unknown>;
5
+ }
6
+ /** Plugin admin entry — called once per active plugin when admin shell loads. */
7
+ export interface PluginAdminModule {
8
+ registerAdmin(registry: PluginAdminRegistry, ctx: PluginAdminContext): void | Promise<void>;
9
+ }
10
+ /** Opaque component type — React `ComponentType` lives in `@fecommunity/reactpress-toolkit/plugin/react`. */
11
+ export type PluginAdminSlotComponent = (props: PluginAdminSlotComponentProps<unknown>) => unknown;
12
+ export interface PluginAdminSlotComponentProps<TContext = unknown> {
13
+ context: TContext;
14
+ pluginId: string;
15
+ config: Record<string, unknown>;
16
+ }
17
+ export interface PluginAdminSlotContribution {
18
+ pluginId: string;
19
+ slot: AdminSlotId;
20
+ priority: number;
21
+ Component: PluginAdminSlotComponent;
22
+ }
23
+ export interface PluginAdminRegistry {
24
+ registerSlot<TContext = unknown>(slot: AdminSlotId, component: (props: PluginAdminSlotComponentProps<TContext>) => unknown, options?: {
25
+ priority?: number;
26
+ }): void;
27
+ }
28
+ export interface PluginAdminSlotHost {
29
+ registerSlot<TContext = unknown>(pluginId: string, slot: AdminSlotId, component: (props: PluginAdminSlotComponentProps<TContext>) => unknown, options?: {
30
+ priority?: number;
31
+ }): void;
32
+ getContributions(slot: AdminSlotId): PluginAdminSlotContribution[];
33
+ reset(): void;
34
+ }
35
+ export declare function createPluginAdminSlotHost(): PluginAdminSlotHost;
36
+ /** Registry passed to `registerAdmin` — scopes contributions to one plugin id. */
37
+ export declare function createPluginAdminRegistry(pluginId: string, host: PluginAdminSlotHost): PluginAdminRegistry;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createPluginAdminSlotHost = createPluginAdminSlotHost;
4
+ exports.createPluginAdminRegistry = createPluginAdminRegistry;
5
+ function createPluginAdminSlotHost() {
6
+ const contributions = [];
7
+ return {
8
+ registerSlot(pluginId, slot, component, options) {
9
+ const priority = options?.priority ?? 10;
10
+ const existing = contributions.findIndex((item) => item.pluginId === pluginId && item.slot === slot);
11
+ const entry = {
12
+ pluginId,
13
+ slot,
14
+ Component: component,
15
+ priority,
16
+ };
17
+ if (existing >= 0) {
18
+ contributions[existing] = entry;
19
+ }
20
+ else {
21
+ contributions.push(entry);
22
+ }
23
+ },
24
+ getContributions(slot) {
25
+ return contributions
26
+ .filter((item) => item.slot === slot)
27
+ .sort((a, b) => a.priority - b.priority);
28
+ },
29
+ reset() {
30
+ contributions.length = 0;
31
+ },
32
+ };
33
+ }
34
+ /** Registry passed to `registerAdmin` — scopes contributions to one plugin id. */
35
+ function createPluginAdminRegistry(pluginId, host) {
36
+ return {
37
+ registerSlot(slot, component, options) {
38
+ host.registerSlot(pluginId, slot, component, options);
39
+ },
40
+ };
41
+ }
@@ -0,0 +1,36 @@
1
+ /** Built-in admin UI slot identifiers. Plugins register React components against these ids. */
2
+ export declare const AdminSlotIds: {
3
+ /** 文章编辑器 · 摘要面板下方(SEO、自定义 meta 等) */
4
+ readonly ARTICLE_EDITOR_META_AFTER_SUMMARY: "article.editor.meta.afterSummary";
5
+ /** 文章编辑器 · 右侧发布框下方 */
6
+ readonly ARTICLE_EDITOR_SIDEBAR_AFTER_PUBLISH: "article.editor.sidebar.afterPublish";
7
+ };
8
+ export type AdminSlotId = (typeof AdminSlotIds)[keyof typeof AdminSlotIds];
9
+ /** All built-in slot ids — used for manifest validation and JSON Schema enum. */
10
+ export declare const ALL_ADMIN_SLOT_IDS: readonly AdminSlotId[];
11
+ export declare function isAdminSlotId(value: string): value is AdminSlotId;
12
+ export interface AdminSlotDefinition {
13
+ id: AdminSlotId;
14
+ /** Human-readable label for plugin authors / docs */
15
+ title: string;
16
+ /** Core module that owns the host surface */
17
+ module: string;
18
+ description?: string;
19
+ }
20
+ /** Draft fields exposed to article editor slots. Host pages may extend via `context`. */
21
+ export interface ArticleEditorDraftFields {
22
+ title: string;
23
+ summary: string;
24
+ slug: string;
25
+ seoKeywords: string;
26
+ seoDescription: string;
27
+ status: 'draft' | 'publish';
28
+ }
29
+ /** Context passed to `article.editor.*` slot components from the article editor page. */
30
+ export interface ArticleEditorAdminSlotContext {
31
+ articleId?: string;
32
+ draft: ArticleEditorDraftFields;
33
+ patch: <K extends keyof ArticleEditorDraftFields>(key: K, value: ArticleEditorDraftFields[K]) => void;
34
+ /** Host-provided i18n helper (typically `react-i18next` `t`). */
35
+ translate: (key: string) => string;
36
+ }
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALL_ADMIN_SLOT_IDS = exports.AdminSlotIds = void 0;
4
+ exports.isAdminSlotId = isAdminSlotId;
5
+ /** Built-in admin UI slot identifiers. Plugins register React components against these ids. */
6
+ exports.AdminSlotIds = {
7
+ /** 文章编辑器 · 摘要面板下方(SEO、自定义 meta 等) */
8
+ ARTICLE_EDITOR_META_AFTER_SUMMARY: 'article.editor.meta.afterSummary',
9
+ /** 文章编辑器 · 右侧发布框下方 */
10
+ ARTICLE_EDITOR_SIDEBAR_AFTER_PUBLISH: 'article.editor.sidebar.afterPublish',
11
+ };
12
+ /** All built-in slot ids — used for manifest validation and JSON Schema enum. */
13
+ exports.ALL_ADMIN_SLOT_IDS = Object.values(exports.AdminSlotIds);
14
+ function isAdminSlotId(value) {
15
+ return exports.ALL_ADMIN_SLOT_IDS.includes(value);
16
+ }
@@ -0,0 +1,4 @@
1
+ export * from './plugin';
2
+ export * from './plugin-admin-locale';
3
+ export * from './security';
4
+ export * from './validate';
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./plugin"), exports);
18
+ __exportStar(require("./plugin-admin-locale"), exports);
19
+ __exportStar(require("./security"), exports);
20
+ __exportStar(require("./validate"), exports);
@@ -0,0 +1,21 @@
1
+ import { getNestedLocaleString, getNestedLocaleValue } from '../../utils/object';
2
+ /** Admin copy shipped with the plugin (`locales/{locale}.json`). */
3
+ export type PluginAdminLocaleMessages = Record<string, unknown>;
4
+ export declare const PLUGIN_LOCALE_DIR = "locales";
5
+ export { getNestedLocaleString, getNestedLocaleValue };
6
+ type PluginSchemaProperty = {
7
+ type?: string;
8
+ title?: string;
9
+ description?: string;
10
+ properties?: Record<string, PluginSchemaProperty>;
11
+ items?: PluginSchemaProperty | PluginSchemaProperty[];
12
+ };
13
+ export type PluginSettingsSchema = Record<string, unknown> & {
14
+ title?: string;
15
+ description?: string;
16
+ properties?: Record<string, PluginSchemaProperty>;
17
+ };
18
+ /** Resolve admin copy from plugin locale bundle; falls back to manifest text. */
19
+ export declare function resolvePluginAdminLocaleText(messages: PluginAdminLocaleMessages | null | undefined, dotPath: string, fallback?: string): string;
20
+ /** Apply plugin admin locale messages to settings JSON Schema titles/descriptions. */
21
+ export declare function localizePluginSettingsSchemaWithLocale(schema: PluginSettingsSchema | null | undefined, messages: PluginAdminLocaleMessages | null | undefined): PluginSettingsSchema | null;
@@ -0,0 +1,2 @@
1
+ import { type PluginAdminLocaleMessages } from './plugin-admin-locale';
2
+ export declare function readPluginAdminLocaleFile(pluginDir: string, locale: string): PluginAdminLocaleMessages | null;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.readPluginAdminLocaleFile = readPluginAdminLocaleFile;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const plugin_admin_locale_1 = require("./plugin-admin-locale");
40
+ function readPluginAdminLocaleFile(pluginDir, locale) {
41
+ const safeLocale = /^[a-z]{2}(?:-[a-z]{2})?$/i.test(locale) ? locale : 'en';
42
+ const filePath = path.join(pluginDir, plugin_admin_locale_1.PLUGIN_LOCALE_DIR, `${safeLocale}.json`);
43
+ if (!fs.existsSync(filePath))
44
+ return null;
45
+ try {
46
+ const raw = JSON.parse(fs.readFileSync(filePath, 'utf8'));
47
+ return raw && typeof raw === 'object' && !Array.isArray(raw)
48
+ ? raw
49
+ : null;
50
+ }
51
+ catch {
52
+ return null;
53
+ }
54
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNestedLocaleValue = exports.getNestedLocaleString = exports.PLUGIN_LOCALE_DIR = void 0;
4
+ exports.resolvePluginAdminLocaleText = resolvePluginAdminLocaleText;
5
+ exports.localizePluginSettingsSchemaWithLocale = localizePluginSettingsSchemaWithLocale;
6
+ const object_1 = require("../../utils/object");
7
+ Object.defineProperty(exports, "getNestedLocaleString", { enumerable: true, get: function () { return object_1.getNestedLocaleString; } });
8
+ Object.defineProperty(exports, "getNestedLocaleValue", { enumerable: true, get: function () { return object_1.getNestedLocaleValue; } });
9
+ exports.PLUGIN_LOCALE_DIR = 'locales';
10
+ /** Resolve admin copy from plugin locale bundle; falls back to manifest text. */
11
+ function resolvePluginAdminLocaleText(messages, dotPath, fallback) {
12
+ const fromLocale = messages ? (0, object_1.getNestedLocaleString)(messages, dotPath) : undefined;
13
+ if (fromLocale)
14
+ return fromLocale;
15
+ return fallback?.trim() ?? '';
16
+ }
17
+ function localizeSchemaField(field, pathParts, resolve) {
18
+ if (typeof field.title === 'string') {
19
+ field.title = resolve([...pathParts, 'title'].join('.'), field.title);
20
+ }
21
+ if (typeof field.description === 'string') {
22
+ field.description = resolve([...pathParts, 'description'].join('.'), field.description);
23
+ }
24
+ if (field.properties) {
25
+ for (const [key, child] of Object.entries(field.properties)) {
26
+ localizeSchemaField(child, [...pathParts, key], resolve);
27
+ }
28
+ }
29
+ const items = field.items;
30
+ if (items && typeof items === 'object' && !Array.isArray(items)) {
31
+ const itemSchema = items;
32
+ if (itemSchema.properties) {
33
+ for (const [key, child] of Object.entries(itemSchema.properties)) {
34
+ localizeSchemaField(child, [...pathParts, 'items', key], resolve);
35
+ }
36
+ }
37
+ else {
38
+ localizeSchemaField(itemSchema, [...pathParts, 'items'], resolve);
39
+ }
40
+ }
41
+ }
42
+ /** Apply plugin admin locale messages to settings JSON Schema titles/descriptions. */
43
+ function localizePluginSettingsSchemaWithLocale(schema, messages) {
44
+ if (!schema)
45
+ return null;
46
+ const out = structuredClone(schema);
47
+ const resolve = (dotPath, fallback) => resolvePluginAdminLocaleText(messages, `settings.${dotPath}`, fallback);
48
+ if (typeof out.title === 'string') {
49
+ out.title = resolve('title', out.title);
50
+ }
51
+ if (typeof out.description === 'string') {
52
+ out.description = resolve('description', out.description);
53
+ }
54
+ if (out.properties) {
55
+ for (const [key, field] of Object.entries(out.properties)) {
56
+ localizeSchemaField(field, [key], resolve);
57
+ }
58
+ }
59
+ return out;
60
+ }
@@ -0,0 +1,82 @@
1
+ /** WordPress-style plugin manifest and site plugin state (shared by server / web). */
2
+ import type { AdminSlotId } from '../admin/slots';
3
+ export interface PluginServerManifest {
4
+ module: string;
5
+ hooks?: {
6
+ subscribe?: string[];
7
+ provide?: string[];
8
+ };
9
+ }
10
+ export interface PluginAdminMenuManifest {
11
+ parent?: string;
12
+ title: string;
13
+ path: string;
14
+ permission?: string;
15
+ sort?: number;
16
+ }
17
+ /** Declarative admin UI — mirrors `server.hooks.subscribe` for Admin slots. */
18
+ export interface PluginAdminSlotsManifest {
19
+ /** Built-in slot ids this plugin mounts UI into (see `AdminSlotIds`). */
20
+ subscribe?: AdminSlotId[];
21
+ }
22
+ export interface PluginAdminManifest {
23
+ /** @deprecated Use convention `admin/index.ts`; declared slots drive loading. */
24
+ entry?: string;
25
+ slots?: PluginAdminSlotsManifest;
26
+ menu?: PluginAdminMenuManifest;
27
+ }
28
+ export interface PluginSettingsManifest {
29
+ schema?: Record<string, unknown>;
30
+ }
31
+ export interface PluginCapabilities {
32
+ headless?: boolean;
33
+ network?: boolean;
34
+ filesystem?: boolean;
35
+ database?: boolean;
36
+ }
37
+ export interface PluginManifest {
38
+ id: string;
39
+ name: string;
40
+ version: string;
41
+ description?: string;
42
+ author?: string;
43
+ requires?: string;
44
+ requiresPlugins?: string[];
45
+ server?: PluginServerManifest;
46
+ admin?: PluginAdminManifest;
47
+ settings?: PluginSettingsManifest;
48
+ permissions?: string[];
49
+ capabilities?: PluginCapabilities;
50
+ }
51
+ export interface PluginEntryMeta {
52
+ version: string;
53
+ source: 'local' | 'npm';
54
+ config?: Record<string, unknown>;
55
+ activatedAt?: string;
56
+ npm?: {
57
+ spec: string;
58
+ resolvedVersion?: string;
59
+ packageName?: string;
60
+ installedAt?: string;
61
+ };
62
+ loadError?: string;
63
+ }
64
+ export interface SitePluginState {
65
+ installedPlugins: string[];
66
+ activePlugins: string[];
67
+ entries: Record<string, PluginEntryMeta>;
68
+ }
69
+ export declare const defaultSitePluginState: SitePluginState;
70
+ export interface GlobalSettingWithPlugins {
71
+ theme?: unknown;
72
+ plugins?: SitePluginState;
73
+ [key: string]: unknown;
74
+ }
75
+ export declare function isValidPluginId(id: string): boolean;
76
+ export declare function parsePluginManifest(raw: unknown): PluginManifest | null;
77
+ export declare function getPluginStateFromGlobalSetting(raw: unknown): SitePluginState;
78
+ export declare function mergePluginStateIntoGlobalSetting(raw: unknown, patch: Partial<SitePluginState>): GlobalSettingWithPlugins;
79
+ /** Conventional admin module path relative to plugin package root. */
80
+ export declare const PLUGIN_ADMIN_MODULE_CONVENTION = "admin/index";
81
+ /** Whether manifest declares admin UI (slot and/or settings menu). */
82
+ export declare function pluginManifestHasAdminUI(admin: PluginAdminManifest | undefined): boolean;