@kokimoki/kit 1.7.0 → 1.8.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/api.js +6 -6
- package/dist/credentials.js +4 -3
- package/dist/dev-app.js +8 -7
- package/dist/dev-frame/render-dev-frame.d.ts +12 -0
- package/dist/dev-frame/render-dev-frame.js +32 -3
- package/dist/dev-i18n.js +5 -4
- package/dist/dev-overlays.js +4 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/kokimoki-kit-plugin.d.ts +7 -0
- package/dist/kokimoki-kit-plugin.js +164 -60
- package/dist/preprocess-style.js +12 -11
- package/dist/production-loading-screen.js +2 -2
- package/dist/schemas/app-meta-schema.d.ts +22 -0
- package/dist/schemas/app-meta-schema.js +31 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/kokimoki-kit.instructions.md +49 -1
- package/package.json +2 -1
package/dist/api.js
CHANGED
|
@@ -4,12 +4,7 @@
|
|
|
4
4
|
* Shared between @kokimoki/cli and @kokimoki/kit
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.DEFAULT_ENDPOINT = void 0;
|
|
8
|
-
exports.createConcept = createConcept;
|
|
9
|
-
exports.getOrganization = getOrganization;
|
|
10
|
-
exports.getConceptOrganization = getConceptOrganization;
|
|
11
|
-
exports.createBuild = createBuild;
|
|
12
|
-
exports.getDeployUrl = getDeployUrl;
|
|
7
|
+
exports.getDeployUrl = exports.createBuild = exports.getConceptOrganization = exports.getOrganization = exports.createConcept = exports.DEFAULT_ENDPOINT = void 0;
|
|
13
8
|
exports.DEFAULT_ENDPOINT = "https://api.kokimoki.com";
|
|
14
9
|
/**
|
|
15
10
|
* Make a request to the Kokimoki API
|
|
@@ -39,6 +34,7 @@ async function createConcept(options, request) {
|
|
|
39
34
|
body: JSON.stringify(request),
|
|
40
35
|
});
|
|
41
36
|
}
|
|
37
|
+
exports.createConcept = createConcept;
|
|
42
38
|
/**
|
|
43
39
|
* Get organization details via the Kokimoki API
|
|
44
40
|
* Used for authentication validation
|
|
@@ -46,6 +42,7 @@ async function createConcept(options, request) {
|
|
|
46
42
|
async function getOrganization(endpoint, apiKey) {
|
|
47
43
|
return kokimokiApiRequest("/auth", { endpoint, apiKey }, { method: "GET" });
|
|
48
44
|
}
|
|
45
|
+
exports.getOrganization = getOrganization;
|
|
49
46
|
/**
|
|
50
47
|
* Get the organization that owns a concept (by concept ID)
|
|
51
48
|
*/
|
|
@@ -63,6 +60,7 @@ async function getConceptOrganization(endpoint, conceptId) {
|
|
|
63
60
|
}
|
|
64
61
|
return await res.json();
|
|
65
62
|
}
|
|
63
|
+
exports.getConceptOrganization = getConceptOrganization;
|
|
66
64
|
/**
|
|
67
65
|
* Create a new build via the Kokimoki API
|
|
68
66
|
*/
|
|
@@ -75,6 +73,7 @@ async function createBuild(options, request, cliVersion) {
|
|
|
75
73
|
body: JSON.stringify(request),
|
|
76
74
|
});
|
|
77
75
|
}
|
|
76
|
+
exports.createBuild = createBuild;
|
|
78
77
|
/**
|
|
79
78
|
* Get the deploy URL for a build
|
|
80
79
|
*/
|
|
@@ -93,3 +92,4 @@ async function getDeployUrl(endpoint, apiKey, buildId) {
|
|
|
93
92
|
}
|
|
94
93
|
return await res.json();
|
|
95
94
|
}
|
|
95
|
+
exports.getDeployUrl = getDeployUrl;
|
package/dist/credentials.js
CHANGED
|
@@ -7,9 +7,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.getCredentialsPath =
|
|
11
|
-
exports.readCredentials = readCredentials;
|
|
12
|
-
exports.writeCredentials = writeCredentials;
|
|
10
|
+
exports.writeCredentials = exports.readCredentials = exports.getCredentialsPath = void 0;
|
|
13
11
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
14
12
|
const os_1 = require("os");
|
|
15
13
|
const path_1 = __importDefault(require("path"));
|
|
@@ -19,6 +17,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
19
17
|
function getCredentialsPath() {
|
|
20
18
|
return path_1.default.join((0, os_1.homedir)(), ".kokimoki");
|
|
21
19
|
}
|
|
20
|
+
exports.getCredentialsPath = getCredentialsPath;
|
|
22
21
|
/**
|
|
23
22
|
* Read credentials from the ~/.kokimoki file
|
|
24
23
|
*/
|
|
@@ -35,6 +34,7 @@ async function readCredentials() {
|
|
|
35
34
|
throw e;
|
|
36
35
|
}
|
|
37
36
|
}
|
|
37
|
+
exports.readCredentials = readCredentials;
|
|
38
38
|
/**
|
|
39
39
|
* Write credentials to the ~/.kokimoki file
|
|
40
40
|
*/
|
|
@@ -42,3 +42,4 @@ async function writeCredentials(credentials) {
|
|
|
42
42
|
const credentialsPath = getCredentialsPath();
|
|
43
43
|
await promises_1.default.writeFile(credentialsPath, JSON.stringify(credentials, null, 2));
|
|
44
44
|
}
|
|
45
|
+
exports.writeCredentials = writeCredentials;
|
package/dist/dev-app.js
CHANGED
|
@@ -3,13 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.deleteAppId =
|
|
7
|
-
exports.setDevAppI18n = setDevAppI18n;
|
|
8
|
-
exports.setDevAppTranslation = setDevAppTranslation;
|
|
9
|
-
exports.computeStoresHash = computeStoresHash;
|
|
10
|
-
exports.readStoresHash = readStoresHash;
|
|
11
|
-
exports.writeStoresHash = writeStoresHash;
|
|
12
|
-
exports.getOrCreateDevApp = getOrCreateDevApp;
|
|
6
|
+
exports.getOrCreateDevApp = exports.writeStoresHash = exports.readStoresHash = exports.computeStoresHash = exports.setDevAppTranslation = exports.setDevAppI18n = exports.deleteAppId = void 0;
|
|
13
7
|
const crypto_1 = __importDefault(require("crypto"));
|
|
14
8
|
const bson_objectid_1 = __importDefault(require("bson-objectid"));
|
|
15
9
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
@@ -108,6 +102,7 @@ async function deleteAppId() {
|
|
|
108
102
|
}
|
|
109
103
|
}
|
|
110
104
|
}
|
|
105
|
+
exports.deleteAppId = deleteAppId;
|
|
111
106
|
/**
|
|
112
107
|
* Set i18n metadata for a dev app
|
|
113
108
|
*/
|
|
@@ -126,6 +121,7 @@ async function setDevAppI18n(endpoint, apiKey, appId, i18nMeta) {
|
|
|
126
121
|
throw new Error(`Failed to set dev app i18n: ${res.status} ${errorText}`);
|
|
127
122
|
}
|
|
128
123
|
}
|
|
124
|
+
exports.setDevAppI18n = setDevAppI18n;
|
|
129
125
|
/**
|
|
130
126
|
* Set translations for a specific language and namespace in a dev app
|
|
131
127
|
*/
|
|
@@ -144,6 +140,7 @@ async function setDevAppTranslation(endpoint, apiKey, appId, lng, namespace, tra
|
|
|
144
140
|
throw new Error(`Failed to set dev app translation: ${res.status} ${errorText}`);
|
|
145
141
|
}
|
|
146
142
|
}
|
|
143
|
+
exports.setDevAppTranslation = setDevAppTranslation;
|
|
147
144
|
/**
|
|
148
145
|
* Compute a hash of the stores configuration
|
|
149
146
|
*/
|
|
@@ -151,6 +148,7 @@ function computeStoresHash(stores) {
|
|
|
151
148
|
const content = JSON.stringify(stores ?? []);
|
|
152
149
|
return crypto_1.default.createHash("sha256").update(content).digest("hex").slice(0, 16);
|
|
153
150
|
}
|
|
151
|
+
exports.computeStoresHash = computeStoresHash;
|
|
154
152
|
/**
|
|
155
153
|
* Read the stored stores hash from .kokimoki/stores-hash
|
|
156
154
|
*/
|
|
@@ -166,6 +164,7 @@ async function readStoresHash() {
|
|
|
166
164
|
throw e;
|
|
167
165
|
}
|
|
168
166
|
}
|
|
167
|
+
exports.readStoresHash = readStoresHash;
|
|
169
168
|
/**
|
|
170
169
|
* Write the stores hash to .kokimoki/stores-hash
|
|
171
170
|
*/
|
|
@@ -173,6 +172,7 @@ async function writeStoresHash(hash) {
|
|
|
173
172
|
await ensureKokimokiDir();
|
|
174
173
|
await promises_1.default.writeFile(path_1.default.join(KOKIMOKI_DIR, STORES_HASH_FILE), hash);
|
|
175
174
|
}
|
|
175
|
+
exports.writeStoresHash = writeStoresHash;
|
|
176
176
|
/**
|
|
177
177
|
* Get or create a dev app for local development.
|
|
178
178
|
*
|
|
@@ -269,3 +269,4 @@ async function getOrCreateDevApp(config) {
|
|
|
269
269
|
};
|
|
270
270
|
}
|
|
271
271
|
}
|
|
272
|
+
exports.getOrCreateDevApp = getOrCreateDevApp;
|
|
@@ -10,6 +10,18 @@ export interface DevFrameCell {
|
|
|
10
10
|
export interface DevFrameConfig {
|
|
11
11
|
/** Title shown in browser tab */
|
|
12
12
|
title?: string;
|
|
13
|
+
/**
|
|
14
|
+
* App meta for SEO and social sharing. Title will be appended with " - Dev View".
|
|
15
|
+
*/
|
|
16
|
+
appMeta?: {
|
|
17
|
+
lang?: string;
|
|
18
|
+
title?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
ogTitle?: string;
|
|
21
|
+
ogDescription?: string;
|
|
22
|
+
ogImage?: string;
|
|
23
|
+
favicon?: string;
|
|
24
|
+
};
|
|
13
25
|
/**
|
|
14
26
|
* Grid layout for the dev frame. Each inner array is a row,
|
|
15
27
|
* and each item in the row is a cell/frame.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Renders the dev frame HTML page - a multi-window view for development
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.renderDevFrame =
|
|
6
|
+
exports.renderDevFrame = void 0;
|
|
7
7
|
const styles_1 = require("./styles");
|
|
8
8
|
/**
|
|
9
9
|
* Generate URL for a dev frame iframe
|
|
@@ -138,16 +138,44 @@ function renderScript() {
|
|
|
138
138
|
* Render the complete dev frame HTML page
|
|
139
139
|
*/
|
|
140
140
|
function renderDevFrame(config) {
|
|
141
|
-
const {
|
|
141
|
+
const { rows, appMeta } = config;
|
|
142
|
+
// Build title: use appMeta.title if available, append " - Dev View"
|
|
143
|
+
const baseTitle = appMeta?.title || config.title || "Kokimoki";
|
|
144
|
+
const title = `${baseTitle} - Dev View`;
|
|
145
|
+
// Build meta tags from appMeta
|
|
146
|
+
const lang = appMeta?.lang || "en";
|
|
147
|
+
const description = appMeta?.description || "";
|
|
148
|
+
const ogTitle = appMeta?.ogTitle || baseTitle;
|
|
149
|
+
const ogDescription = appMeta?.ogDescription || description;
|
|
150
|
+
const ogImage = appMeta?.ogImage || "";
|
|
151
|
+
const favicon = appMeta?.favicon || "";
|
|
142
152
|
// Track seen labels across all rows for duplicate detection
|
|
143
153
|
const seenLabels = new Set();
|
|
144
154
|
const rowsHtml = rows.map((row) => renderRow(row, seenLabels)).join("\n");
|
|
155
|
+
// Build optional meta tags
|
|
156
|
+
const metaTags = [];
|
|
157
|
+
if (description) {
|
|
158
|
+
metaTags.push(`<meta name="description" content="${description}">`);
|
|
159
|
+
}
|
|
160
|
+
if (ogTitle) {
|
|
161
|
+
metaTags.push(`<meta property="og:title" content="${ogTitle}">`);
|
|
162
|
+
}
|
|
163
|
+
if (ogDescription) {
|
|
164
|
+
metaTags.push(`<meta property="og:description" content="${ogDescription}">`);
|
|
165
|
+
}
|
|
166
|
+
if (ogImage) {
|
|
167
|
+
metaTags.push(`<meta property="og:image" content="${ogImage}">`);
|
|
168
|
+
}
|
|
169
|
+
if (favicon) {
|
|
170
|
+
metaTags.push(`<link rel="icon" href="${favicon}">`);
|
|
171
|
+
}
|
|
145
172
|
return `<!DOCTYPE html>
|
|
146
|
-
<html lang="
|
|
173
|
+
<html lang="${lang}">
|
|
147
174
|
<head>
|
|
148
175
|
<meta charset="UTF-8">
|
|
149
176
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
150
177
|
<title>${title}</title>
|
|
178
|
+
${metaTags.join("\n ")}
|
|
151
179
|
<style>${styles_1.devFrameStyles}</style>
|
|
152
180
|
</head>
|
|
153
181
|
<body>
|
|
@@ -158,3 +186,4 @@ function renderDevFrame(config) {
|
|
|
158
186
|
</body>
|
|
159
187
|
</html>`;
|
|
160
188
|
}
|
|
189
|
+
exports.renderDevFrame = renderDevFrame;
|
package/dist/dev-i18n.js
CHANGED
|
@@ -3,10 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.loadI18nFromPath =
|
|
7
|
-
exports.getI18nMeta = getI18nMeta;
|
|
8
|
-
exports.syncAllI18nToDevApp = syncAllI18nToDevApp;
|
|
9
|
-
exports.syncI18nFile = syncI18nFile;
|
|
6
|
+
exports.syncI18nFile = exports.syncAllI18nToDevApp = exports.getI18nMeta = exports.loadI18nFromPath = void 0;
|
|
10
7
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
11
8
|
const path_1 = __importDefault(require("path"));
|
|
12
9
|
const dev_app_1 = require("./dev-app");
|
|
@@ -41,6 +38,7 @@ async function loadI18nFromPath(i18nPath) {
|
|
|
41
38
|
}
|
|
42
39
|
return resources;
|
|
43
40
|
}
|
|
41
|
+
exports.loadI18nFromPath = loadI18nFromPath;
|
|
44
42
|
/**
|
|
45
43
|
* Scan an i18n folder and return i18n metadata.
|
|
46
44
|
* Expected structure: `{i18nPath}/{lng}/{namespace}.json`
|
|
@@ -94,6 +92,7 @@ async function getI18nMeta(i18nPath, primaryLng = "en") {
|
|
|
94
92
|
languages,
|
|
95
93
|
};
|
|
96
94
|
}
|
|
95
|
+
exports.getI18nMeta = getI18nMeta;
|
|
97
96
|
/**
|
|
98
97
|
* Sync primary language i18n files to the dev app build directory (initial sync).
|
|
99
98
|
* Only uploads primaryLng since that's what AI translations use as source.
|
|
@@ -135,6 +134,7 @@ async function syncAllI18nToDevApp(devAppInfo, i18nResources, primaryLng = "en")
|
|
|
135
134
|
console.warn(`[kokimoki-kit] Synced i18n: ${syncedFiles.join(", ")}`);
|
|
136
135
|
}
|
|
137
136
|
}
|
|
137
|
+
exports.syncAllI18nToDevApp = syncAllI18nToDevApp;
|
|
138
138
|
/**
|
|
139
139
|
* Sync a single i18n file to the dev app build directory.
|
|
140
140
|
* Only syncs if the file is for the primary language.
|
|
@@ -162,3 +162,4 @@ async function syncI18nFile(devAppInfo, i18nPath, changedFilePath, primaryLng =
|
|
|
162
162
|
console.warn(`[kokimoki-kit] Failed to sync i18n ${lng}/${ns}:`, e instanceof Error ? e.message : e);
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
+
exports.syncI18nFile = syncI18nFile;
|
package/dist/dev-overlays.js
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* Development overlay HTML templates for kokimoki-kit plugin
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.renderLoadingPage =
|
|
7
|
-
exports.renderErrorPage = renderErrorPage;
|
|
8
|
-
exports.renderStoresChangedPage = renderStoresChangedPage;
|
|
6
|
+
exports.renderStoresChangedPage = exports.renderErrorPage = exports.renderLoadingPage = void 0;
|
|
9
7
|
const pageBaseStyles = `
|
|
10
8
|
color: white;
|
|
11
9
|
display: flex;
|
|
@@ -111,6 +109,7 @@ function renderLoadingPage() {
|
|
|
111
109
|
</body>
|
|
112
110
|
</html>`;
|
|
113
111
|
}
|
|
112
|
+
exports.renderLoadingPage = renderLoadingPage;
|
|
114
113
|
/**
|
|
115
114
|
* Generate error page HTML for dev app errors (full page)
|
|
116
115
|
*/
|
|
@@ -176,6 +175,7 @@ function renderErrorPage(error) {
|
|
|
176
175
|
</body>
|
|
177
176
|
</html>`;
|
|
178
177
|
}
|
|
178
|
+
exports.renderErrorPage = renderErrorPage;
|
|
179
179
|
/**
|
|
180
180
|
* Generate stores changed warning page HTML (full page, not overlay)
|
|
181
181
|
*/
|
|
@@ -298,3 +298,4 @@ function renderStoresChangedPage(canReset) {
|
|
|
298
298
|
</body>
|
|
299
299
|
</html>`;
|
|
300
300
|
}
|
|
301
|
+
exports.renderStoresChangedPage = renderStoresChangedPage;
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -20,6 +20,8 @@ __exportStar(require("./kokimoki-kit-plugin"), exports);
|
|
|
20
20
|
__exportStar(require("./preprocess-style"), exports);
|
|
21
21
|
// Re-export Zod utilities for schema definition
|
|
22
22
|
__exportStar(require("./zod"), exports);
|
|
23
|
+
// App Meta schema for built-in store
|
|
24
|
+
__exportStar(require("./schemas/app-meta-schema"), exports);
|
|
23
25
|
// Shared utilities (used by both kit and cli)
|
|
24
26
|
__exportStar(require("./api"), exports);
|
|
25
27
|
__exportStar(require("./credentials"), exports);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PluginOption } from "vite";
|
|
2
2
|
import { ZodType } from "zod/v4";
|
|
3
3
|
import type { DevFrameCell } from "./dev-frame";
|
|
4
|
+
import { type AppMetaState } from "./schemas/app-meta-schema";
|
|
4
5
|
export { getI18nMeta, type I18nMeta } from "./dev-i18n";
|
|
5
6
|
export interface KokimokiKitConfig {
|
|
6
7
|
conceptId: string;
|
|
@@ -53,5 +54,11 @@ export interface KokimokiKitConfig {
|
|
|
53
54
|
* ```
|
|
54
55
|
*/
|
|
55
56
|
devView?: readonly (readonly DevFrameCell[])[] | false;
|
|
57
|
+
/**
|
|
58
|
+
* Default app meta values for SEO and social sharing.
|
|
59
|
+
* These values are used as initial state for the built-in appMetaStore
|
|
60
|
+
* and for server-side HTML meta tag injection.
|
|
61
|
+
*/
|
|
62
|
+
defaultAppMeta?: AppMetaState;
|
|
56
63
|
}
|
|
57
64
|
export declare function kokimokiKitPlugin(config: KokimokiKitConfig): PluginOption;
|
|
@@ -15,30 +15,20 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
|
|
|
15
15
|
}) : function(o, v) {
|
|
16
16
|
o["default"] = v;
|
|
17
17
|
});
|
|
18
|
-
var __importStar = (this && this.__importStar) ||
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
})();
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
35
25
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
27
|
};
|
|
38
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.getI18nMeta = void 0;
|
|
40
|
-
exports.kokimokiKitPlugin = kokimokiKitPlugin;
|
|
29
|
+
exports.kokimokiKitPlugin = exports.getI18nMeta = void 0;
|
|
41
30
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
31
|
+
const node_html_parser_1 = require("node-html-parser");
|
|
42
32
|
const path_1 = __importDefault(require("path"));
|
|
43
33
|
const yaml = __importStar(require("yaml"));
|
|
44
34
|
const v4_1 = require("zod/v4");
|
|
@@ -50,10 +40,22 @@ const dev_i18n_1 = require("./dev-i18n");
|
|
|
50
40
|
const dev_overlays_1 = require("./dev-overlays");
|
|
51
41
|
const preprocess_style_1 = require("./preprocess-style");
|
|
52
42
|
const production_loading_screen_1 = require("./production-loading-screen");
|
|
43
|
+
const app_meta_schema_1 = require("./schemas/app-meta-schema");
|
|
53
44
|
const version_1 = require("./version");
|
|
54
45
|
var dev_i18n_2 = require("./dev-i18n");
|
|
55
46
|
Object.defineProperty(exports, "getI18nMeta", { enumerable: true, get: function () { return dev_i18n_2.getI18nMeta; } });
|
|
47
|
+
/**
|
|
48
|
+
* Built-in app meta store configuration.
|
|
49
|
+
* Automatically injected into all apps for server-side meta tag injection.
|
|
50
|
+
*/
|
|
51
|
+
const BUILT_IN_APP_META_STORE = {
|
|
52
|
+
pattern: app_meta_schema_1.APP_META_STORE_NAME,
|
|
53
|
+
schema: app_meta_schema_1.appMetaStoreSchema,
|
|
54
|
+
local: false,
|
|
55
|
+
};
|
|
56
56
|
function kokimokiKitPlugin(config) {
|
|
57
|
+
// Combine user stores with built-in stores
|
|
58
|
+
const allStores = [...(config.stores ?? []), BUILT_IN_APP_META_STORE];
|
|
57
59
|
// Cache for loaded i18n resources
|
|
58
60
|
let cachedI18n = null;
|
|
59
61
|
// Cache dev app info for syncing
|
|
@@ -63,6 +65,37 @@ function kokimokiKitPlugin(config) {
|
|
|
63
65
|
let initPromise = null;
|
|
64
66
|
// Cached dev app result
|
|
65
67
|
let cachedDevAppResult = null;
|
|
68
|
+
/**
|
|
69
|
+
* Resolve asset path for meta tags.
|
|
70
|
+
* In production, prepends %KM_ASSETS% placeholder for relative paths.
|
|
71
|
+
* In dev, returns path as-is since assets are served from root.
|
|
72
|
+
*/
|
|
73
|
+
function resolveAssetUrl(path, isProduction) {
|
|
74
|
+
if (!path)
|
|
75
|
+
return path;
|
|
76
|
+
// Only prefix relative paths (starting with /)
|
|
77
|
+
if (isProduction && path.startsWith("/")) {
|
|
78
|
+
return `%KM_ASSETS%${path}`;
|
|
79
|
+
}
|
|
80
|
+
return path;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolve asset URLs in defaultAppMeta object.
|
|
84
|
+
* Creates a new object with ogImage and favicon paths resolved.
|
|
85
|
+
*/
|
|
86
|
+
function resolveAppMetaAssets(meta, isProduction) {
|
|
87
|
+
if (!meta)
|
|
88
|
+
return null;
|
|
89
|
+
return {
|
|
90
|
+
...meta,
|
|
91
|
+
ogImage: meta.ogImage
|
|
92
|
+
? resolveAssetUrl(meta.ogImage, isProduction)
|
|
93
|
+
: undefined,
|
|
94
|
+
favicon: meta.favicon
|
|
95
|
+
? resolveAssetUrl(meta.favicon, isProduction)
|
|
96
|
+
: undefined,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
66
99
|
/**
|
|
67
100
|
* Start initialization if not already started.
|
|
68
101
|
* Returns a promise that resolves when initialization is complete.
|
|
@@ -137,11 +170,15 @@ function kokimokiKitPlugin(config) {
|
|
|
137
170
|
if (process.env.NODE_ENV !== "development") {
|
|
138
171
|
// Remove any existing km-loading element from the HTML
|
|
139
172
|
const processedHtml = (0, production_loading_screen_1.removeExistingLoadingScreen)(html);
|
|
140
|
-
//
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
173
|
+
// Parse HTML for DOM manipulation
|
|
174
|
+
const doc = (0, node_html_parser_1.parse)(processedHtml);
|
|
175
|
+
const head = doc.querySelector("head");
|
|
176
|
+
const body = doc.querySelector("body");
|
|
177
|
+
const htmlEl = doc.querySelector("html");
|
|
178
|
+
// Add base tag
|
|
179
|
+
head?.insertAdjacentHTML("afterbegin", `<base href="%KM_BASE%">`);
|
|
180
|
+
// Inject kokimoki-env script
|
|
181
|
+
head?.insertAdjacentHTML("afterbegin", `<script id="kokimoki-env" type="application/json">
|
|
145
182
|
{
|
|
146
183
|
"dev": %KM_DEV%,
|
|
147
184
|
"test": %KM_TEST%,
|
|
@@ -154,10 +191,12 @@ function kokimokiKitPlugin(config) {
|
|
|
154
191
|
"i18nNamespaces": ${JSON.stringify(i18nNamespaces)},
|
|
155
192
|
"i18nLanguages": ${JSON.stringify(i18nLanguages)},
|
|
156
193
|
"base": "%KM_BASE%",
|
|
157
|
-
"assets": "%KM_ASSETS%"
|
|
194
|
+
"assets": "%KM_ASSETS%",
|
|
195
|
+
"defaultAppMeta": ${JSON.stringify(resolveAppMetaAssets(config.defaultAppMeta, true))}
|
|
158
196
|
}
|
|
159
|
-
</script
|
|
160
|
-
|
|
197
|
+
</script>`);
|
|
198
|
+
// Inject assets URL helper script
|
|
199
|
+
head?.insertAdjacentHTML("beforeend", `<script>
|
|
161
200
|
window.__toAssetsUrl = (path) => {
|
|
162
201
|
if (path.startsWith("km-proxy")) {
|
|
163
202
|
return "/%KM_BUILD_ID%/" + path;
|
|
@@ -165,16 +204,50 @@ function kokimokiKitPlugin(config) {
|
|
|
165
204
|
|
|
166
205
|
return "%KM_ASSETS%/" + path;
|
|
167
206
|
};
|
|
168
|
-
</script
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
207
|
+
</script>`);
|
|
208
|
+
// Inject loading screen
|
|
209
|
+
head?.insertAdjacentHTML("beforeend", production_loading_screen_1.loadingScreenStyles);
|
|
210
|
+
head?.insertAdjacentHTML("beforeend", production_loading_screen_1.loadingScreenScript);
|
|
211
|
+
body?.insertAdjacentHTML("afterbegin", production_loading_screen_1.loadingScreenElement);
|
|
212
|
+
// Inject meta tags from defaultAppMeta
|
|
213
|
+
if (config.defaultAppMeta) {
|
|
214
|
+
const meta = config.defaultAppMeta;
|
|
215
|
+
if (meta.lang) {
|
|
216
|
+
htmlEl?.setAttribute("lang", meta.lang);
|
|
217
|
+
}
|
|
218
|
+
if (meta.title) {
|
|
219
|
+
head?.insertAdjacentHTML("beforeend", `<title>${meta.title}</title>`);
|
|
220
|
+
}
|
|
221
|
+
if (meta.description) {
|
|
222
|
+
head?.insertAdjacentHTML("beforeend", `<meta name="description" content="${meta.description}" />`);
|
|
223
|
+
}
|
|
224
|
+
if (meta.ogTitle ?? meta.title) {
|
|
225
|
+
head?.insertAdjacentHTML("beforeend", `<meta property="og:title" content="${meta.ogTitle ?? meta.title}" />`);
|
|
226
|
+
}
|
|
227
|
+
if (meta.ogDescription ?? meta.description) {
|
|
228
|
+
head?.insertAdjacentHTML("beforeend", `<meta property="og:description" content="${meta.ogDescription ?? meta.description}" />`);
|
|
229
|
+
}
|
|
230
|
+
if (meta.ogImage) {
|
|
231
|
+
head?.insertAdjacentHTML("beforeend", `<meta property="og:image" content="${resolveAssetUrl(meta.ogImage, true)}" />`);
|
|
232
|
+
}
|
|
233
|
+
if (meta.favicon) {
|
|
234
|
+
head?.insertAdjacentHTML("beforeend", `<link rel="icon" type="image/png" href="${resolveAssetUrl(meta.favicon, true)}" />`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Update asset URLs in link and script tags
|
|
238
|
+
doc.querySelectorAll("link[href]").forEach((el) => {
|
|
239
|
+
const href = el.getAttribute("href");
|
|
240
|
+
if (href) {
|
|
241
|
+
el.setAttribute("href", `%KM_ASSETS%${href.startsWith("/") ? "" : "/"}${href}`);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
doc.querySelectorAll("script[src]").forEach((el) => {
|
|
245
|
+
const src = el.getAttribute("src");
|
|
246
|
+
if (src) {
|
|
247
|
+
el.setAttribute("src", `%KM_ASSETS%${src.startsWith("/") ? "" : "/"}${src}`);
|
|
248
|
+
}
|
|
176
249
|
});
|
|
177
|
-
return
|
|
250
|
+
return doc.toString();
|
|
178
251
|
}
|
|
179
252
|
// Development mode: ensure initialization is started and wait for it
|
|
180
253
|
if (initState === "pending" || initState === "initializing") {
|
|
@@ -191,7 +264,7 @@ function kokimokiKitPlugin(config) {
|
|
|
191
264
|
error: { code: "INIT_ERROR", message: "Initialization failed" },
|
|
192
265
|
};
|
|
193
266
|
// Check if stores configuration has changed
|
|
194
|
-
const currentStoresHash = (0, dev_app_1.computeStoresHash)(
|
|
267
|
+
const currentStoresHash = (0, dev_app_1.computeStoresHash)(allStores);
|
|
195
268
|
const previousStoresHash = await (0, dev_app_1.readStoresHash)();
|
|
196
269
|
const storesChanged = previousStoresHash !== null && previousStoresHash !== currentStoresHash;
|
|
197
270
|
// Write initial stores hash if it doesn't exist yet
|
|
@@ -212,9 +285,12 @@ function kokimokiKitPlugin(config) {
|
|
|
212
285
|
const defaultProjectConfigFile = await promises_1.default.readFile(config.defaultProjectConfigPath, "utf8");
|
|
213
286
|
defaultProjectConfig = config.schema.parse(yaml.parse(defaultProjectConfigFile));
|
|
214
287
|
}
|
|
215
|
-
//
|
|
216
|
-
|
|
217
|
-
|
|
288
|
+
// Parse HTML for DOM manipulation
|
|
289
|
+
const doc = (0, node_html_parser_1.parse)(html);
|
|
290
|
+
const head = doc.querySelector("head");
|
|
291
|
+
const htmlEl = doc.querySelector("html");
|
|
292
|
+
// Inject kokimoki-env script
|
|
293
|
+
const envScript = (0, node_html_parser_1.parse)(`<script id="kokimoki-env" type="application/json">
|
|
218
294
|
{
|
|
219
295
|
"dev": true,
|
|
220
296
|
"test": true,
|
|
@@ -225,15 +301,43 @@ function kokimokiKitPlugin(config) {
|
|
|
225
301
|
"i18nLanguages": ${JSON.stringify(i18nLanguages)},
|
|
226
302
|
"base": "/",
|
|
227
303
|
"assets": "/",
|
|
228
|
-
"buildUrl": ${JSON.stringify(buildUrl ?? null)}
|
|
304
|
+
"buildUrl": ${JSON.stringify(buildUrl ?? null)},
|
|
305
|
+
"defaultAppMeta": ${JSON.stringify(config.defaultAppMeta ?? null)}
|
|
229
306
|
}
|
|
230
307
|
</script>`);
|
|
308
|
+
head?.insertAdjacentHTML("afterbegin", envScript.toString());
|
|
309
|
+
// Inject meta tags from defaultAppMeta in development
|
|
310
|
+
if (config.defaultAppMeta) {
|
|
311
|
+
const meta = config.defaultAppMeta;
|
|
312
|
+
if (meta.lang) {
|
|
313
|
+
htmlEl?.setAttribute("lang", meta.lang);
|
|
314
|
+
}
|
|
315
|
+
if (meta.title) {
|
|
316
|
+
head?.insertAdjacentHTML("beforeend", `<title>${meta.title}</title>`);
|
|
317
|
+
}
|
|
318
|
+
if (meta.description) {
|
|
319
|
+
head?.insertAdjacentHTML("beforeend", `<meta name="description" content="${meta.description}" />`);
|
|
320
|
+
}
|
|
321
|
+
if (meta.ogTitle ?? meta.title) {
|
|
322
|
+
head?.insertAdjacentHTML("beforeend", `<meta property="og:title" content="${meta.ogTitle ?? meta.title}" />`);
|
|
323
|
+
}
|
|
324
|
+
if (meta.ogDescription ?? meta.description) {
|
|
325
|
+
head?.insertAdjacentHTML("beforeend", `<meta property="og:description" content="${meta.ogDescription ?? meta.description}" />`);
|
|
326
|
+
}
|
|
327
|
+
if (meta.ogImage) {
|
|
328
|
+
head?.insertAdjacentHTML("beforeend", `<meta property="og:image" content="${meta.ogImage}" />`);
|
|
329
|
+
}
|
|
330
|
+
if (meta.favicon) {
|
|
331
|
+
head?.insertAdjacentHTML("beforeend", `<link rel="icon" type="image/png" href="${meta.favicon}" />`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
231
334
|
// Inject default project style in development
|
|
232
335
|
if (config.defaultProjectStylePath) {
|
|
233
336
|
const defaultProjectStyle = await promises_1.default.readFile(config.defaultProjectStylePath, "utf8");
|
|
234
|
-
|
|
337
|
+
const body = doc.querySelector("body");
|
|
338
|
+
body?.insertAdjacentHTML("beforeend", `<style id="km-dev-style">${(0, preprocess_style_1.preprocessStyle)(defaultProjectStyle)}</style>`);
|
|
235
339
|
}
|
|
236
|
-
return
|
|
340
|
+
return doc.toString();
|
|
237
341
|
},
|
|
238
342
|
// write kokimoki metadata to .kokimoki directory
|
|
239
343
|
async generateBundle(_, _bundle) {
|
|
@@ -259,6 +363,7 @@ function kokimokiKitPlugin(config) {
|
|
|
259
363
|
build: "dist",
|
|
260
364
|
defaultProjectConfigPath: config.defaultProjectConfigPath,
|
|
261
365
|
defaultProjectStylePath: config.defaultProjectStylePath,
|
|
366
|
+
defaultAppMeta: config.defaultAppMeta,
|
|
262
367
|
i18n,
|
|
263
368
|
}, null, 2));
|
|
264
369
|
// write schema
|
|
@@ -297,19 +402,17 @@ function kokimokiKitPlugin(config) {
|
|
|
297
402
|
properties: {},
|
|
298
403
|
};
|
|
299
404
|
await promises_1.default.writeFile(".kokimoki/schema.json", JSON.stringify(jsonSchema, null, 2));
|
|
300
|
-
// write stores config with JSON schemas to build output
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
});
|
|
312
|
-
}
|
|
405
|
+
// write stores config with JSON schemas to build output (always includes built-in stores)
|
|
406
|
+
const storesWithJsonSchema = allStores.map((store) => ({
|
|
407
|
+
pattern: store.pattern,
|
|
408
|
+
local: store.local,
|
|
409
|
+
schema: v4_1.z.toJSONSchema(store.schema),
|
|
410
|
+
}));
|
|
411
|
+
this.emitFile({
|
|
412
|
+
type: "asset",
|
|
413
|
+
fileName: "km-stores.json",
|
|
414
|
+
source: JSON.stringify(storesWithJsonSchema, null, 2),
|
|
415
|
+
});
|
|
313
416
|
// write i18n files to build output as individual files per lng/ns
|
|
314
417
|
const i18nResources = await getI18nResources();
|
|
315
418
|
if (Object.keys(i18nResources).length > 0) {
|
|
@@ -340,7 +443,7 @@ function kokimokiKitPlugin(config) {
|
|
|
340
443
|
startInitialization();
|
|
341
444
|
// Helper to check stores changed status
|
|
342
445
|
async function checkStoresChanged() {
|
|
343
|
-
const currentStoresHash = (0, dev_app_1.computeStoresHash)(
|
|
446
|
+
const currentStoresHash = (0, dev_app_1.computeStoresHash)(allStores);
|
|
344
447
|
const previousStoresHash = await (0, dev_app_1.readStoresHash)();
|
|
345
448
|
return (previousStoresHash !== null &&
|
|
346
449
|
previousStoresHash !== currentStoresHash);
|
|
@@ -387,7 +490,7 @@ function kokimokiKitPlugin(config) {
|
|
|
387
490
|
// API endpoint to acknowledge stores hash change (dismiss the popup)
|
|
388
491
|
server.middlewares.use("/__kokimoki/stores-hash/acknowledge", async (_req, res) => {
|
|
389
492
|
try {
|
|
390
|
-
const currentStoresHash = (0, dev_app_1.computeStoresHash)(
|
|
493
|
+
const currentStoresHash = (0, dev_app_1.computeStoresHash)(allStores);
|
|
391
494
|
await (0, dev_app_1.writeStoresHash)(currentStoresHash);
|
|
392
495
|
res.statusCode = 200;
|
|
393
496
|
res.setHeader("Content-Type", "application/json");
|
|
@@ -407,7 +510,7 @@ function kokimokiKitPlugin(config) {
|
|
|
407
510
|
// Delete the app-id file so a new dev app will be created
|
|
408
511
|
await (0, dev_app_1.deleteAppId)();
|
|
409
512
|
// Update the stores hash
|
|
410
|
-
const currentStoresHash = (0, dev_app_1.computeStoresHash)(
|
|
513
|
+
const currentStoresHash = (0, dev_app_1.computeStoresHash)(allStores);
|
|
411
514
|
await (0, dev_app_1.writeStoresHash)(currentStoresHash);
|
|
412
515
|
// Reset initialization state so next request triggers re-initialization
|
|
413
516
|
initState = "pending";
|
|
@@ -523,8 +626,8 @@ function kokimokiKitPlugin(config) {
|
|
|
523
626
|
}
|
|
524
627
|
// Render dev view HTML at root
|
|
525
628
|
const devViewHtml = (0, dev_frame_1.renderDevFrame)({
|
|
526
|
-
title: "Dev View",
|
|
527
629
|
rows: config.devView,
|
|
630
|
+
appMeta: config.defaultAppMeta,
|
|
528
631
|
});
|
|
529
632
|
res.statusCode = 200;
|
|
530
633
|
res.setHeader("Content-Type", "text/html");
|
|
@@ -534,3 +637,4 @@ function kokimokiKitPlugin(config) {
|
|
|
534
637
|
},
|
|
535
638
|
};
|
|
536
639
|
}
|
|
640
|
+
exports.kokimokiKitPlugin = kokimokiKitPlugin;
|
package/dist/preprocess-style.js
CHANGED
|
@@ -3,17 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.hexToRgb =
|
|
7
|
-
exports.rgbToHex = rgbToHex;
|
|
8
|
-
exports.revertReplaceForColorPickers = revertReplaceForColorPickers;
|
|
9
|
-
exports.hexToTailwindRgbString = hexToTailwindRgbString;
|
|
10
|
-
exports.getLuminance = getLuminance;
|
|
11
|
-
exports.calculateRatio = calculateRatio;
|
|
12
|
-
exports.handleStringColor = handleStringColor;
|
|
13
|
-
exports.destringRgb = destringRgb;
|
|
14
|
-
exports.generateA11yOnColor = generateA11yOnColor;
|
|
15
|
-
exports.generatePalette = generatePalette;
|
|
16
|
-
exports.preprocessStyle = preprocessStyle;
|
|
6
|
+
exports.preprocessStyle = exports.generatePalette = exports.generateA11yOnColor = exports.destringRgb = exports.handleStringColor = exports.calculateRatio = exports.getLuminance = exports.hexToTailwindRgbString = exports.revertReplaceForColorPickers = exports.rgbToHex = exports.hexToRgb = void 0;
|
|
17
7
|
const colorjs_io_1 = __importDefault(require("colorjs.io"));
|
|
18
8
|
const colornames_1 = __importDefault(require("colornames"));
|
|
19
9
|
// List of rgb tuple variable names (possibly temporary system to support color picker for these variables)
|
|
@@ -113,10 +103,12 @@ function hexToRgb(hex) {
|
|
|
113
103
|
b: parseInt(b, 16),
|
|
114
104
|
};
|
|
115
105
|
}
|
|
106
|
+
exports.hexToRgb = hexToRgb;
|
|
116
107
|
function rgbToHex(r, g, b) {
|
|
117
108
|
const toHex = (c) => `0${c.toString(16)}`.slice(-2);
|
|
118
109
|
return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
|
|
119
110
|
}
|
|
111
|
+
exports.rgbToHex = rgbToHex;
|
|
120
112
|
// export function replaceForColorPickers(code: string) {
|
|
121
113
|
// return code.replace(
|
|
122
114
|
// /--([a-z0-9-]+):\s*(\d+)\s+(\d+)\s+(\d+);/gi,
|
|
@@ -153,6 +145,7 @@ function revertReplaceForColorPickers(code) {
|
|
|
153
145
|
return match;
|
|
154
146
|
});
|
|
155
147
|
}
|
|
148
|
+
exports.revertReplaceForColorPickers = revertReplaceForColorPickers;
|
|
156
149
|
function lighten(hex, intensity) {
|
|
157
150
|
const color = hexToRgb(`#${hex}`);
|
|
158
151
|
if (!color)
|
|
@@ -179,6 +172,7 @@ function hexToTailwindRgbString(hex) {
|
|
|
179
172
|
const [, r, g, b] = colorParts;
|
|
180
173
|
return `${parseInt(r, 16)} ${parseInt(g, 16)} ${parseInt(b, 16)}`;
|
|
181
174
|
}
|
|
175
|
+
exports.hexToTailwindRgbString = hexToTailwindRgbString;
|
|
182
176
|
function getLuminance(r, g, b) {
|
|
183
177
|
const { _r, _g, _b } = typeof r === "object"
|
|
184
178
|
? { _r: r.r, _g: r.g, _b: r.b }
|
|
@@ -192,6 +186,7 @@ function getLuminance(r, g, b) {
|
|
|
192
186
|
});
|
|
193
187
|
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
194
188
|
}
|
|
189
|
+
exports.getLuminance = getLuminance;
|
|
195
190
|
function calculateRatio(luminance1, luminance2) {
|
|
196
191
|
const lum1 = typeof luminance1 === "string"
|
|
197
192
|
? getLuminance(handleStringColor(luminance1))
|
|
@@ -205,6 +200,7 @@ function calculateRatio(luminance1, luminance2) {
|
|
|
205
200
|
? (lum2 + 0.05) / (lum1 + 0.05)
|
|
206
201
|
: (lum1 + 0.05) / (lum2 + 0.05);
|
|
207
202
|
}
|
|
203
|
+
exports.calculateRatio = calculateRatio;
|
|
208
204
|
function handleStringColor(colorString, returnType = "rgb") {
|
|
209
205
|
// if it's a css variable
|
|
210
206
|
if (colorString.includes("--")) {
|
|
@@ -228,6 +224,7 @@ function handleStringColor(colorString, returnType = "rgb") {
|
|
|
228
224
|
}
|
|
229
225
|
return colorString;
|
|
230
226
|
}
|
|
227
|
+
exports.handleStringColor = handleStringColor;
|
|
231
228
|
function cssColorToHex(colorString) {
|
|
232
229
|
if (colorString.includes("#"))
|
|
233
230
|
return colorString;
|
|
@@ -254,11 +251,13 @@ function destringRgb(rgbString) {
|
|
|
254
251
|
b: parseInt(rgb[3], 10),
|
|
255
252
|
};
|
|
256
253
|
}
|
|
254
|
+
exports.destringRgb = destringRgb;
|
|
257
255
|
function generateA11yOnColor(hex) {
|
|
258
256
|
const black = calculateRatio(hex, "#000000");
|
|
259
257
|
const white = calculateRatio(hex, "#FFFFFF");
|
|
260
258
|
return black < white ? "0 0 0" : "255 255 255";
|
|
261
259
|
}
|
|
260
|
+
exports.generateA11yOnColor = generateA11yOnColor;
|
|
262
261
|
function generatePalette(baseColor) {
|
|
263
262
|
const hexValidation = new RegExp(/^#[0-9a-f]{6}$/i);
|
|
264
263
|
if (!hexValidation.test(baseColor))
|
|
@@ -300,6 +299,7 @@ function generatePalette(baseColor) {
|
|
|
300
299
|
});
|
|
301
300
|
return response;
|
|
302
301
|
}
|
|
302
|
+
exports.generatePalette = generatePalette;
|
|
303
303
|
function preprocessGfcThemeBlock(code) {
|
|
304
304
|
// Generate map of defined css variables
|
|
305
305
|
const cssVariableMap = {};
|
|
@@ -376,3 +376,4 @@ function preprocessStyle(code) {
|
|
|
376
376
|
}
|
|
377
377
|
});
|
|
378
378
|
}
|
|
379
|
+
exports.preprocessStyle = preprocessStyle;
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* This screen is injected into production builds and removed when km:ready is received.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.loadingScreenElement = exports.loadingScreenScript = exports.loadingScreenStyles = void 0;
|
|
8
|
-
exports.removeExistingLoadingScreen = removeExistingLoadingScreen;
|
|
7
|
+
exports.removeExistingLoadingScreen = exports.loadingScreenElement = exports.loadingScreenScript = exports.loadingScreenStyles = void 0;
|
|
9
8
|
/**
|
|
10
9
|
* Loading screen styles
|
|
11
10
|
*/
|
|
@@ -121,3 +120,4 @@ function removeExistingLoadingScreen(html) {
|
|
|
121
120
|
.replace(/<div[^>]*id=["']km-loading["'][^>]*>[\s\S]*?<\/div>/gi, "")
|
|
122
121
|
.replace(/<style[^>]*id=["']km-loading-style["'][^>]*>[\s\S]*?<\/style>/gi, "");
|
|
123
122
|
}
|
|
123
|
+
exports.removeExistingLoadingScreen = removeExistingLoadingScreen;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
/**
|
|
3
|
+
* Reserved store name for the App Meta store.
|
|
4
|
+
* Stores with the `__km/` prefix are reserved for SDK internal use.
|
|
5
|
+
*/
|
|
6
|
+
export declare const APP_META_STORE_NAME = "__km/app-meta";
|
|
7
|
+
/**
|
|
8
|
+
* Schema for the App Meta store.
|
|
9
|
+
* Used by the server to inject meta tags into the HTML response.
|
|
10
|
+
*
|
|
11
|
+
* All fields are optional - missing fields will fall back to defaults in index.html.
|
|
12
|
+
*/
|
|
13
|
+
export declare const appMetaStoreSchema: z.ZodObject<{
|
|
14
|
+
lang: z.ZodOptional<z.ZodString>;
|
|
15
|
+
title: z.ZodOptional<z.ZodString>;
|
|
16
|
+
description: z.ZodOptional<z.ZodString>;
|
|
17
|
+
ogTitle: z.ZodOptional<z.ZodString>;
|
|
18
|
+
ogDescription: z.ZodOptional<z.ZodString>;
|
|
19
|
+
ogImage: z.ZodOptional<z.ZodString>;
|
|
20
|
+
favicon: z.ZodOptional<z.ZodString>;
|
|
21
|
+
}, z.core.$strip>;
|
|
22
|
+
export type AppMetaState = z.infer<typeof appMetaStoreSchema>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.appMetaStoreSchema = exports.APP_META_STORE_NAME = void 0;
|
|
4
|
+
const v4_1 = require("zod/v4");
|
|
5
|
+
/**
|
|
6
|
+
* Reserved store name for the App Meta store.
|
|
7
|
+
* Stores with the `__km/` prefix are reserved for SDK internal use.
|
|
8
|
+
*/
|
|
9
|
+
exports.APP_META_STORE_NAME = "__km/app-meta";
|
|
10
|
+
/**
|
|
11
|
+
* Schema for the App Meta store.
|
|
12
|
+
* Used by the server to inject meta tags into the HTML response.
|
|
13
|
+
*
|
|
14
|
+
* All fields are optional - missing fields will fall back to defaults in index.html.
|
|
15
|
+
*/
|
|
16
|
+
exports.appMetaStoreSchema = v4_1.z.object({
|
|
17
|
+
/** HTML lang attribute (e.g., 'en', 'et', 'de') */
|
|
18
|
+
lang: v4_1.z.string().optional(),
|
|
19
|
+
/** Document title (browser tab) */
|
|
20
|
+
title: v4_1.z.string().optional(),
|
|
21
|
+
/** Meta description */
|
|
22
|
+
description: v4_1.z.string().optional(),
|
|
23
|
+
/** Open Graph title (defaults to title if not set) */
|
|
24
|
+
ogTitle: v4_1.z.string().optional(),
|
|
25
|
+
/** Open Graph description (defaults to description if not set) */
|
|
26
|
+
ogDescription: v4_1.z.string().optional(),
|
|
27
|
+
/** Open Graph image URL */
|
|
28
|
+
ogImage: v4_1.z.string().optional(),
|
|
29
|
+
/** Favicon URL */
|
|
30
|
+
favicon: v4_1.z.string().optional(),
|
|
31
|
+
});
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const KOKIMOKI_KIT_VERSION = "1.
|
|
1
|
+
export declare const KOKIMOKI_KIT_VERSION = "1.8.0";
|
package/dist/version.js
CHANGED
|
@@ -109,9 +109,57 @@ export default defineConfig({
|
|
|
109
109
|
| `endpoint` | `string` | API endpoint (default: `https://api.kokimoki.com`) |
|
|
110
110
|
| `host` | `string` | WebSocket host (default: `y-wss.kokimoki.com`) |
|
|
111
111
|
| `devView` | `array \| false` | Dev frame layout or `false` to disable |
|
|
112
|
-
| `
|
|
112
|
+
| `defaultAppMeta` | `object` | Default meta tags for SEO and social sharing |
|
|
113
113
|
| `defaultProjectStylePath` | `string` | Path to default project style file |
|
|
114
114
|
|
|
115
|
+
## App Meta
|
|
116
|
+
|
|
117
|
+
The `defaultAppMeta` option configures HTML meta tags for SEO and social sharing previews. These defaults are injected into the HTML at build time and used as the initial state for `kmClient.metaStore`.
|
|
118
|
+
|
|
119
|
+
### Configuration
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
kokimokiKitPlugin({
|
|
123
|
+
// ...
|
|
124
|
+
defaultAppMeta: {
|
|
125
|
+
lang: "en",
|
|
126
|
+
title: "My Game",
|
|
127
|
+
description: "An awesome multiplayer game",
|
|
128
|
+
ogTitle: "My Game",
|
|
129
|
+
ogDescription: "Join the fun!",
|
|
130
|
+
ogImage: "/og-image.png",
|
|
131
|
+
favicon: "/favicon.png",
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Fields
|
|
137
|
+
|
|
138
|
+
| Field | Description |
|
|
139
|
+
| --------------- | ---------------------------------------------------- |
|
|
140
|
+
| `lang` | HTML `lang` attribute (e.g., `"en"`, `"de"`) |
|
|
141
|
+
| `title` | Document title (browser tab) |
|
|
142
|
+
| `description` | Meta description for SEO |
|
|
143
|
+
| `ogTitle` | Open Graph title (defaults to `title` if not set) |
|
|
144
|
+
| `ogDescription` | Open Graph description (defaults to `description`) |
|
|
145
|
+
| `ogImage` | Open Graph image URL (use relative path like `/og-image.png`) |
|
|
146
|
+
| `favicon` | Favicon URL (use relative path like `/favicon.png`) |
|
|
147
|
+
|
|
148
|
+
### Asset Path Resolution
|
|
149
|
+
|
|
150
|
+
Relative paths (starting with `/`) for `ogImage` and `favicon` are automatically prefixed with the assets base URL in production builds. This ensures images work correctly when served from a CDN.
|
|
151
|
+
|
|
152
|
+
### Runtime Updates
|
|
153
|
+
|
|
154
|
+
The meta state can be updated at runtime via `kmClient.metaStore`:
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
await kmClient.transact([kmClient.metaStore], ([meta]) => {
|
|
158
|
+
meta.title = "Game Room: Epic Battle";
|
|
159
|
+
meta.ogImage = "https://example.com/custom-preview.png";
|
|
160
|
+
});
|
|
161
|
+
```
|
|
162
|
+
|
|
115
163
|
## Dev Frame
|
|
116
164
|
|
|
117
165
|
The dev frame provides a multi-window view for testing different player modes simultaneously during development.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kokimoki/kit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"bson-objectid": "^2.0.4",
|
|
27
27
|
"colorjs.io": "^0.5.2",
|
|
28
28
|
"colornames": "^1.1.1",
|
|
29
|
+
"node-html-parser": "^7.0.1",
|
|
29
30
|
"yaml": "^2.7.0",
|
|
30
31
|
"zod": "^4.3.5"
|
|
31
32
|
},
|