@takuhon/core 1.0.0 → 1.3.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 +371 -7
- package/dist/index.js +975 -23
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/takuhon.schema.json +116 -2
package/package.json
CHANGED
package/takuhon.schema.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://takuhon.example/schemas/1.
|
|
3
|
+
"$id": "https://takuhon.example/schemas/1.3.0/takuhon.schema.json",
|
|
4
4
|
"title": "Takuhon Profile",
|
|
5
5
|
"description": "Portable profile data format consumed by @takuhon/core. The canonical contract for profile content authored as takuhon.json.",
|
|
6
6
|
"type": "object",
|
|
@@ -312,6 +312,23 @@
|
|
|
312
312
|
"order": { "type": "integer", "minimum": 0 }
|
|
313
313
|
}
|
|
314
314
|
},
|
|
315
|
+
"SkillCategory": {
|
|
316
|
+
"type": "object",
|
|
317
|
+
"additionalProperties": false,
|
|
318
|
+
"required": ["id", "label"],
|
|
319
|
+
"properties": {
|
|
320
|
+
"id": {
|
|
321
|
+
"type": "string",
|
|
322
|
+
"minLength": 1,
|
|
323
|
+
"maxLength": 64,
|
|
324
|
+
"description": "Matches the `category` value on the skills that belong to this group."
|
|
325
|
+
},
|
|
326
|
+
"label": {
|
|
327
|
+
"$ref": "#/$defs/LocalizedTitle",
|
|
328
|
+
"description": "Localized display heading for the group."
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
},
|
|
315
332
|
"Contact": {
|
|
316
333
|
"type": "object",
|
|
317
334
|
"additionalProperties": false,
|
|
@@ -362,7 +379,104 @@
|
|
|
362
379
|
"description": "Opt-in flag for first-party analytics. Default is false to keep takuhon privacy-respecting by default."
|
|
363
380
|
},
|
|
364
381
|
"activity": { "$ref": "#/$defs/ActivitySettings" },
|
|
365
|
-
"publicVisibility": { "$ref": "#/$defs/PublicVisibility" }
|
|
382
|
+
"publicVisibility": { "$ref": "#/$defs/PublicVisibility" },
|
|
383
|
+
"contact": { "$ref": "#/$defs/ContactSettings" },
|
|
384
|
+
"appearance": { "$ref": "#/$defs/AppearanceSettings" },
|
|
385
|
+
"skillCategories": {
|
|
386
|
+
"type": "array",
|
|
387
|
+
"maxItems": 50,
|
|
388
|
+
"items": { "$ref": "#/$defs/SkillCategory" },
|
|
389
|
+
"description": "Ordered skill-category display groups (added in 1.3.0). When present, the rendered profile groups skills by their `category` under these localized headings, in array order; absent = the flat skill list. A skill whose `category` is not listed here (or which has none) renders in a trailing group so nothing is dropped."
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
},
|
|
393
|
+
"AppearanceSettings": {
|
|
394
|
+
"type": "object",
|
|
395
|
+
"additionalProperties": false,
|
|
396
|
+
"description": "Opt-in design tokens for the rendered profile (added in 1.2.0). A declarative re-skin seam: owners override the standard renderer's built-in color and font defaults. This is a token map only, not arbitrary CSS — every value is length- and pattern-constrained so it cannot break out of the inline <style>. Overriding tokens re-skins the page but cannot re-layout it (spacing/radius/type-scale are intentionally not exposed). Absent = the built-in defaults are used unchanged.",
|
|
397
|
+
"properties": {
|
|
398
|
+
"fontFamily": {
|
|
399
|
+
"type": "string",
|
|
400
|
+
"minLength": 1,
|
|
401
|
+
"maxLength": 256,
|
|
402
|
+
"pattern": "^[A-Za-z0-9\\s,'\"._-]+$",
|
|
403
|
+
"description": "CSS font-family stack for the page body, e.g. \"Inter, system-ui, sans-serif\". Quotes and commas are allowed; CSS-structural characters (; { } < >) are not."
|
|
404
|
+
},
|
|
405
|
+
"colors": {
|
|
406
|
+
"$ref": "#/$defs/AppearanceColors",
|
|
407
|
+
"description": "Light-mode (:root) color overrides."
|
|
408
|
+
},
|
|
409
|
+
"colorsDark": {
|
|
410
|
+
"$ref": "#/$defs/AppearanceColors",
|
|
411
|
+
"description": "Dark-mode (prefers-color-scheme: dark) color overrides. Note: until the standard renderer ships a default dark palette, only the keys set here change in dark mode."
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
"AppearanceColors": {
|
|
416
|
+
"type": "object",
|
|
417
|
+
"additionalProperties": false,
|
|
418
|
+
"description": "A set of overridable color tokens. Each value is a CSS color (hex, rgb()/rgba(), hsl()/hsla(), or a named color); CSS-structural characters (; { } < > \" ' \\) are disallowed so a value cannot escape the inline <style>.",
|
|
419
|
+
"properties": {
|
|
420
|
+
"bg": { "$ref": "#/$defs/CssColor", "description": "Page background." },
|
|
421
|
+
"surface": {
|
|
422
|
+
"$ref": "#/$defs/CssColor",
|
|
423
|
+
"description": "Raised surfaces such as skill/tag chips."
|
|
424
|
+
},
|
|
425
|
+
"text": { "$ref": "#/$defs/CssColor", "description": "Primary body text." },
|
|
426
|
+
"textMuted": {
|
|
427
|
+
"$ref": "#/$defs/CssColor",
|
|
428
|
+
"description": "Secondary/muted text (taglines, meta, captions)."
|
|
429
|
+
},
|
|
430
|
+
"border": { "$ref": "#/$defs/CssColor", "description": "Hairline borders and rules." },
|
|
431
|
+
"accent": {
|
|
432
|
+
"$ref": "#/$defs/CssColor",
|
|
433
|
+
"description": "Accent color for emphasis and focus affordances."
|
|
434
|
+
},
|
|
435
|
+
"primary": {
|
|
436
|
+
"$ref": "#/$defs/CssColor",
|
|
437
|
+
"description": "Primary interactive color, e.g. links."
|
|
438
|
+
},
|
|
439
|
+
"primaryContrast": {
|
|
440
|
+
"$ref": "#/$defs/CssColor",
|
|
441
|
+
"description": "Foreground color used on top of the primary color."
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
"CssColor": {
|
|
446
|
+
"type": "string",
|
|
447
|
+
"minLength": 1,
|
|
448
|
+
"maxLength": 64,
|
|
449
|
+
"pattern": "^(?:#[0-9A-Fa-f]{3,8}|[A-Za-z]+|(?:rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color)\\([A-Za-z0-9.,%/\\s-]*\\))$",
|
|
450
|
+
"description": "A CSS color value, restricted to a safe allowlist: a hex color (#rgb/#rgba/#rrggbb/#rrggbbaa), a bare keyword (named colors, currentColor, transparent), or a color function (rgb/rgba/hsl/hsla/hwb/lab/lch/oklab/oklch/color). url(), image-set(), var(), and other fetch- or reference-bearing functions are intentionally excluded so a value can never trigger an external request or escape the inline <style>."
|
|
451
|
+
},
|
|
452
|
+
"ContactSettings": {
|
|
453
|
+
"type": "object",
|
|
454
|
+
"additionalProperties": false,
|
|
455
|
+
"description": "Opt-in contact form configuration (added in 1.1.0). Only public values live here; the Turnstile site key is safe to embed in the page. The Turnstile secret, the recipient address, and the From label are provisioned out of band as environment configuration and are never stored in takuhon.json. Adapters that support the form mount the widget and a POST endpoint when 'enabled' is true.",
|
|
456
|
+
"properties": {
|
|
457
|
+
"enabled": {
|
|
458
|
+
"type": "boolean",
|
|
459
|
+
"default": false,
|
|
460
|
+
"description": "Master switch. When false (the default), no contact form is mounted even if a site key is present."
|
|
461
|
+
},
|
|
462
|
+
"turnstileSiteKey": {
|
|
463
|
+
"type": "string",
|
|
464
|
+
"minLength": 1,
|
|
465
|
+
"maxLength": 128,
|
|
466
|
+
"description": "Public Cloudflare Turnstile site key, safe to embed in the page. Without it the widget is not mounted."
|
|
467
|
+
},
|
|
468
|
+
"endpoint": {
|
|
469
|
+
"type": "string",
|
|
470
|
+
"minLength": 1,
|
|
471
|
+
"maxLength": 2048,
|
|
472
|
+
"description": "Override the POST endpoint the widget submits to. Defaults to /api/contact on the same origin."
|
|
473
|
+
},
|
|
474
|
+
"subjectPrefix": {
|
|
475
|
+
"type": "string",
|
|
476
|
+
"minLength": 1,
|
|
477
|
+
"maxLength": 128,
|
|
478
|
+
"description": "Subject prefix for the delivered email, e.g. '[example.com contact]'."
|
|
479
|
+
}
|
|
366
480
|
}
|
|
367
481
|
},
|
|
368
482
|
"PublicVisibility": {
|