@takuhon/core 1.1.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 CHANGED
@@ -1,5 +1,5 @@
1
1
  var $schema = "https://json-schema.org/draft/2020-12/schema";
2
- var $id = "https://takuhon.example/schemas/1.1.0/takuhon.schema.json";
2
+ var $id = "https://takuhon.example/schemas/1.3.0/takuhon.schema.json";
3
3
  var title = "Takuhon Profile";
4
4
  var description = "Portable profile data format consumed by @takuhon/core. The canonical contract for profile content authored as takuhon.json.";
5
5
  var type = "object";
@@ -496,6 +496,26 @@ var $defs = {
496
496
  }
497
497
  }
498
498
  },
499
+ SkillCategory: {
500
+ type: "object",
501
+ additionalProperties: false,
502
+ required: [
503
+ "id",
504
+ "label"
505
+ ],
506
+ properties: {
507
+ id: {
508
+ type: "string",
509
+ minLength: 1,
510
+ maxLength: 64,
511
+ description: "Matches the `category` value on the skills that belong to this group."
512
+ },
513
+ label: {
514
+ $ref: "#/$defs/LocalizedTitle",
515
+ description: "Localized display heading for the group."
516
+ }
517
+ }
518
+ },
499
519
  Contact: {
500
520
  type: "object",
501
521
  additionalProperties: false,
@@ -569,9 +589,88 @@ var $defs = {
569
589
  },
570
590
  contact: {
571
591
  $ref: "#/$defs/ContactSettings"
592
+ },
593
+ appearance: {
594
+ $ref: "#/$defs/AppearanceSettings"
595
+ },
596
+ skillCategories: {
597
+ type: "array",
598
+ maxItems: 50,
599
+ items: {
600
+ $ref: "#/$defs/SkillCategory"
601
+ },
602
+ 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."
603
+ }
604
+ }
605
+ },
606
+ AppearanceSettings: {
607
+ type: "object",
608
+ additionalProperties: false,
609
+ 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.",
610
+ properties: {
611
+ fontFamily: {
612
+ type: "string",
613
+ minLength: 1,
614
+ maxLength: 256,
615
+ pattern: "^[A-Za-z0-9\\s,'\"._-]+$",
616
+ 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."
617
+ },
618
+ colors: {
619
+ $ref: "#/$defs/AppearanceColors",
620
+ description: "Light-mode (:root) color overrides."
621
+ },
622
+ colorsDark: {
623
+ $ref: "#/$defs/AppearanceColors",
624
+ 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."
625
+ }
626
+ }
627
+ },
628
+ AppearanceColors: {
629
+ type: "object",
630
+ additionalProperties: false,
631
+ 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>.",
632
+ properties: {
633
+ bg: {
634
+ $ref: "#/$defs/CssColor",
635
+ description: "Page background."
636
+ },
637
+ surface: {
638
+ $ref: "#/$defs/CssColor",
639
+ description: "Raised surfaces such as skill/tag chips."
640
+ },
641
+ text: {
642
+ $ref: "#/$defs/CssColor",
643
+ description: "Primary body text."
644
+ },
645
+ textMuted: {
646
+ $ref: "#/$defs/CssColor",
647
+ description: "Secondary/muted text (taglines, meta, captions)."
648
+ },
649
+ border: {
650
+ $ref: "#/$defs/CssColor",
651
+ description: "Hairline borders and rules."
652
+ },
653
+ accent: {
654
+ $ref: "#/$defs/CssColor",
655
+ description: "Accent color for emphasis and focus affordances."
656
+ },
657
+ primary: {
658
+ $ref: "#/$defs/CssColor",
659
+ description: "Primary interactive color, e.g. links."
660
+ },
661
+ primaryContrast: {
662
+ $ref: "#/$defs/CssColor",
663
+ description: "Foreground color used on top of the primary color."
572
664
  }
573
665
  }
574
666
  },
667
+ CssColor: {
668
+ type: "string",
669
+ minLength: 1,
670
+ maxLength: 64,
671
+ 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-]*\\))$",
672
+ 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>."
673
+ },
575
674
  ContactSettings: {
576
675
  type: "object",
577
676
  additionalProperties: false,
@@ -1847,6 +1946,23 @@ declare const schema: {
1847
1946
  };
1848
1947
  };
