me3-protocol 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +14 -0
- package/dist/index.js +49 -0
- package/examples/full.json +9 -0
- package/package.json +1 -1
- package/schema.json +38 -0
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,18 @@ export interface Me3Page {
|
|
|
14
14
|
/** Whether to show in navigation */
|
|
15
15
|
visible: boolean;
|
|
16
16
|
}
|
|
17
|
+
export interface Me3Post {
|
|
18
|
+
/** URL-friendly identifier */
|
|
19
|
+
slug: string;
|
|
20
|
+
/** Display name for listing */
|
|
21
|
+
title: string;
|
|
22
|
+
/** Path to markdown file (relative to me.json) */
|
|
23
|
+
file: string;
|
|
24
|
+
/** ISO publish date (optional) */
|
|
25
|
+
publishedAt?: string;
|
|
26
|
+
/** Short excerpt for archive/listing (optional) */
|
|
27
|
+
excerpt?: string;
|
|
28
|
+
}
|
|
17
29
|
export interface Me3Links {
|
|
18
30
|
website?: string;
|
|
19
31
|
github?: string;
|
|
@@ -130,6 +142,8 @@ export interface Me3Profile {
|
|
|
130
142
|
buttons?: Me3Button[];
|
|
131
143
|
/** Custom pages (markdown) */
|
|
132
144
|
pages?: Me3Page[];
|
|
145
|
+
/** Blog posts (markdown) */
|
|
146
|
+
posts?: Me3Post[];
|
|
133
147
|
/**
|
|
134
148
|
* Custom footer configuration.
|
|
135
149
|
* - `undefined`: default footer behavior (renderer-defined)
|
package/dist/index.js
CHANGED
|
@@ -277,6 +277,55 @@ function validateProfile(data) {
|
|
|
277
277
|
});
|
|
278
278
|
}
|
|
279
279
|
}
|
|
280
|
+
// Posts (optional)
|
|
281
|
+
if (profile.posts !== undefined) {
|
|
282
|
+
const posts = profile.posts;
|
|
283
|
+
if (!Array.isArray(posts)) {
|
|
284
|
+
errors.push({ field: "posts", message: "Posts must be an array" });
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
posts.forEach((post, index) => {
|
|
288
|
+
if (!post || typeof post !== "object") {
|
|
289
|
+
errors.push({
|
|
290
|
+
field: `posts[${index}]`,
|
|
291
|
+
message: "Post must be an object",
|
|
292
|
+
});
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
if (!post.slug || typeof post.slug !== "string") {
|
|
296
|
+
errors.push({
|
|
297
|
+
field: `posts[${index}].slug`,
|
|
298
|
+
message: "Post slug is required",
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
if (!post.title || typeof post.title !== "string") {
|
|
302
|
+
errors.push({
|
|
303
|
+
field: `posts[${index}].title`,
|
|
304
|
+
message: "Post title is required",
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (!post.file || typeof post.file !== "string") {
|
|
308
|
+
errors.push({
|
|
309
|
+
field: `posts[${index}].file`,
|
|
310
|
+
message: "Post file is required",
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
if (post.publishedAt !== undefined &&
|
|
314
|
+
typeof post.publishedAt !== "string") {
|
|
315
|
+
errors.push({
|
|
316
|
+
field: `posts[${index}].publishedAt`,
|
|
317
|
+
message: "Post publishedAt must be a string",
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
if (post.excerpt !== undefined && typeof post.excerpt !== "string") {
|
|
321
|
+
errors.push({
|
|
322
|
+
field: `posts[${index}].excerpt`,
|
|
323
|
+
message: "Post excerpt must be a string",
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
280
329
|
// Intents (optional)
|
|
281
330
|
if (profile.intents !== undefined) {
|
|
282
331
|
if (typeof profile.intents !== "object" || profile.intents === null) {
|
package/examples/full.json
CHANGED
|
@@ -28,6 +28,15 @@
|
|
|
28
28
|
"pages": [
|
|
29
29
|
{ "slug": "about", "title": "About", "file": "about.md", "visible": true }
|
|
30
30
|
],
|
|
31
|
+
"posts": [
|
|
32
|
+
{
|
|
33
|
+
"slug": "hello-world",
|
|
34
|
+
"title": "Hello World",
|
|
35
|
+
"file": "blog/hello-world.md",
|
|
36
|
+
"publishedAt": "2026-01-29T12:00:00.000Z",
|
|
37
|
+
"excerpt": "A short welcome post for the blog."
|
|
38
|
+
}
|
|
39
|
+
],
|
|
31
40
|
"intents": {
|
|
32
41
|
"subscribe": {
|
|
33
42
|
"enabled": true,
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -282,6 +282,37 @@
|
|
|
282
282
|
],
|
|
283
283
|
"type": "object"
|
|
284
284
|
},
|
|
285
|
+
"Me3Post": {
|
|
286
|
+
"additionalProperties": false,
|
|
287
|
+
"properties": {
|
|
288
|
+
"excerpt": {
|
|
289
|
+
"description": "Short excerpt for archive/listing (optional)",
|
|
290
|
+
"type": "string"
|
|
291
|
+
},
|
|
292
|
+
"file": {
|
|
293
|
+
"description": "Path to markdown file (relative to me.json)",
|
|
294
|
+
"type": "string"
|
|
295
|
+
},
|
|
296
|
+
"publishedAt": {
|
|
297
|
+
"description": "ISO publish date (optional)",
|
|
298
|
+
"type": "string"
|
|
299
|
+
},
|
|
300
|
+
"slug": {
|
|
301
|
+
"description": "URL-friendly identifier",
|
|
302
|
+
"type": "string"
|
|
303
|
+
},
|
|
304
|
+
"title": {
|
|
305
|
+
"description": "Display name for listing",
|
|
306
|
+
"type": "string"
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
"required": [
|
|
310
|
+
"slug",
|
|
311
|
+
"title",
|
|
312
|
+
"file"
|
|
313
|
+
],
|
|
314
|
+
"type": "object"
|
|
315
|
+
},
|
|
285
316
|
"Me3Profile": {
|
|
286
317
|
"additionalProperties": false,
|
|
287
318
|
"properties": {
|
|
@@ -343,6 +374,13 @@
|
|
|
343
374
|
},
|
|
344
375
|
"type": "array"
|
|
345
376
|
},
|
|
377
|
+
"posts": {
|
|
378
|
+
"description": "Blog posts (markdown)",
|
|
379
|
+
"items": {
|
|
380
|
+
"$ref": "#/definitions/Me3Post"
|
|
381
|
+
},
|
|
382
|
+
"type": "array"
|
|
383
|
+
},
|
|
346
384
|
"version": {
|
|
347
385
|
"description": "Protocol version",
|
|
348
386
|
"type": "string"
|