@takuhon/core 0.14.0 → 0.15.1
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 +52 -3
- package/dist/index.js +45 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -3697,20 +3697,69 @@ declare class ConflictError extends StorageError {
|
|
|
3697
3697
|
* snapshot always renders the same markup, so both rendering surfaces (the
|
|
3698
3698
|
* static HTML export and the React profile) and their tests stay in lockstep.
|
|
3699
3699
|
*
|
|
3700
|
+
* The card paints an **opaque background rectangle** first, so it stays legible
|
|
3701
|
+
* wherever it is embedded — including a GitHub README served through the Camo
|
|
3702
|
+
* image proxy, where no surrounding page styles apply and a transparent card
|
|
3703
|
+
* would render invisibly on a dark theme. The colour set is supplied by a
|
|
3704
|
+
* {@link Palette}: {@link renderActivitySvg} defaults to {@link LIGHT_PALETTE},
|
|
3705
|
+
* and a transport (a Worker route, the CLI build) can pass {@link DARK_PALETTE}
|
|
3706
|
+
* to serve a dark variant. Both palettes are plain data, so the render stays
|
|
3707
|
+
* deterministic.
|
|
3708
|
+
*
|
|
3700
3709
|
* Every snapshot-derived string (language names, dates) is XML-escaped before
|
|
3701
3710
|
* it reaches the markup: language names come from an external API and are
|
|
3702
3711
|
* treated as untrusted. An empty snapshot (no metric fields) renders to `''`
|
|
3703
3712
|
* so callers can omit the section with a truthiness check.
|
|
3704
3713
|
*/
|
|
3705
3714
|
|
|
3715
|
+
/**
|
|
3716
|
+
* Colour set for an activity card. Kept as plain data (no CSS variables, no
|
|
3717
|
+
* `currentColor`) so the rendered SVG is fully self-contained and legible when
|
|
3718
|
+
* served as an image through Camo, where no page styles apply.
|
|
3719
|
+
*/
|
|
3720
|
+
interface Palette {
|
|
3721
|
+
/** Fill of the opaque background rectangle behind the whole card. */
|
|
3722
|
+
background: string;
|
|
3723
|
+
/** Primary text (language legend, coding-time figure). */
|
|
3724
|
+
text: string;
|
|
3725
|
+
/** Secondary text (captions, rank score, "Last synced"). */
|
|
3726
|
+
muted: string;
|
|
3727
|
+
/** Accent fill (the rank badge disc). */
|
|
3728
|
+
accent: string;
|
|
3729
|
+
/**
|
|
3730
|
+
* Order-based palette for the language bar and its legend chips; entries are
|
|
3731
|
+
* assigned to the top languages in order, and anything past the end (or the
|
|
3732
|
+
* folded "Other" segment) uses {@link Palette.otherColor}.
|
|
3733
|
+
*/
|
|
3734
|
+
languageColors: readonly string[];
|
|
3735
|
+
/** Colour of the folded "Other" language segment. */
|
|
3736
|
+
otherColor: string;
|
|
3737
|
+
/** Five-step contribution heat ramp, lowest (zero) first. */
|
|
3738
|
+
heatColors: readonly string[];
|
|
3739
|
+
}
|
|
3740
|
+
/** Default palette: dark text on an opaque white card. */
|
|
3741
|
+
declare const LIGHT_PALETTE: Palette;
|
|
3742
|
+
/**
|
|
3743
|
+
* Dark variant: light text on an opaque dark card (tuned to read on a GitHub
|
|
3744
|
+
* dark-theme README). The heat ramp stays in the card's blue family rather than
|
|
3745
|
+
* borrowing GitHub's green, so light and dark cards look like the same design.
|
|
3746
|
+
*/
|
|
3747
|
+
declare const DARK_PALETTE: Palette;
|
|
3748
|
+
/** Options accepted by {@link renderActivitySvg}. */
|
|
3749
|
+
interface RenderActivitySvgOptions {
|
|
3750
|
+
/** Colour set to render with. Defaults to {@link LIGHT_PALETTE}. */
|
|
3751
|
+
palette?: Palette;
|
|
3752
|
+
}
|
|
3706
3753
|
/**
|
|
3707
3754
|
* Render the activity snapshot as a self-contained `<svg>` string, or `''`
|
|
3708
3755
|
* when the snapshot carries no metric data (so callers can omit the section).
|
|
3709
3756
|
* Sections render independently — whatever the snapshot holds is shown, the
|
|
3710
3757
|
* rest is left out — and `lastSyncedAt`'s date is always stamped in the footer
|
|
3711
|
-
* so staleness stays visible.
|
|
3758
|
+
* so staleness stays visible. Colours come from `options.palette`
|
|
3759
|
+
* ({@link LIGHT_PALETTE} by default); the card always paints an opaque
|
|
3760
|
+
* background so it stays legible when embedded as an image.
|
|
3712
3761
|
*/
|
|
3713
|
-
declare function renderActivitySvg(snapshot: ActivitySnapshot): string;
|
|
3762
|
+
declare function renderActivitySvg(snapshot: ActivitySnapshot, options?: RenderActivitySvgOptions): string;
|
|
3714
3763
|
|
|
3715
3764
|
/**
|
|
3716
3765
|
* Résumé / CV projection of a profile.
|
|
@@ -4010,4 +4059,4 @@ declare function stripImageMetadata(bytes: Uint8Array, mime: AcceptedImageMime):
|
|
|
4010
4059
|
*/
|
|
4011
4060
|
declare const SCHEMA_VERSION = "0.5.0";
|
|
4012
4061
|
|
|
4013
|
-
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, type Education, type ExportOptions, type ExportedTakuhon, type Honor, IMAGE_EXTENSIONS, type ImageInfo, ImportError, type Iso3166Alpha2, type IsoDateTime, 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 Patent, type PatentStatus, type Profile, type Project, type Publication, RANK_FULL_CODING_HOURS, RANK_FULL_CONTRIBUTIONS, RANK_TIER_THRESHOLDS, type RankInput, type RankTier, type RankTierLabel, type Recommendation, type RecommendationAuthor, 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, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, importTakuhon, isActivitySnapshot, migrateTakuhon, migrations, normalize, readImageInfo, readMcpResource, renderActivitySvg, resolveLocale, schema, stripImageMetadata, validate };
|
|
4062
|
+
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 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 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, generateJsonLd, generatePersonJsonLd, generateProfilePageJsonLd, importTakuhon, isActivitySnapshot, migrateTakuhon, migrations, normalize, readImageInfo, readMcpResource, renderActivitySvg, resolveLocale, schema, stripImageMetadata, validate };
|
package/dist/index.js
CHANGED
|
@@ -11413,18 +11413,30 @@ function deriveRankTier(input) {
|
|
|
11413
11413
|
var WIDTH = 520;
|
|
11414
11414
|
var PAD = 16;
|
|
11415
11415
|
var INNER = WIDTH - PAD * 2;
|
|
11416
|
-
var TEXT_COLOR = "#1a1a1a";
|
|
11417
|
-
var MUTED_COLOR = "#666666";
|
|
11418
|
-
var ACCENT_COLOR = "#0b5fff";
|
|
11419
11416
|
var FONT_FAMILY = "system-ui,-apple-system,Segoe UI,Roboto,sans-serif";
|
|
11420
|
-
var LANGUAGE_COLORS = ["#0b5fff", "#7c3aed", "#059669", "#d97706", "#dc2626", "#0891b2"];
|
|
11421
|
-
var OTHER_COLOR = "#9ca3af";
|
|
11422
11417
|
var MAX_LANGUAGES = 6;
|
|
11423
|
-
var HEAT_COLORS = ["#ebedf0", "#cce0ff", "#99c2ff", "#4d8aff", "#0b5fff"];
|
|
11424
11418
|
var CELL = 7;
|
|
11425
11419
|
var CELL_PITCH = 9;
|
|
11426
11420
|
var CALENDAR_ROWS = 7;
|
|
11427
11421
|
var MAX_CALENDAR_DAYS = 53 * CALENDAR_ROWS;
|
|
11422
|
+
var LIGHT_PALETTE = {
|
|
11423
|
+
background: "#ffffff",
|
|
11424
|
+
text: "#1a1a1a",
|
|
11425
|
+
muted: "#666666",
|
|
11426
|
+
accent: "#0b5fff",
|
|
11427
|
+
languageColors: ["#0b5fff", "#7c3aed", "#059669", "#d97706", "#dc2626", "#0891b2"],
|
|
11428
|
+
otherColor: "#9ca3af",
|
|
11429
|
+
heatColors: ["#ebedf0", "#cce0ff", "#99c2ff", "#4d8aff", "#0b5fff"]
|
|
11430
|
+
};
|
|
11431
|
+
var DARK_PALETTE = {
|
|
11432
|
+
background: "#0d1117",
|
|
11433
|
+
text: "#e6edf3",
|
|
11434
|
+
muted: "#9198a1",
|
|
11435
|
+
accent: "#4493f8",
|
|
11436
|
+
languageColors: ["#4493f8", "#a371f7", "#3fb950", "#d29922", "#f85149", "#39c5cf"],
|
|
11437
|
+
otherColor: "#6e7681",
|
|
11438
|
+
heatColors: ["#161b22", "#0a2c5e", "#11468f", "#1f6fdb", "#4493f8"]
|
|
11439
|
+
};
|
|
11428
11440
|
function escapeXml(value) {
|
|
11429
11441
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
11430
11442
|
}
|
|
@@ -11441,23 +11453,23 @@ function text(x, y, content, opts) {
|
|
|
11441
11453
|
const anchor = opts.anchor !== void 0 ? ` text-anchor="${opts.anchor}"` : "";
|
|
11442
11454
|
return `<text x="${String(x)}" y="${String(y)}" font-family="${FONT_FAMILY}" font-size="${String(opts.size)}" fill="${opts.fill}"${weight}${anchor}>${escapeXml(content)}</text>`;
|
|
11443
11455
|
}
|
|
11444
|
-
function caption(x, y, label) {
|
|
11445
|
-
return text(x, y, label, { size: 12, fill
|
|
11456
|
+
function caption(x, y, label, fill) {
|
|
11457
|
+
return text(x, y, label, { size: 12, fill, weight: 600 });
|
|
11446
11458
|
}
|
|
11447
11459
|
function rect(x, y, w, h, fill, rx = 0) {
|
|
11448
11460
|
const corner = rx > 0 ? ` rx="${String(rx)}"` : "";
|
|
11449
11461
|
return `<rect x="${String(round2(x))}" y="${String(y)}" width="${String(round2(w))}" height="${String(h)}" fill="${fill}"${corner}/>`;
|
|
11450
11462
|
}
|
|
11451
|
-
function languageSegments(languages) {
|
|
11463
|
+
function languageSegments(languages, palette) {
|
|
11452
11464
|
const segments = languages.slice(0, MAX_LANGUAGES).map((l, i) => ({
|
|
11453
11465
|
name: l.name,
|
|
11454
11466
|
percent: l.percent,
|
|
11455
|
-
color:
|
|
11467
|
+
color: palette.languageColors[i] ?? palette.otherColor
|
|
11456
11468
|
}));
|
|
11457
11469
|
const rest = languages.slice(MAX_LANGUAGES);
|
|
11458
11470
|
if (rest.length > 0) {
|
|
11459
11471
|
const percent = round2(rest.reduce((sum, l) => sum + l.percent, 0));
|
|
11460
|
-
segments.push({ name: "Other", percent, color:
|
|
11472
|
+
segments.push({ name: "Other", percent, color: palette.otherColor });
|
|
11461
11473
|
}
|
|
11462
11474
|
return segments.filter((s) => s.percent > 0);
|
|
11463
11475
|
}
|
|
@@ -11465,7 +11477,8 @@ function heatLevel(count, max) {
|
|
|
11465
11477
|
if (count <= 0) return 0;
|
|
11466
11478
|
return Math.min(4, Math.max(1, Math.ceil(count / max * 4)));
|
|
11467
11479
|
}
|
|
11468
|
-
function renderActivitySvg(snapshot) {
|
|
11480
|
+
function renderActivitySvg(snapshot, options = {}) {
|
|
11481
|
+
const palette = options.palette ?? LIGHT_PALETTE;
|
|
11469
11482
|
const hasLanguages = snapshot.languages !== void 0 && snapshot.languages.length > 0;
|
|
11470
11483
|
const hasContributions = snapshot.contributions !== void 0 && snapshot.contributions.days.length > 0;
|
|
11471
11484
|
const hasCodingTime = snapshot.codingTime !== void 0;
|
|
@@ -11474,9 +11487,9 @@ function renderActivitySvg(snapshot) {
|
|
|
11474
11487
|
const parts = [];
|
|
11475
11488
|
let y = PAD;
|
|
11476
11489
|
if (hasLanguages && snapshot.languages) {
|
|
11477
|
-
const segments = languageSegments(snapshot.languages);
|
|
11490
|
+
const segments = languageSegments(snapshot.languages, palette);
|
|
11478
11491
|
const total = segments.reduce((sum, s) => sum + s.percent, 0);
|
|
11479
|
-
parts.push(caption(PAD, y + 11, "Languages"));
|
|
11492
|
+
parts.push(caption(PAD, y + 11, "Languages", palette.muted));
|
|
11480
11493
|
y += 22;
|
|
11481
11494
|
let x = PAD;
|
|
11482
11495
|
for (const segment of segments) {
|
|
@@ -11493,7 +11506,7 @@ function renderActivitySvg(snapshot) {
|
|
|
11493
11506
|
parts.push(
|
|
11494
11507
|
text(cx + 16, cy + 9, `${segment.name} ${String(segment.percent)}%`, {
|
|
11495
11508
|
size: 12,
|
|
11496
|
-
fill:
|
|
11509
|
+
fill: palette.text
|
|
11497
11510
|
})
|
|
11498
11511
|
);
|
|
11499
11512
|
});
|
|
@@ -11503,13 +11516,18 @@ function renderActivitySvg(snapshot) {
|
|
|
11503
11516
|
const days = snapshot.contributions.days.slice(-MAX_CALENDAR_DAYS);
|
|
11504
11517
|
const max = days.reduce((m, d) => Math.max(m, d.count), 1);
|
|
11505
11518
|
parts.push(
|
|
11506
|
-
caption(
|
|
11519
|
+
caption(
|
|
11520
|
+
PAD,
|
|
11521
|
+
y + 11,
|
|
11522
|
+
`Contributions \xB7 ${groupDigits(snapshot.contributions.total)}`,
|
|
11523
|
+
palette.muted
|
|
11524
|
+
)
|
|
11507
11525
|
);
|
|
11508
11526
|
y += 22;
|
|
11509
11527
|
days.forEach((day, i) => {
|
|
11510
11528
|
const column = Math.floor(i / CALENDAR_ROWS);
|
|
11511
11529
|
const row = i % CALENDAR_ROWS;
|
|
11512
|
-
const fill =
|
|
11530
|
+
const fill = palette.heatColors[heatLevel(day.count, max)] ?? palette.heatColors[0];
|
|
11513
11531
|
parts.push(rect(PAD + column * CELL_PITCH, y + row * CELL_PITCH, CELL, CELL, fill, 1.5));
|
|
11514
11532
|
});
|
|
11515
11533
|
y += CALENDAR_ROWS * CELL_PITCH - (CELL_PITCH - CELL) + 12;
|
|
@@ -11518,21 +11536,21 @@ function renderActivitySvg(snapshot) {
|
|
|
11518
11536
|
const rankX = PAD + INNER - 120;
|
|
11519
11537
|
if (hasCodingTime && snapshot.codingTime) {
|
|
11520
11538
|
const t = snapshot.codingTime;
|
|
11521
|
-
parts.push(caption(PAD, y + 11, "Coding time"));
|
|
11539
|
+
parts.push(caption(PAD, y + 11, "Coding time", palette.muted));
|
|
11522
11540
|
parts.push(
|
|
11523
11541
|
text(PAD, y + 38, `${groupDigits(t.hours)}h ${String(t.minutes)}m`, {
|
|
11524
11542
|
size: 22,
|
|
11525
|
-
fill:
|
|
11543
|
+
fill: palette.text,
|
|
11526
11544
|
weight: 700
|
|
11527
11545
|
})
|
|
11528
11546
|
);
|
|
11529
11547
|
}
|
|
11530
11548
|
if (hasRank && snapshot.rank) {
|
|
11531
11549
|
const rank = snapshot.rank;
|
|
11532
|
-
parts.push(caption(rankX, y + 11, "Rank"));
|
|
11550
|
+
parts.push(caption(rankX, y + 11, "Rank", palette.muted));
|
|
11533
11551
|
const centerY = y + 32;
|
|
11534
11552
|
parts.push(
|
|
11535
|
-
`<circle cx="${String(rankX + 14)}" cy="${String(centerY)}" r="14" fill="${
|
|
11553
|
+
`<circle cx="${String(rankX + 14)}" cy="${String(centerY)}" r="14" fill="${palette.accent}"/>`
|
|
11536
11554
|
);
|
|
11537
11555
|
parts.push(
|
|
11538
11556
|
`<text x="${String(rankX + 14)}" y="${String(centerY)}" font-family="${FONT_FAMILY}" font-size="14" font-weight="700" fill="#ffffff" text-anchor="middle" dominant-baseline="central">${escapeXml(rank.tier)}</text>`
|
|
@@ -11540,7 +11558,7 @@ function renderActivitySvg(snapshot) {
|
|
|
11540
11558
|
parts.push(
|
|
11541
11559
|
text(rankX + 36, centerY + 4, `score ${String(rank.score)}`, {
|
|
11542
11560
|
size: 12,
|
|
11543
|
-
fill:
|
|
11561
|
+
fill: palette.muted
|
|
11544
11562
|
})
|
|
11545
11563
|
);
|
|
11546
11564
|
}
|
|
@@ -11549,13 +11567,14 @@ function renderActivitySvg(snapshot) {
|
|
|
11549
11567
|
parts.push(
|
|
11550
11568
|
text(WIDTH - PAD, y + 11, `Last synced ${snapshot.lastSyncedAt.slice(0, 10)}`, {
|
|
11551
11569
|
size: 11,
|
|
11552
|
-
fill:
|
|
11570
|
+
fill: palette.muted,
|
|
11553
11571
|
anchor: "end"
|
|
11554
11572
|
})
|
|
11555
11573
|
);
|
|
11556
11574
|
y += 22;
|
|
11557
11575
|
const height = y + PAD - 12;
|
|
11558
|
-
|
|
11576
|
+
const background = rect(0, 0, WIDTH, height, palette.background);
|
|
11577
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${String(WIDTH)}" height="${String(height)}" viewBox="0 0 ${String(WIDTH)} ${String(height)}" role="img" aria-label="Developer activity"><title>Developer activity</title>${background}${parts.join("")}</svg>`;
|
|
11559
11578
|
}
|
|
11560
11579
|
|
|
11561
11580
|
// src/cv.ts
|
|
@@ -12077,8 +12096,10 @@ var SCHEMA_VERSION = "0.5.0";
|
|
|
12077
12096
|
export {
|
|
12078
12097
|
ACCEPTED_IMAGE_MIME_TYPES,
|
|
12079
12098
|
ConflictError,
|
|
12099
|
+
DARK_PALETTE,
|
|
12080
12100
|
IMAGE_EXTENSIONS,
|
|
12081
12101
|
ImportError,
|
|
12102
|
+
LIGHT_PALETTE,
|
|
12082
12103
|
MAX_IMAGE_BYTES,
|
|
12083
12104
|
MAX_IMAGE_DIMENSION,
|
|
12084
12105
|
MAX_IMAGE_FRAMES,
|