1849
1948
  };
1949
+ SkillCategory: {
1950
+ type: string;
1951
+ additionalProperties: boolean;
1952
+ required: string[];
1953
+ properties: {
1954
+ id: {
1955
+ type: string;
1956
+ minLength: number;
1957
+ maxLength: number;
1958
+ description: string;
1959
+ };
1960
+ label: {
1961
+ $ref: string;
1962
+ description: string;
1963
+ };
1964
+ };
1965
+ };
1850
1966
  Contact: {
1851
1967
  type: string;
1852
1968
  additionalProperties: boolean;
@@ -1918,8 +2034,87 @@ declare const schema: {
1918
2034
  contact: {
1919
2035
  $ref: string;
1920
2036
  };
2037
+ appearance: {
2038
+ $ref: string;
2039
+ };
2040
+ skillCategories: {
2041
+ type: string;
2042
+ maxItems: number;
2043
+ items: {
2044
+ $ref: string;
2045
+ };
2046
+ description: string;
2047
+ };
2048
+ };
2049
+ };
2050
+ AppearanceSettings: {
2051
+ type: string;
2052
+ additionalProperties: boolean;
2053
+ description: string;
2054
+ properties: {
2055
+ fontFamily: {
2056
+ type: string;
2057
+ minLength: number;
2058
+ maxLength: number;
2059
+ pattern: string;
2060
+ description: string;
2061
+ };
2062
+ colors: {
2063
+ $ref: string;
2064
+ description: string;
2065
+ };
2066
+ colorsDark: {
2067
+ $ref: string;
2068
+ description: string;
2069
+ };
2070
+ };
2071
+ };
2072
+ AppearanceColors: {
2073
+ type: string;
2074
+ additionalProperties: boolean;
2075
+ description: string;
2076
+ properties: {
2077
+ bg: {
2078
+ $ref: string;
2079
+ description: string;
2080
+ };
2081
+ surface: {
2082
+ $ref: string;
2083
+ description: string;
2084
+ };
2085
+ text: {
2086
+ $ref: string;
2087
+ description: string;
2088
+ };
2089
+ textMuted: {
2090
+ $ref: string;
2091
+ description: string;
2092
+ };
2093
+ border: {
2094
+ $ref: string;
2095
+ description: string;
2096
+ };
2097
+ accent: {
2098
+ $ref: string;
2099
+ description: string;
2100
+ };
2101
+ primary: {
2102
+ $ref: string;
2103
+ description: string;
2104
+ };
2105
+ primaryContrast: {
2106
+ $ref: string;
2107
+ description: string;
2108
+ };
1921
2109
  };
1922
2110
  };
2111
+ CssColor: {
2112
+ type: string;
2113
+ minLength: number;
2114
+ maxLength: number;
2115
+ pattern: string;
2116
+ description: string;
2117
+ };
1923
2118
  ContactSettings: {
1924
2119
  type: string;
1925
2120
  additionalProperties: boolean;
@@ -2989,6 +3184,71 @@ interface Settings {
2989
3184
  publicVisibility?: PublicVisibility;
2990
3185
  /** Opt-in contact form (added in 1.1.0). Absent = no contact form. */
2991
3186
  contact?: ContactSettings;
3187
+ /** Opt-in design tokens for the rendered profile (added in 1.2.0). Absent = built-in defaults. */
3188
+ appearance?: AppearanceSettings;
3189
+ /**
3190
+ * Ordered skill-category display groups (added in 1.3.0). When present, the
3191
+ * rendered profile groups skills by their `category` under these localized
3192
+ * headings, in array order; absent = the flat skill list. A skill whose
3193
+ * `category` is unlisted (or absent) renders in a trailing group.
3194
+ */
3195
+ skillCategories?: SkillCategory[];
3196
+ }
3197
+ /**
3198
+ * One skill-category display group (added in 1.3.0). Maps a `Skill.category`
3199
+ * value to a localized heading; the array position in {@link
3200
+ * Settings.skillCategories} defines the group's display order.
3201
+ */
3202
+ interface SkillCategory {
3203
+ /** Matches the `category` value on the skills that belong to this group. */
3204
+ id: string;
3205
+ /** Localized display heading for the group. */
3206
+ label: LocalizedTitle;
3207
+ }
3208
+ /**
3209
+ * Opt-in design tokens for the rendered profile (added in 1.2.0).
3210
+ *
3211
+ * A declarative re-skin seam: owners override the standard renderer's built-in
3212
+ * color and font defaults. This is a token map only — never arbitrary CSS — so
3213
+ * every value is length- and pattern-constrained (see the schema) and cannot
3214
+ * break out of the inline `<style>`. Overriding tokens re-skins the page but
3215
+ * cannot re-layout it; spacing, radius, and the type scale are intentionally
3216
+ * not exposed. An absent block leaves the built-in defaults unchanged.
3217
+ */
3218
+ interface AppearanceSettings {
3219
+ /** CSS font-family stack for the page body, e.g. `"Inter, system-ui, sans-serif"`. */
3220
+ fontFamily?: string;
3221
+ /** Light-mode (`:root`) color overrides. */
3222
+ colors?: AppearanceColors;
3223
+ /**
3224
+ * Dark-mode (`prefers-color-scheme: dark`) color overrides. Until the
3225
+ * standard renderer ships a default dark palette, only the keys set here
3226
+ * change in dark mode.
3227
+ */
3228
+ colorsDark?: AppearanceColors;
3229
+ }
3230
+ /**
3231
+ * Overridable color tokens (added in 1.2.0). Each value is a CSS color (hex,
3232
+ * `rgb()`/`rgba()`, `hsl()`/`hsla()`, or a named color); CSS-structural
3233
+ * characters are disallowed so a value cannot escape the inline `<style>`.
3234
+ */
3235
+ interface AppearanceColors {
3236
+ /** Page background. */
3237
+ bg?: string;
3238
+ /** Raised surfaces such as skill/tag chips. */
3239
+ surface?: string;
3240
+ /** Primary body text. */
3241
+ text?: string;
3242
+ /** Secondary/muted text (taglines, meta, captions). */
3243
+ textMuted?: string;
3244
+ /** Hairline borders and rules. */
3245
+ border?: string;
3246
+ /** Accent color for emphasis and focus affordances. */
3247
+ accent?: string;
3248
+ /** Primary interactive color, e.g. links. */
3249
+ primary?: string;
3250
+ /** Foreground color used on top of the primary color. */
3251
+ primaryContrast?: string;
2992
3252
  }
2993
3253
  /**
2994
3254
  * Owner-curated configuration for the opt-in contact form (added in 1.1.0).
@@ -3339,13 +3599,31 @@ interface LocalizedRecommendation extends VisibilityControlled {
3339
3599
  relatedEducationId?: Slug;
3340
3600
  order?: number;
3341
3601
  }
3602
+ /**
3603
+ * One skill-category group after locale resolution: the localized `label` map
3604
+ * collapsed to the single resolved string. See {@link SkillCategory}.
3605
+ */
3606
+ interface LocalizedSkillCategory {
3607
+ id: string;
3608
+ label: string;
3609
+ }
3610
+ /**
3611
+ * {@link Settings} after locale resolution. Identical to the raw settings
3612
+ * except `skillCategories` labels are collapsed to single resolved strings
3613
+ * ({@link LocalizedSkillCategory}); every other settings field is passed
3614
+ * through unchanged.
3615
+ */
3616
+ type LocalizedSettings = Omit<Settings, 'skillCategories'> & {
3617
+ skillCategories?: LocalizedSkillCategory[];
3618
+ };
3342
3619
  /**
3343
3620
  * A takuhon document with every localized map flattened to a single string,
3344
3621
  * plus a `resolvedLocale` field recording which tag was actually used as the
3345
3622
  * head of the fallback chain. `resolveLocale()` returns this shape.
3346
3623
  *
3347
- * `Skill`, `Contact`, `Settings`, and `Meta` carry no localized fields and
3348
- * pass through unchanged.
3624
+ * `Skill`, `Contact`, and `Meta` carry no localized fields and pass through
3625
+ * unchanged; `Settings` passes through too, except its `skillCategories`
3626
+ * labels are resolved to the single locale string (see {@link LocalizedSettings}).
3349
3627
  */
3350
3628
  interface LocalizedTakuhon {
3351
3629
  schemaVersion: string;
@@ -3366,7 +3644,7 @@ interface LocalizedTakuhon {
3366
3644
  testScores: LocalizedTestScore[];
3367
3645
  recommendations: LocalizedRecommendation[];
3368
3646
  contact: Contact;
3369
- settings: Settings;
3647
+ settings: LocalizedSettings;
3370
3648
  meta: Meta;
3371
3649
  /**
3372
3650
  * The locale tag that was matched first by the fallback chain and used as
@@ -3412,7 +3690,7 @@ interface LocalizedTakuhon {
3412
3690
  * versions whose JSON Schema this package literally bundles, not the full
3413
3691
  * support window seen by end users.
3414
3692
  */
3415
- declare const SUPPORTED_SCHEMA_VERSIONS: readonly ["0.1.0", "0.2.0", "0.3.0", "0.4.0", "0.5.0", "0.6.0", "0.7.0", "1.0.0", "1.1.0"];
3693
+ declare const SUPPORTED_SCHEMA_VERSIONS: readonly ["0.1.0", "0.2.0", "0.3.0", "0.4.0", "0.5.0", "0.6.0", "0.7.0", "1.0.0", "1.1.0", "1.2.0", "1.3.0"];
3416
3694
  /**
3417
3695
  * A single validation failure.
3418
3696
  *
@@ -4542,6 +4820,6 @@ declare function stripImageMetadata(bytes: Uint8Array, mime: AcceptedImageMime):
4542
4820
  * A takuhon profile document's `schemaVersion` field must be migrate-compatible
4543
4821
  * with this version. See operational-lifecycle docs for the migration policy.
4544
4822
  */
4545
- declare const SCHEMA_VERSION = "1.1.0";
4823
+ declare const SCHEMA_VERSION = "1.3.0";
4546
4824
 
4547
- export { ACCEPTED_IMAGE_MIME_TYPES, type AcceptedImageMime, type ActivitySettings, type ActivitySnapshot, type ActivityStorage, type Address, type AssetOptions, type AssetRecord, type Avatar, type Career, type Certification, type CodingTime, ConflictError, type Contact, type ContentLicense, type ContentLicenseAttribution, type ContributionCalendar, type ContributionDay, type Course, type CvDocument, type CvHeader, type CvSection, type CvSectionKind, DARK_PALETTE, type Education, type ExportOptions, type ExportedTakuhon, type GravatarOptions, type Honor, IMAGE_EXTENSIONS, type ImageInfo, ImportError, type Iso3166Alpha2, type IsoDateTime, LIGHT_PALETTE, type Language, type LanguageBreakdown, type LanguageProficiency, type Link, type LinkBuiltin, type LinkCustom, type LinkType, type LocaleTag, type LocalizedAddress, type LocalizedAvatar, type LocalizedBody, type LocalizedCareer, type LocalizedCertification, type LocalizedCourse, type LocalizedEducation, type LocalizedHonor, type LocalizedLanguage, type LocalizedLink, type LocalizedLinkBuiltin, type LocalizedLinkCustom, type LocalizedMembership, type LocalizedPatent, type LocalizedProfile, type LocalizedProject, type LocalizedPublication, type LocalizedRecommendation, type LocalizedRecommendationAuthor, type LocalizedTakuhon, type LocalizedTestScore, type LocalizedTitle, type LocalizedVolunteering, MAX_IMAGE_BYTES, MAX_IMAGE_DIMENSION, MAX_IMAGE_FRAMES, MCP_PROFILE_SECTIONS, MCP_RESOURCES, MCP_TOOLS, type McpInputSchema, type McpProfileSection, McpRequestError, type McpResourceDefinition, type McpResourceResult, type McpToolDefinition, type McpToolResult, type Membership, type Meta, type MetaPrivacy, type Migration, MigrationError, type NormalizedTakuhon, NotFoundError, type Palette, type Patent, type PatentStatus, type Profile, type Project, type PublicVisibility, type Publication, RANK_FULL_CODING_HOURS, RANK_FULL_CONTRIBUTIONS, RANK_TIER_THRESHOLDS, type RankInput, type RankTier, type RankTierLabel, type Recommendation, type RecommendationAuthor, type RenderActivitySvgOptions, SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, type Schema, type Settings, type Skill, type Slug, StorageError, type Takuhon, type TakuhonAssetStorage, type TakuhonStorage, type TestScore, type ValidationError, type ValidationResult, type Volunteering, type YearMonth, applyPublicPrivacyFilter, computeLanguagePercentages, deriveCv, deriveRankTier, detectImageMime, executeMcpTool, exportTakuhon, formatCodingTime, formatDate, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, getPresentLabel, gravatarUrl, importTakuhon, isActivitySnapshot, migrateTakuhon, migrations, normalize, readImageInfo, readMcpResource, renderActivitySvg, resolveLocale, schema, stripImageMetadata, validate };
4825
+ export { ACCEPTED_IMAGE_MIME_TYPES, type AcceptedImageMime, type ActivitySettings, type ActivitySnapshot, type ActivityStorage, type Address, type AppearanceColors, type AppearanceSettings, type AssetOptions, type AssetRecord, type Avatar, type Career, type Certification, type CodingTime, ConflictError, type Contact, type ContentLicense, type ContentLicenseAttribution, type ContributionCalendar, type ContributionDay, type Course, type CvDocument, type CvHeader, type CvSection, type CvSectionKind, DARK_PALETTE, type Education, type ExportOptions, type ExportedTakuhon, type GravatarOptions, type Honor, IMAGE_EXTENSIONS, type ImageInfo, ImportError, type Iso3166Alpha2, type IsoDateTime, LIGHT_PALETTE, type Language, type LanguageBreakdown, type LanguageProficiency, type Link, type LinkBuiltin, type LinkCustom, type LinkType, type LocaleTag, type LocalizedAddress, type LocalizedAvatar, type LocalizedBody, type LocalizedCareer, type LocalizedCertification, type LocalizedCourse, type LocalizedEducation, type LocalizedHonor, type LocalizedLanguage, type LocalizedLink, type LocalizedLinkBuiltin, type LocalizedLinkCustom, type LocalizedMembership, type LocalizedPatent, type LocalizedProfile, type LocalizedProject, type LocalizedPublication, type LocalizedRecommendation, type LocalizedRecommendationAuthor, type LocalizedTakuhon, type LocalizedTestScore, type LocalizedTitle, type LocalizedVolunteering, MAX_IMAGE_BYTES, MAX_IMAGE_DIMENSION, MAX_IMAGE_FRAMES, MCP_PROFILE_SECTIONS, MCP_RESOURCES, MCP_TOOLS, type McpInputSchema, type McpProfileSection, McpRequestError, type McpResourceDefinition, type McpResourceResult, type McpToolDefinition, type McpToolResult, type Membership, type Meta, type MetaPrivacy, type Migration, MigrationError, type NormalizedTakuhon, NotFoundError, type Palette, type Patent, type PatentStatus, type Profile, type Project, type PublicVisibility, type Publication, RANK_FULL_CODING_HOURS, RANK_FULL_CONTRIBUTIONS, RANK_TIER_THRESHOLDS, type RankInput, type RankTier, type RankTierLabel, type Recommendation, type RecommendationAuthor, type RenderActivitySvgOptions, SCHEMA_VERSION, SUPPORTED_SCHEMA_VERSIONS, type Schema, type Settings, type Skill, type Slug, StorageError, type Takuhon, type TakuhonAssetStorage, type TakuhonStorage, type TestScore, type ValidationError, type ValidationResult, type Volunteering, type YearMonth, applyPublicPrivacyFilter, computeLanguagePercentages, deriveCv, deriveRankTier, detectImageMime, executeMcpTool, exportTakuhon, formatCodingTime, formatDate, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, getPresentLabel, gravatarUrl, importTakuhon, isActivitySnapshot, migrateTakuhon, migrations, normalize, readImageInfo, readMcpResource, renderActivitySvg, resolveLocale, schema, stripImageMetadata, validate };