@liustack/pptfast 0.8.0 → 0.9.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/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/browser.js +67 -67
- package/dist/{chunk-4NKLJ7OK.js → chunk-6JJGXB5S.js} +569 -460
- package/dist/chunk-6JJGXB5S.js.map +1 -0
- package/dist/{chunk-HBRSZW67.js → chunk-RE53OS3K.js} +3 -3
- package/dist/{chunk-HBRSZW67.js.map → chunk-RE53OS3K.js.map} +1 -1
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +10 -0
- package/dist/index.js +2 -2
- package/dist/{pixel-audit-HJEJ36WB.js → pixel-audit-ZB4RSPHG.js} +2 -2
- package/dist/validate.d.ts +1 -1
- package/dist/validate.js +10 -10
- package/package.json +1 -1
- package/dist/chunk-4NKLJ7OK.js.map +0 -1
- /package/dist/{pixel-audit-HJEJ36WB.js.map → pixel-audit-ZB4RSPHG.js.map} +0 -0
|
@@ -2948,6 +2948,401 @@ function resolveNarrative(input) {
|
|
|
2948
2948
|
return { strategy, pacing, audience };
|
|
2949
2949
|
}
|
|
2950
2950
|
|
|
2951
|
+
// src/lib/svg-text-layout.ts
|
|
2952
|
+
var WIDE_CHAR_RE = /[\u2014\u2018-\u201f\u2e80-\u9fff\uff00-\uffef]/;
|
|
2953
|
+
var NO_CORRECTION = { regular: 1, bold: 1 };
|
|
2954
|
+
var GEORGIA = {
|
|
2955
|
+
space: { regular: 1, bold: 0.7254 },
|
|
2956
|
+
wide: NO_CORRECTION,
|
|
2957
|
+
upper: { regular: 1, bold: 1.1242 },
|
|
2958
|
+
lowerDigit: { regular: 1, bold: 1.0461 },
|
|
2959
|
+
other: { regular: 1, bold: 0.9159 }
|
|
2960
|
+
};
|
|
2961
|
+
var YAHEI = {
|
|
2962
|
+
space: { regular: 1, bold: 0.8511 },
|
|
2963
|
+
wide: NO_CORRECTION,
|
|
2964
|
+
upper: { regular: 1, bold: 1.0317 },
|
|
2965
|
+
lowerDigit: { regular: 1, bold: 1.0266 },
|
|
2966
|
+
other: { regular: 1, bold: 0.9593 }
|
|
2967
|
+
};
|
|
2968
|
+
var SIMSUN_KAITI = {
|
|
2969
|
+
space: { regular: 1.4286, bold: 1.4286 },
|
|
2970
|
+
wide: NO_CORRECTION,
|
|
2971
|
+
upper: { regular: 1, bold: 0.852 },
|
|
2972
|
+
lowerDigit: { regular: 1, bold: 1.048 },
|
|
2973
|
+
other: { regular: 1.2235, bold: 1.2235 }
|
|
2974
|
+
};
|
|
2975
|
+
var ENVELOPE = {
|
|
2976
|
+
space: { regular: 1, bold: Math.max(GEORGIA.space.bold, YAHEI.space.bold, SIMSUN_KAITI.space.bold) },
|
|
2977
|
+
wide: { regular: 1, bold: Math.max(GEORGIA.wide.bold, YAHEI.wide.bold, SIMSUN_KAITI.wide.bold) },
|
|
2978
|
+
upper: { regular: 1, bold: Math.max(GEORGIA.upper.bold, YAHEI.upper.bold, SIMSUN_KAITI.upper.bold) },
|
|
2979
|
+
lowerDigit: {
|
|
2980
|
+
regular: 1,
|
|
2981
|
+
bold: Math.max(GEORGIA.lowerDigit.bold, YAHEI.lowerDigit.bold, SIMSUN_KAITI.lowerDigit.bold)
|
|
2982
|
+
},
|
|
2983
|
+
other: { regular: 1, bold: Math.max(GEORGIA.other.bold, YAHEI.other.bold, SIMSUN_KAITI.other.bold) }
|
|
2984
|
+
};
|
|
2985
|
+
var GEORGIA_REGULAR_EXACT = { 32: 0.2412, 33: 0.3311, 34: 0.4116, 35: 0.6431, 36: 0.6099, 37: 0.8174, 38: 0.7104, 39: 0.2153, 40: 0.375, 41: 0.375, 42: 0.4722, 43: 0.6431, 44: 0.2695, 45: 0.374, 46: 0.2695, 47: 0.4688, 48: 0.6138, 49: 0.4297, 50: 0.5586, 51: 0.5518, 52: 0.5649, 53: 0.5283, 54: 0.5659, 55: 0.5024, 56: 0.5962, 57: 0.5659, 58: 0.3125, 59: 0.3125, 60: 0.6431, 61: 0.6431, 62: 0.6431, 63: 0.4785, 64: 0.9287, 65: 0.6709, 66: 0.6538, 67: 0.6421, 68: 0.749, 69: 0.6533, 70: 0.5991, 71: 0.7251, 72: 0.8149, 73: 0.3896, 74: 0.5176, 75: 0.6943, 76: 0.6035, 77: 0.9272, 78: 0.7671, 79: 0.7441, 80: 0.6099, 81: 0.7441, 82: 0.7017, 83: 0.561, 84: 0.6187, 85: 0.7563, 86: 0.6665, 87: 0.9756, 88: 0.7104, 89: 0.6152, 90: 0.6016, 91: 0.375, 92: 0.4688, 93: 0.375, 94: 0.6431, 95: 0.6431, 96: 0.5, 97: 0.5039, 98: 0.5601, 99: 0.4541, 100: 0.5742, 101: 0.4834, 102: 0.3252, 103: 0.5093, 104: 0.582, 105: 0.293, 106: 0.292, 107: 0.5356, 108: 0.2861, 109: 0.8809, 110: 0.5908, 111: 0.5391, 112: 0.5713, 113: 0.5596, 114: 0.4097, 115: 0.4321, 116: 0.3452, 117: 0.5752, 118: 0.4966, 119: 0.7373, 120: 0.5049, 121: 0.4922, 122: 0.4438, 123: 0.4302, 124: 0.375, 125: 0.4302, 126: 0.6431 };
|
|
2986
|
+
var GEORGIA_BOLD_EXACT = { 32: 0.2539, 33: 0.3765, 34: 0.5098, 35: 0.7031, 36: 0.6406, 37: 0.8794, 38: 0.7993, 39: 0.269, 40: 0.4468, 41: 0.4468, 42: 0.4819, 43: 0.7031, 44: 0.3281, 45: 0.3789, 46: 0.3281, 47: 0.4717, 48: 0.7012, 49: 0.4897, 50: 0.6265, 51: 0.6245, 52: 0.6494, 53: 0.5991, 54: 0.6479, 55: 0.5542, 56: 0.6763, 57: 0.6479, 58: 0.3672, 59: 0.3672, 60: 0.7031, 61: 0.7031, 62: 0.7031, 63: 0.5483, 64: 0.9668, 65: 0.7583, 66: 0.7573, 67: 0.7153, 68: 0.834, 69: 0.7212, 70: 0.6714, 71: 0.8071, 72: 0.9131, 73: 0.4458, 74: 0.5952, 75: 0.8169, 76: 0.6855, 77: 1.0234, 78: 0.8394, 79: 0.8198, 80: 0.7012, 81: 0.8198, 82: 0.7974, 83: 0.6489, 84: 0.6841, 85: 0.8335, 86: 0.7622, 87: 1.1265, 88: 0.8086, 89: 0.7319, 90: 0.6895, 91: 0.4468, 92: 0.4717, 93: 0.4468, 94: 0.7031, 95: 0.7031, 96: 0.5, 97: 0.5957, 98: 0.6455, 99: 0.5312, 100: 0.6631, 101: 0.5718, 102: 0.3931, 103: 0.5767, 104: 0.6797, 105: 0.3535, 106: 0.3462, 107: 0.6318, 108: 0.3442, 109: 1.0156, 110: 0.6899, 111: 0.6357, 112: 0.6577, 113: 0.6484, 114: 0.52, 115: 0.5127, 116: 0.3975, 117: 0.6768, 118: 0.5669, 119: 0.8633, 120: 0.5879, 121: 0.562, 122: 0.5254, 123: 0.5, 124: 0.3877, 125: 0.5, 126: 0.7031 };
|
|
2987
|
+
var YAHEI_REGULAR_EXACT = { 32: 0.2959, 33: 0.3125, 34: 0.4355, 35: 0.6382, 36: 0.5864, 37: 0.8896, 38: 0.8701, 39: 0.2563, 40: 0.334, 41: 0.334, 42: 0.4551, 43: 0.7417, 44: 0.2407, 45: 0.4326, 46: 0.2407, 47: 0.4272, 48: 0.5864, 49: 0.5864, 50: 0.5864, 51: 0.5864, 52: 0.5864, 53: 0.5864, 54: 0.5864, 55: 0.5864, 56: 0.5864, 57: 0.5864, 58: 0.2407, 59: 0.2407, 60: 0.7417, 61: 0.7417, 62: 0.7417, 63: 0.4829, 64: 1.0312, 65: 0.7036, 66: 0.6274, 67: 0.6689, 68: 0.7617, 69: 0.5498, 70: 0.5312, 71: 0.7437, 72: 0.7734, 73: 0.2939, 74: 0.396, 75: 0.6348, 76: 0.5132, 77: 0.9771, 78: 0.813, 79: 0.8149, 80: 0.6118, 81: 0.8149, 82: 0.6528, 83: 0.5771, 84: 0.5732, 85: 0.7466, 86: 0.6763, 87: 1.0176, 88: 0.645, 89: 0.6035, 90: 0.6201, 91: 0.334, 92: 0.416, 93: 0.334, 94: 0.7417, 95: 0.4482, 96: 0.2949, 97: 0.5527, 98: 0.6387, 99: 0.5015, 100: 0.6396, 101: 0.5674, 102: 0.3467, 103: 0.6396, 104: 0.6157, 105: 0.2661, 106: 0.2671, 107: 0.5444, 108: 0.2661, 109: 0.937, 110: 0.6162, 111: 0.6357, 112: 0.6387, 113: 0.6396, 114: 0.3818, 115: 0.4629, 116: 0.3726, 117: 0.6162, 118: 0.5249, 119: 0.7896, 120: 0.5068, 121: 0.5293, 122: 0.4917, 123: 0.334, 124: 0.269, 125: 0.334, 126: 0.7417 };
|
|
2988
|
+
var YAHEI_BOLD_EXACT = { 32: 0.2979, 33: 0.3486, 34: 0.521, 35: 0.6401, 36: 0.6167, 37: 0.9312, 38: 0.9111, 39: 0.3081, 40: 0.3896, 41: 0.3896, 42: 0.4873, 43: 0.7612, 44: 0.2856, 45: 0.4365, 46: 0.2856, 47: 0.4727, 48: 0.6167, 49: 0.6167, 50: 0.6167, 51: 0.6167, 52: 0.6167, 53: 0.6167, 54: 0.6167, 55: 0.6167, 56: 0.6167, 57: 0.6167, 58: 0.2856, 59: 0.2856, 60: 0.7612, 61: 0.7612, 62: 0.7612, 63: 0.4741, 64: 1.0298, 65: 0.752, 66: 0.6836, 67: 0.6733, 68: 0.7915, 69: 0.5718, 70: 0.5581, 71: 0.7651, 72: 0.8213, 73: 0.3354, 74: 0.4702, 75: 0.6929, 76: 0.5469, 77: 1.0283, 78: 0.8481, 79: 0.8184, 80: 0.6572, 81: 0.8184, 82: 0.6982, 83: 0.6016, 84: 0.6255, 85: 0.7764, 86: 0.7148, 87: 1.0762, 88: 0.7002, 89: 0.6484, 90: 0.6504, 91: 0.3896, 92: 0.4644, 93: 0.3896, 94: 0.7612, 95: 0.4482, 96: 0.3335, 97: 0.5776, 98: 0.666, 99: 0.5166, 100: 0.6646, 101: 0.582, 102: 0.4053, 103: 0.6646, 104: 0.6455, 105: 0.2959, 106: 0.3018, 107: 0.5962, 108: 0.2959, 109: 0.9819, 110: 0.6479, 111: 0.6572, 112: 0.666, 113: 0.6646, 114: 0.4238, 115: 0.4937, 116: 0.4141, 117: 0.6479, 118: 0.5771, 119: 0.8516, 120: 0.585, 121: 0.5742, 122: 0.5137, 123: 0.3896, 124: 0.3413, 125: 0.3896, 126: 0.7612 };
|
|
2989
|
+
var CLASS_TABLE_FOR = {
|
|
2990
|
+
georgia: GEORGIA,
|
|
2991
|
+
yahei: YAHEI,
|
|
2992
|
+
"simsun-kaiti": SIMSUN_KAITI,
|
|
2993
|
+
unknown: ENVELOPE
|
|
2994
|
+
};
|
|
2995
|
+
var EXACT_TABLE_FOR = {
|
|
2996
|
+
georgia: { regular: GEORGIA_REGULAR_EXACT, bold: GEORGIA_BOLD_EXACT },
|
|
2997
|
+
yahei: { regular: YAHEI_REGULAR_EXACT, bold: YAHEI_BOLD_EXACT }
|
|
2998
|
+
};
|
|
2999
|
+
function classifyFaceKey(fontFamily) {
|
|
3000
|
+
const first = fontFamily?.split(",")[0]?.replace(/['"]/g, "").trim().toLowerCase();
|
|
3001
|
+
if (!first) return "unknown";
|
|
3002
|
+
if (first === "georgia") return "georgia";
|
|
3003
|
+
if (first === "microsoft yahei" || first === "\u5FAE\u8F6F\u96C5\u9ED1") return "yahei";
|
|
3004
|
+
if (first === "simsun" || first === "\u5B8B\u4F53" || first === "kaiti" || first === "\u6977\u4F53") return "simsun-kaiti";
|
|
3005
|
+
return "unknown";
|
|
3006
|
+
}
|
|
3007
|
+
function classAverageUnits(char, table, mode) {
|
|
3008
|
+
if (/\s/.test(char)) return 0.35 * table.space[mode];
|
|
3009
|
+
if (WIDE_CHAR_RE.test(char)) return 1 * table.wide[mode];
|
|
3010
|
+
if (/[A-Z]/.test(char)) return 0.66 * table.upper[mode];
|
|
3011
|
+
if (/[a-z0-9]/.test(char)) return 0.56 * table.lowerDigit[mode];
|
|
3012
|
+
return 0.46 * table.other[mode];
|
|
3013
|
+
}
|
|
3014
|
+
function measureTextUnits(text, weight) {
|
|
3015
|
+
const mode = weight?.bold ? "bold" : "regular";
|
|
3016
|
+
const faceKey = classifyFaceKey(weight?.fontFamily);
|
|
3017
|
+
const classTable = CLASS_TABLE_FOR[faceKey];
|
|
3018
|
+
const exactTable = mode === "bold" ? EXACT_TABLE_FOR[faceKey]?.bold : void 0;
|
|
3019
|
+
return Array.from(text).reduce((sum, char) => {
|
|
3020
|
+
if (exactTable && !WIDE_CHAR_RE.test(char)) {
|
|
3021
|
+
const exact = exactTable[char.charCodeAt(0)];
|
|
3022
|
+
if (exact !== void 0) return sum + exact;
|
|
3023
|
+
}
|
|
3024
|
+
return sum + classAverageUnits(char, classTable, mode);
|
|
3025
|
+
}, 0);
|
|
3026
|
+
}
|
|
3027
|
+
var MONO_ADVANCE_EM = 1126 / 2048;
|
|
3028
|
+
function measureMonoTextUnits(text) {
|
|
3029
|
+
return Array.from(text).reduce((sum, char) => {
|
|
3030
|
+
if (WIDE_CHAR_RE.test(char)) return sum + 1;
|
|
3031
|
+
return sum + MONO_ADVANCE_EM;
|
|
3032
|
+
}, 0);
|
|
3033
|
+
}
|
|
3034
|
+
function splitLongToken(token, maxUnits, weight) {
|
|
3035
|
+
const chunks = [];
|
|
3036
|
+
let current = "";
|
|
3037
|
+
for (const char of Array.from(token)) {
|
|
3038
|
+
const candidate = `${current}${char}`;
|
|
3039
|
+
if (current && measureTextUnits(candidate, weight) > maxUnits) {
|
|
3040
|
+
chunks.push(current);
|
|
3041
|
+
current = char;
|
|
3042
|
+
} else {
|
|
3043
|
+
current = candidate;
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
if (current) chunks.push(current);
|
|
3047
|
+
return chunks;
|
|
3048
|
+
}
|
|
3049
|
+
var LATIN_RUN_OR_CHAR_RE = /[A-Za-z0-9](?:[A-Za-z0-9.\-%]*[A-Za-z0-9%])?|./gu;
|
|
3050
|
+
function tokenize(text) {
|
|
3051
|
+
const normalized = text.trim().replace(/\s+/g, " ");
|
|
3052
|
+
if (!normalized) return { tokens: [], spaceDelimited: false };
|
|
3053
|
+
const spaceDelimited = normalized.includes(" ");
|
|
3054
|
+
return {
|
|
3055
|
+
tokens: spaceDelimited ? normalized.split(" ") : normalized.match(LATIN_RUN_OR_CHAR_RE) ?? [],
|
|
3056
|
+
spaceDelimited
|
|
3057
|
+
};
|
|
3058
|
+
}
|
|
3059
|
+
function wrapWithUnits(text, maxUnits, weight) {
|
|
3060
|
+
const lines = [];
|
|
3061
|
+
let hadSplit = false;
|
|
3062
|
+
let minSplitFreeUnits = 0;
|
|
3063
|
+
for (const paragraph2 of text.split(/\n+/)) {
|
|
3064
|
+
const { tokens, spaceDelimited } = tokenize(paragraph2);
|
|
3065
|
+
let current = "";
|
|
3066
|
+
for (const token of tokens) {
|
|
3067
|
+
const tokenUnits = measureTextUnits(token, weight);
|
|
3068
|
+
const isRunToken = !spaceDelimited && Array.from(token).length > 1;
|
|
3069
|
+
if (isRunToken) minSplitFreeUnits = Math.max(minSplitFreeUnits, tokenUnits);
|
|
3070
|
+
const tokenChunks = tokenUnits > maxUnits ? splitLongToken(token, maxUnits, weight) : [token];
|
|
3071
|
+
if (isRunToken && tokenChunks.length > 1) hadSplit = true;
|
|
3072
|
+
for (const [chunkIndex, chunk] of tokenChunks.entries()) {
|
|
3073
|
+
const prefix = current && spaceDelimited && chunkIndex === 0 ? " " : "";
|
|
3074
|
+
const candidate = `${current}${prefix}${chunk}`;
|
|
3075
|
+
if (current && measureTextUnits(candidate, weight) > maxUnits) {
|
|
3076
|
+
lines.push(current);
|
|
3077
|
+
current = chunk;
|
|
3078
|
+
} else {
|
|
3079
|
+
current = candidate;
|
|
3080
|
+
}
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
if (current) lines.push(current);
|
|
3084
|
+
}
|
|
3085
|
+
return { lines, hadSplit, minSplitFreeUnits };
|
|
3086
|
+
}
|
|
3087
|
+
function balanceWrappedLines(content, lines, weight) {
|
|
3088
|
+
if (lines.length < 2 || content.includes("\n")) return lines;
|
|
3089
|
+
const units = lines.map((l) => measureTextUnits(l, weight));
|
|
3090
|
+
const widest = Math.max(...units);
|
|
3091
|
+
if (units[units.length - 1] >= widest * 0.5) return lines;
|
|
3092
|
+
const total = units.reduce((sum, u) => sum + u, 0);
|
|
3093
|
+
const { tokens } = tokenize(content);
|
|
3094
|
+
const longestToken = Math.max(...tokens.map((t) => measureTextUnits(t, weight)), 0);
|
|
3095
|
+
let target = Math.max(total / lines.length, longestToken);
|
|
3096
|
+
for (let i = 0; i < 8; i += 1) {
|
|
3097
|
+
const candidate = wrapWithUnits(content, target, weight);
|
|
3098
|
+
if (candidate.lines.length === lines.length) return candidate.lines;
|
|
3099
|
+
if (candidate.lines.length < lines.length) return lines;
|
|
3100
|
+
target *= 1.06;
|
|
3101
|
+
}
|
|
3102
|
+
return lines;
|
|
3103
|
+
}
|
|
3104
|
+
function truncateToUnits(text, maxUnits, weight) {
|
|
3105
|
+
if (measureTextUnits(text, weight) <= maxUnits) return text;
|
|
3106
|
+
const budget = maxUnits - 1;
|
|
3107
|
+
let out = "";
|
|
3108
|
+
for (const ch of Array.from(text)) {
|
|
3109
|
+
if (measureTextUnits(out + ch, weight) > budget) break;
|
|
3110
|
+
out += ch;
|
|
3111
|
+
}
|
|
3112
|
+
if (out === "") {
|
|
3113
|
+
return measureTextUnits("\u2026", weight) > maxUnits ? "" : "\u2026";
|
|
3114
|
+
}
|
|
3115
|
+
return `${out}\u2026`;
|
|
3116
|
+
}
|
|
3117
|
+
function truncateToMonoUnits(text, maxUnits) {
|
|
3118
|
+
if (measureMonoTextUnits(text) <= maxUnits) return text;
|
|
3119
|
+
const budget = maxUnits - 1;
|
|
3120
|
+
let out = "";
|
|
3121
|
+
for (const ch of Array.from(text)) {
|
|
3122
|
+
if (measureMonoTextUnits(out + ch) > budget) break;
|
|
3123
|
+
out += ch;
|
|
3124
|
+
}
|
|
3125
|
+
if (out === "") {
|
|
3126
|
+
return measureMonoTextUnits("\u2026") > maxUnits ? "" : "\u2026";
|
|
3127
|
+
}
|
|
3128
|
+
return `${out}\u2026`;
|
|
3129
|
+
}
|
|
3130
|
+
function fitSvgLine(text, opts) {
|
|
3131
|
+
const minFontSize = opts.minFontSize ?? 12;
|
|
3132
|
+
const letterSpacing = opts.letterSpacing ?? 0;
|
|
3133
|
+
const weight = { bold: opts.bold, fontFamily: opts.fontFamily };
|
|
3134
|
+
const units = measureTextUnits(text, weight);
|
|
3135
|
+
if (units <= 0) return { text, fontSize: opts.fontSize, truncated: false };
|
|
3136
|
+
const charCount = Array.from(text).length;
|
|
3137
|
+
const spacingBudget = Math.max(0, charCount - 1) * letterSpacing;
|
|
3138
|
+
const availableWidth = Math.max(0, opts.maxWidth - spacingBudget);
|
|
3139
|
+
const fitted = Math.min(opts.fontSize, Math.floor(availableWidth / units));
|
|
3140
|
+
if (fitted >= minFontSize) return { text, fontSize: fitted, truncated: false };
|
|
3141
|
+
return {
|
|
3142
|
+
text: truncateToUnits(text, availableWidth / minFontSize, weight),
|
|
3143
|
+
fontSize: minFontSize,
|
|
3144
|
+
truncated: true
|
|
3145
|
+
};
|
|
3146
|
+
}
|
|
3147
|
+
function layoutSvgText(text, options) {
|
|
3148
|
+
const content = text?.trim() ?? "";
|
|
3149
|
+
const maxLines = options.maxLines ?? 2;
|
|
3150
|
+
const lineHeightRatio = options.lineHeightRatio ?? 1.08;
|
|
3151
|
+
const weight = { bold: options.bold, fontFamily: options.fontFamily };
|
|
3152
|
+
const minPt = options.minPt;
|
|
3153
|
+
if (!content) {
|
|
3154
|
+
return { lines: [], fontSize: options.fontSize, lineHeight: 0, truncated: false };
|
|
3155
|
+
}
|
|
3156
|
+
const fontSizeFor = (ls) => {
|
|
3157
|
+
const longest = Math.max(...ls.map((l) => measureTextUnits(l, weight)), 1);
|
|
3158
|
+
return Math.max(1, Math.min(options.fontSize, Math.floor(options.maxWidth / longest)));
|
|
3159
|
+
};
|
|
3160
|
+
const baseUnits = options.maxWidth / options.fontSize;
|
|
3161
|
+
let maxUnits = baseUnits;
|
|
3162
|
+
let attempt = wrapWithUnits(content, maxUnits, weight);
|
|
3163
|
+
const minSplitFreeUnits = attempt.minSplitFreeUnits;
|
|
3164
|
+
let legacyLines = attempt.lines;
|
|
3165
|
+
for (let i = 0; legacyLines.length > maxLines && i < 8; i += 1) {
|
|
3166
|
+
maxUnits *= 1.14;
|
|
3167
|
+
attempt = wrapWithUnits(content, maxUnits, weight);
|
|
3168
|
+
legacyLines = attempt.lines;
|
|
3169
|
+
}
|
|
3170
|
+
const legacyHadSplit = attempt.hadSplit;
|
|
3171
|
+
if (legacyLines.length > maxLines) {
|
|
3172
|
+
legacyLines = [
|
|
3173
|
+
...legacyLines.slice(0, maxLines - 1),
|
|
3174
|
+
legacyLines.slice(maxLines - 1).join("")
|
|
3175
|
+
];
|
|
3176
|
+
}
|
|
3177
|
+
let lines = legacyLines;
|
|
3178
|
+
if (legacyHadSplit) {
|
|
3179
|
+
const reachCeilingUnits = minPt === void 0 ? baseUnits * 1.14 ** 8 : Infinity;
|
|
3180
|
+
if (minSplitFreeUnits <= reachCeilingUnits) {
|
|
3181
|
+
let splitFreeUnits = minSplitFreeUnits;
|
|
3182
|
+
let splitFreeAttempt = wrapWithUnits(content, splitFreeUnits, weight);
|
|
3183
|
+
let admissible = splitFreeAttempt.lines.length <= maxLines;
|
|
3184
|
+
if (admissible && minPt !== void 0) {
|
|
3185
|
+
admissible = fontSizeFor(splitFreeAttempt.lines) >= minPt;
|
|
3186
|
+
}
|
|
3187
|
+
const stepCap = minPt === void 0 ? 8 : 32;
|
|
3188
|
+
for (let i = 0; !admissible && splitFreeAttempt.lines.length > maxLines && splitFreeUnits < reachCeilingUnits && i < stepCap; i += 1) {
|
|
3189
|
+
splitFreeUnits = Math.min(splitFreeUnits * 1.14, reachCeilingUnits);
|
|
3190
|
+
splitFreeAttempt = wrapWithUnits(content, splitFreeUnits, weight);
|
|
3191
|
+
admissible = splitFreeAttempt.lines.length <= maxLines;
|
|
3192
|
+
if (admissible && minPt !== void 0) {
|
|
3193
|
+
admissible = fontSizeFor(splitFreeAttempt.lines) >= minPt;
|
|
3194
|
+
}
|
|
3195
|
+
}
|
|
3196
|
+
if (admissible) lines = splitFreeAttempt.lines;
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
if (options.balanceLines) {
|
|
3200
|
+
lines = balanceWrappedLines(content, lines, weight);
|
|
3201
|
+
}
|
|
3202
|
+
const fontSize = fontSizeFor(lines);
|
|
3203
|
+
return {
|
|
3204
|
+
lines,
|
|
3205
|
+
fontSize,
|
|
3206
|
+
lineHeight: Math.round(fontSize * lineHeightRatio),
|
|
3207
|
+
truncated: false
|
|
3208
|
+
};
|
|
3209
|
+
}
|
|
3210
|
+
function hasExactWidthTable(fontFamily) {
|
|
3211
|
+
return EXACT_TABLE_FOR[classifyFaceKey(fontFamily)] !== void 0;
|
|
3212
|
+
}
|
|
3213
|
+
|
|
3214
|
+
// src/svg/fonts.ts
|
|
3215
|
+
var SAFE_FONTS = new Set(
|
|
3216
|
+
[
|
|
3217
|
+
// Latin sans
|
|
3218
|
+
"Arial",
|
|
3219
|
+
"Calibri",
|
|
3220
|
+
"Tahoma",
|
|
3221
|
+
"Verdana",
|
|
3222
|
+
"Segoe UI",
|
|
3223
|
+
// Latin serif
|
|
3224
|
+
"Georgia",
|
|
3225
|
+
"Times New Roman",
|
|
3226
|
+
"Cambria",
|
|
3227
|
+
// Latin mono
|
|
3228
|
+
"Consolas",
|
|
3229
|
+
"Courier New",
|
|
3230
|
+
"Lucida Console",
|
|
3231
|
+
// CJK (Windows)
|
|
3232
|
+
"Microsoft YaHei",
|
|
3233
|
+
"\u5FAE\u8F6F\u96C5\u9ED1",
|
|
3234
|
+
"SimSun",
|
|
3235
|
+
"\u5B8B\u4F53",
|
|
3236
|
+
"SimHei",
|
|
3237
|
+
"\u9ED1\u4F53",
|
|
3238
|
+
"KaiTi",
|
|
3239
|
+
"\u6977\u4F53",
|
|
3240
|
+
"FangSong",
|
|
3241
|
+
"\u4EFF\u5B8B"
|
|
3242
|
+
].map((f) => f.toLowerCase())
|
|
3243
|
+
);
|
|
3244
|
+
var ROLE_DEFAULT = {
|
|
3245
|
+
heading: "Microsoft YaHei",
|
|
3246
|
+
body: "Microsoft YaHei",
|
|
3247
|
+
mono: "Consolas"
|
|
3248
|
+
};
|
|
3249
|
+
function resolveFontFace(stack, role) {
|
|
3250
|
+
for (const raw of stack) {
|
|
3251
|
+
const name = raw.replace(/['"]/g, "").trim();
|
|
3252
|
+
if (SAFE_FONTS.has(name.toLowerCase())) return name;
|
|
3253
|
+
}
|
|
3254
|
+
return ROLE_DEFAULT[role];
|
|
3255
|
+
}
|
|
3256
|
+
var CJK_SAFE_FACES = new Set(
|
|
3257
|
+
["Microsoft YaHei", "\u5FAE\u8F6F\u96C5\u9ED1", "SimSun", "\u5B8B\u4F53", "SimHei", "\u9ED1\u4F53", "KaiTi", "\u6977\u4F53", "FangSong", "\u4EFF\u5B8B"].map(
|
|
3258
|
+
(f) => f.toLowerCase()
|
|
3259
|
+
)
|
|
3260
|
+
);
|
|
3261
|
+
var EA_FALLBACK_FACE = ROLE_DEFAULT.heading;
|
|
3262
|
+
function eaFontFaceFor(latinFace) {
|
|
3263
|
+
const name = latinFace.replace(/['"]/g, "").trim();
|
|
3264
|
+
return CJK_SAFE_FACES.has(name.toLowerCase()) ? name : EA_FALLBACK_FACE;
|
|
3265
|
+
}
|
|
3266
|
+
var SERIF_SAFE_FACES = new Set(
|
|
3267
|
+
["Georgia", "Times New Roman", "Cambria", "SimSun", "\u5B8B\u4F53", "FangSong", "\u4EFF\u5B8B", "KaiTi", "\u6977\u4F53"].map(
|
|
3268
|
+
(f) => f.toLowerCase()
|
|
3269
|
+
)
|
|
3270
|
+
);
|
|
3271
|
+
var PREVIEW_FALLBACK = {
|
|
3272
|
+
serif: "Songti SC, STSong, serif",
|
|
3273
|
+
sans: "PingFang SC, Helvetica Neue, sans-serif",
|
|
3274
|
+
mono: "Menlo, monospace"
|
|
3275
|
+
};
|
|
3276
|
+
function resolveFontStack(stack, role) {
|
|
3277
|
+
const face = resolveFontFace(stack, role);
|
|
3278
|
+
const fallback = role === "mono" ? PREVIEW_FALLBACK.mono : SERIF_SAFE_FACES.has(face.toLowerCase()) ? PREVIEW_FALLBACK.serif : PREVIEW_FALLBACK.sans;
|
|
3279
|
+
return `${face}, ${fallback}`;
|
|
3280
|
+
}
|
|
3281
|
+
function isMonoFontFamily(fontFamily) {
|
|
3282
|
+
return fontFamily.endsWith(`, ${PREVIEW_FALLBACK.mono}`);
|
|
3283
|
+
}
|
|
3284
|
+
function isBold(weight) {
|
|
3285
|
+
if (!weight) return false;
|
|
3286
|
+
if (weight === "bold" || weight === "bolder") return true;
|
|
3287
|
+
return parseInt(weight, 10) >= 600;
|
|
3288
|
+
}
|
|
3289
|
+
|
|
3290
|
+
// src/svg/ink.ts
|
|
3291
|
+
var LUMINANCE_INK_THRESHOLD = 0.4;
|
|
3292
|
+
var LARGE_TEXT_MIN_PX = 24;
|
|
3293
|
+
var CONTRAST_RATIO_LARGE = 3;
|
|
3294
|
+
var CONTRAST_RATIO_BODY = 4.5;
|
|
3295
|
+
function relativeLuminance(hex) {
|
|
3296
|
+
let h = hex.trim().replace(/^#/, "");
|
|
3297
|
+
if (h.length === 3 || h.length === 4) h = [...h].map((c) => c + c).join("");
|
|
3298
|
+
if (h.length === 8) h = h.slice(0, 6);
|
|
3299
|
+
if (!/^[0-9a-fA-F]{6}$/.test(h)) return 0;
|
|
3300
|
+
const n = parseInt(h, 16);
|
|
3301
|
+
const chan = [n >> 16 & 255, n >> 8 & 255, n & 255].map((v) => {
|
|
3302
|
+
const c = v / 255;
|
|
3303
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
3304
|
+
});
|
|
3305
|
+
return 0.2126 * chan[0] + 0.7152 * chan[1] + 0.0722 * chan[2];
|
|
3306
|
+
}
|
|
3307
|
+
function contrastRatio(hexA, hexB) {
|
|
3308
|
+
const la = relativeLuminance(hexA);
|
|
3309
|
+
const lb = relativeLuminance(hexB);
|
|
3310
|
+
const lighter = Math.max(la, lb);
|
|
3311
|
+
const darker = Math.min(la, lb);
|
|
3312
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
3313
|
+
}
|
|
3314
|
+
function requiredContrastRatio(fontSizePx) {
|
|
3315
|
+
return fontSizePx >= LARGE_TEXT_MIN_PX ? CONTRAST_RATIO_LARGE : CONTRAST_RATIO_BODY;
|
|
3316
|
+
}
|
|
3317
|
+
var DARK_INK = "#0A0E14";
|
|
3318
|
+
var LIGHT_INK = "#FFFFFF";
|
|
3319
|
+
function readableOn(bgHex) {
|
|
3320
|
+
const darkContrast = contrastRatio(DARK_INK, bgHex);
|
|
3321
|
+
const lightContrast = contrastRatio(LIGHT_INK, bgHex);
|
|
3322
|
+
if (darkContrast === lightContrast) {
|
|
3323
|
+
return relativeLuminance(bgHex) > LUMINANCE_INK_THRESHOLD ? DARK_INK : LIGHT_INK;
|
|
3324
|
+
}
|
|
3325
|
+
return darkContrast > lightContrast ? DARK_INK : LIGHT_INK;
|
|
3326
|
+
}
|
|
3327
|
+
function accessibleInk(preferredFill, bgHex, fontSizePx) {
|
|
3328
|
+
return contrastRatio(preferredFill, bgHex) >= requiredContrastRatio(fontSizePx) ? preferredFill : readableOn(bgHex);
|
|
3329
|
+
}
|
|
3330
|
+
function blendOver(fg, bg, alpha2) {
|
|
3331
|
+
const toRgb = (hex) => {
|
|
3332
|
+
const n = parseInt(hex.replace("#", ""), 16);
|
|
3333
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
3334
|
+
};
|
|
3335
|
+
const [fr, fgc, fb] = toRgb(fg);
|
|
3336
|
+
const [br, bgc, bb] = toRgb(bg);
|
|
3337
|
+
const mix = (f, b) => Math.round(f * alpha2 + b * (1 - alpha2));
|
|
3338
|
+
const toHex2 = (v) => v.toString(16).padStart(2, "0");
|
|
3339
|
+
return `#${toHex2(mix(fr, br))}${toHex2(mix(fgc, bgc))}${toHex2(mix(fb, bb))}`;
|
|
3340
|
+
}
|
|
3341
|
+
function accessibleOpacity(inkHex, bgHex, fontSizePx, preferredOpacity) {
|
|
3342
|
+
const blended = blendOver(inkHex, bgHex, preferredOpacity);
|
|
3343
|
+
return contrastRatio(blended, bgHex) >= requiredContrastRatio(fontSizePx) ? preferredOpacity : 1;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
2951
3346
|
// src/svg/layouts/registry.ts
|
|
2952
3347
|
function filterByNarrativesOnly(defs, strategy) {
|
|
2953
3348
|
return defs.filter((def) => def.narrativesOnly === void 0 || def.narrativesOnly.includes(strategy));
|
|
@@ -4204,6 +4599,34 @@ function resolveBrand(id, override) {
|
|
|
4204
4599
|
return override ? { ...base2, ...override } : base2;
|
|
4205
4600
|
}
|
|
4206
4601
|
var REGISTERABLE_SLIDE_TYPES = ["cover", "chapter", "content", "ending"];
|
|
4602
|
+
function resolveBackgroundHex(spec, surfaceFallback) {
|
|
4603
|
+
if (spec.kind === "color") return spec.value;
|
|
4604
|
+
if (spec.kind === "gradient") return spec.from;
|
|
4605
|
+
return surfaceFallback;
|
|
4606
|
+
}
|
|
4607
|
+
var CONTRAST_FLOOR = 3;
|
|
4608
|
+
var CONTRAST_CHECKED_SLIDE_TYPES = ["cover", "content", "ending"];
|
|
4609
|
+
function assertContrastFloor(id, style) {
|
|
4610
|
+
for (const slideType of CONTRAST_CHECKED_SLIDE_TYPES) {
|
|
4611
|
+
const bg = resolveBackgroundHex(style.defaultBackgrounds[slideType], style.colors.surface);
|
|
4612
|
+
for (const token of ["text", "muted"]) {
|
|
4613
|
+
const ratio = contrastRatio(style.colors[token], bg);
|
|
4614
|
+
if (ratio < CONTRAST_FLOOR) {
|
|
4615
|
+
throw new PptfastError(
|
|
4616
|
+
`theme "${id}" colors.${token} has a contrast ratio of ${ratio.toFixed(2)}:1 against its "${slideType}" background (${bg}) \u2014 must be at least ${CONTRAST_FLOOR.toFixed(1)}:1`
|
|
4617
|
+
);
|
|
4618
|
+
}
|
|
4619
|
+
}
|
|
4620
|
+
}
|
|
4621
|
+
}
|
|
4622
|
+
function warnUnmeasuredFace(id, role, stack) {
|
|
4623
|
+
const face = resolveFontFace(stack, role);
|
|
4624
|
+
if (!hasExactWidthTable(face)) {
|
|
4625
|
+
console.warn(
|
|
4626
|
+
`theme "${id}" ${role} font "${face}" has no exact width table \u2014 text width estimation falls back to a conservative class-average envelope and may overflow on long text; see measureTextUnits in src/lib/svg-text-layout.ts`
|
|
4627
|
+
);
|
|
4628
|
+
}
|
|
4629
|
+
}
|
|
4207
4630
|
function registerTheme(def) {
|
|
4208
4631
|
if (CANONICAL_THEME_IDS.includes(def.id) || REGISTERED_THEMES.has(def.id)) {
|
|
4209
4632
|
throw new PptfastError(`theme "${def.id}" is already installed`);
|
|
@@ -4211,6 +4634,7 @@ function registerTheme(def) {
|
|
|
4211
4634
|
if (!def.style) {
|
|
4212
4635
|
throw new PptfastError(`theme "${def.id}" is missing style tokens`);
|
|
4213
4636
|
}
|
|
4637
|
+
assertContrastFloor(def.id, def.style);
|
|
4214
4638
|
const layouts = {};
|
|
4215
4639
|
for (const slideType of REGISTERABLE_SLIDE_TYPES) {
|
|
4216
4640
|
const ids = def.layouts?.[slideType] ?? FULL_LAYOUTS[slideType];
|
|
@@ -4235,6 +4659,8 @@ function registerTheme(def) {
|
|
|
4235
4659
|
}
|
|
4236
4660
|
layouts[slideType] = ids;
|
|
4237
4661
|
}
|
|
4662
|
+
warnUnmeasuredFace(def.id, "heading", def.style.fonts.heading);
|
|
4663
|
+
warnUnmeasuredFace(def.id, "body", def.style.fonts.body);
|
|
4238
4664
|
REGISTERED_THEMES.set(def.id, { ...def, layouts });
|
|
4239
4665
|
}
|
|
4240
4666
|
function getInstalledThemeIds() {
|
|
@@ -4367,7 +4793,7 @@ var COMPONENT_FIELD_ALIASES = {
|
|
|
4367
4793
|
}
|
|
4368
4794
|
};
|
|
4369
4795
|
var COMPONENT_ITEM_FIELD_ALIASES = {
|
|
4370
|
-
kpi_cards: { itemsKey: "items", aliases: { title: "label", name: "label" } },
|
|
4796
|
+
kpi_cards: [{ itemsKey: "items", aliases: { title: "label", name: "label" } }],
|
|
4371
4797
|
// Numeric-axis family (structure-components wave task 2, decision 8):
|
|
4372
4798
|
// waterfall's per-item signed delta is commonly reached for as "amount" in
|
|
4373
4799
|
// finance-deck vocabulary (a waterfall/bridge chart is itself a finance-
|
|
@@ -4375,30 +4801,38 @@ var COMPONENT_ITEM_FIELD_ALIASES = {
|
|
|
4375
4801
|
// model that knows "Gantt chart" but not this schema's numeric-axis-only
|
|
4376
4802
|
// shape (decision 6: no date parsing) reaches for by analogy to a
|
|
4377
4803
|
// calendar's own "from"/"to" range vocabulary.
|
|
4378
|
-
waterfall: { itemsKey: "items", aliases: { amount: "value" } },
|
|
4379
|
-
gantt: { itemsKey: "items", aliases: { from: "start", to: "end" } },
|
|
4380
|
-
// Sankey (structure-components wave 2 task 4
|
|
4381
|
-
//
|
|
4382
|
-
//
|
|
4383
|
-
//
|
|
4384
|
-
//
|
|
4385
|
-
//
|
|
4386
|
-
//
|
|
4387
|
-
//
|
|
4388
|
-
//
|
|
4389
|
-
//
|
|
4390
|
-
//
|
|
4391
|
-
//
|
|
4392
|
-
|
|
4804
|
+
waterfall: [{ itemsKey: "items", aliases: { amount: "value" } }],
|
|
4805
|
+
gantt: [{ itemsKey: "items", aliases: { from: "start", to: "end" } }],
|
|
4806
|
+
// Sankey (structure-components wave 2 task 4, `links`; field-alias sweep
|
|
4807
|
+
// task I1, `nodes`): `links`' `source`/`target` is the exact field-name
|
|
4808
|
+
// convention D3-sankey and Plotly's own Sankey trace both use for a
|
|
4809
|
+
// link's two endpoints — a model that has ever produced a sankey spec for
|
|
4810
|
+
// either of those two (the dominant JS/Python charting libraries for this
|
|
4811
|
+
// diagram type) reaches for that vocabulary over this schema's
|
|
4812
|
+
// `from`/`to`. `nodes[].label` carried no alias until task I1 widened this
|
|
4813
|
+
// table's value type to a list of specs — rescuing it needed a *second*
|
|
4814
|
+
// item-array entry for the same component type (`nodes` alongside
|
|
4815
|
+
// `links`), which the original one-`itemsKey`-per-component-type shape
|
|
4816
|
+
// did not support (a real, scoped-out gap, not a silent drop). Now that a
|
|
4817
|
+
// component type can list one spec per item array, `nodes` gets its own:
|
|
4818
|
+
// `name` is D3's own classic node-label convention (the same
|
|
4819
|
+
// "reaches for the charting library's vocabulary" logic as `links`'
|
|
4820
|
+
// `source`/`target` above), `title` mirrors kpi_cards' own
|
|
4821
|
+
// `title`→`label` alias above — the same generic title-for-label slip on
|
|
4822
|
+
// any labeled-card-like item shape.
|
|
4823
|
+
sankey: [
|
|
4824
|
+
{ itemsKey: "links", aliases: { source: "from", target: "to" } },
|
|
4825
|
+
{ itemsKey: "nodes", aliases: { name: "label", title: "label" } }
|
|
4826
|
+
],
|
|
4393
4827
|
// Real-world tech-deck mental model: layers have a "name" and hold
|
|
4394
4828
|
// "components" or "nodes" — pptfast's own top-level components array
|
|
4395
4829
|
// shares the word "components" by coincidence only; this alias is scoped
|
|
4396
4830
|
// to one architecture layer's own item shape, never the deck-level array.
|
|
4397
|
-
architecture: { itemsKey: "layers", aliases: { name: "title", components: "items", nodes: "items" } },
|
|
4398
|
-
steps: { itemsKey: "items", aliases: { description: "text", desc: "text" } },
|
|
4399
|
-
timeline: { itemsKey: "milestones", aliases: { year: "date", text: "desc", description: "desc" } },
|
|
4400
|
-
numbered_cards: { itemsKey: "items", aliases: { description: "text", desc: "text" } },
|
|
4401
|
-
row_cards: { itemsKey: "items", aliases: { description: "text", desc: "text" } }
|
|
4831
|
+
architecture: [{ itemsKey: "layers", aliases: { name: "title", components: "items", nodes: "items" } }],
|
|
4832
|
+
steps: [{ itemsKey: "items", aliases: { description: "text", desc: "text" } }],
|
|
4833
|
+
timeline: [{ itemsKey: "milestones", aliases: { year: "date", text: "desc", description: "desc" } }],
|
|
4834
|
+
numbered_cards: [{ itemsKey: "items", aliases: { description: "text", desc: "text" } }],
|
|
4835
|
+
row_cards: [{ itemsKey: "items", aliases: { description: "text", desc: "text" } }]
|
|
4402
4836
|
};
|
|
4403
4837
|
var SLIDE_FIELD_ALIASES = {
|
|
4404
4838
|
note: "notes",
|
|
@@ -4425,18 +4859,20 @@ function normalizeComponent(component, si, ci, normalized) {
|
|
|
4425
4859
|
let next = component;
|
|
4426
4860
|
const blockAliases = COMPONENT_FIELD_ALIASES[component.type];
|
|
4427
4861
|
if (blockAliases) next = renameAliases(next, blockAliases, path, normalized);
|
|
4428
|
-
const
|
|
4429
|
-
if (
|
|
4430
|
-
const
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4862
|
+
const itemSpecs = COMPONENT_ITEM_FIELD_ALIASES[component.type];
|
|
4863
|
+
if (itemSpecs) {
|
|
4864
|
+
for (const itemSpec of itemSpecs) {
|
|
4865
|
+
const items = next[itemSpec.itemsKey];
|
|
4866
|
+
if (Array.isArray(items)) {
|
|
4867
|
+
let itemsChanged = false;
|
|
4868
|
+
const nextItems = items.map((item, ii) => {
|
|
4869
|
+
if (!isPlainObject(item)) return item;
|
|
4870
|
+
const renamed = renameAliases(item, itemSpec.aliases, `${path}.${itemSpec.itemsKey}[${ii}]`, normalized);
|
|
4871
|
+
if (renamed !== item) itemsChanged = true;
|
|
4872
|
+
return renamed;
|
|
4873
|
+
});
|
|
4874
|
+
if (itemsChanged) next = { ...next, [itemSpec.itemsKey]: nextItems };
|
|
4875
|
+
}
|
|
4440
4876
|
}
|
|
4441
4877
|
}
|
|
4442
4878
|
return next;
|
|
@@ -5016,288 +5452,61 @@ function resolveArchetypeId(slideType, layouts, seed, pageKey, requestedLayout,
|
|
|
5016
5452
|
return Math.max(strategyWeight, beatWeight);
|
|
5017
5453
|
};
|
|
5018
5454
|
const salt = `${slideType}-archetype:${pageKey}`;
|
|
5019
|
-
const picked = weightedPickBySeed(seed, salt, pool, weightOf);
|
|
5020
|
-
if (picked === previousEffectiveLayoutId && pool.length > 1) {
|
|
5021
|
-
const remainder = pool.filter((id) => id !== previousEffectiveLayoutId);
|
|
5022
|
-
return weightedPickBySeed(seed, salt, remainder, weightOf);
|
|
5023
|
-
}
|
|
5024
|
-
return picked;
|
|
5025
|
-
}
|
|
5026
|
-
function resolveIrStrategy(ir) {
|
|
5027
|
-
return resolveNarrative(ir.narrative).strategy;
|
|
5028
|
-
}
|
|
5029
|
-
function resolveOneEffectiveLayoutId(ir, slide, seed, strategy, pageKey, previousEffectiveLayoutId) {
|
|
5030
|
-
const tokens = resolveStyle(ir.theme.id, ir.theme.style);
|
|
5031
|
-
const bgSpec = slide.background ?? tokens.defaultBackgrounds[slide.type];
|
|
5032
|
-
const imageCoverTakeover = bgSpec.kind === "asset" && (slide.type === "cover" || slide.type === "chapter");
|
|
5033
|
-
if (imageCoverTakeover) return null;
|
|
5034
|
-
if (slide.layout) {
|
|
5035
|
-
const requestedLayoutDef = getLayout(slide.layout);
|
|
5036
|
-
if (requestedLayoutDef?.kind === "takeover" && findImageComponent(slide) != null) {
|
|
5037
|
-
return slide.layout;
|
|
5038
|
-
}
|
|
5039
|
-
}
|
|
5040
|
-
const themeDef = getThemeDefinition(ir.theme.id);
|
|
5041
|
-
return resolveArchetypeId(
|
|
5042
|
-
slide.type,
|
|
5043
|
-
themeDef.layouts,
|
|
5044
|
-
seed,
|
|
5045
|
-
pageKey,
|
|
5046
|
-
slide.layout,
|
|
5047
|
-
strategy,
|
|
5048
|
-
previousEffectiveLayoutId,
|
|
5049
|
-
slide.beat
|
|
5050
|
-
);
|
|
5051
|
-
}
|
|
5052
|
-
var deckEffectiveLayoutIdsCache = /* @__PURE__ */ new WeakMap();
|
|
5053
|
-
function resolveDeckEffectiveLayoutIds(ir) {
|
|
5054
|
-
const cached = deckEffectiveLayoutIdsCache.get(ir);
|
|
5055
|
-
if (cached) return cached;
|
|
5056
|
-
const seed = cachedDeckSeed(ir);
|
|
5057
|
-
const strategy = resolveIrStrategy(ir);
|
|
5058
|
-
const deckIds = [];
|
|
5059
|
-
for (let i = 0; i < ir.slides.length; i++) {
|
|
5060
|
-
const slide = ir.slides[i];
|
|
5061
|
-
const previous = i > 0 ? deckIds[i - 1] : null;
|
|
5062
|
-
deckIds.push(resolveOneEffectiveLayoutId(ir, slide, seed, strategy, slide.id ?? String(i), previous));
|
|
5063
|
-
}
|
|
5064
|
-
deckEffectiveLayoutIdsCache.set(ir, deckIds);
|
|
5065
|
-
return deckIds;
|
|
5066
|
-
}
|
|
5067
|
-
function resolveEffectiveLayoutId(ir, slide, index) {
|
|
5068
|
-
return resolveDeckEffectiveLayoutIds(ir)[index] ?? null;
|
|
5069
|
-
}
|
|
5070
|
-
function resolveEffectiveLayoutBodyCapacity(ir, slide, index) {
|
|
5071
|
-
const layoutId = resolveEffectiveLayoutId(ir, slide, index);
|
|
5072
|
-
const capacity = layoutId === null ? void 0 : getLayout(layoutId)?.slots.find((s) => s.name === "body")?.capacity;
|
|
5073
|
-
return { layoutId, capacity };
|
|
5074
|
-
}
|
|
5075
|
-
|
|
5076
|
-
// src/lib/svg-text-layout.ts
|
|
5077
|
-
var WIDE_CHAR_RE = /[\u2014\u2018-\u201f\u2e80-\u9fff\uff00-\uffef]/;
|
|
5078
|
-
var NO_CORRECTION = { regular: 1, bold: 1 };
|
|
5079
|
-
var GEORGIA = {
|
|
5080
|
-
space: { regular: 1, bold: 0.7254 },
|
|
5081
|
-
wide: NO_CORRECTION,
|
|
5082
|
-
upper: { regular: 1, bold: 1.1242 },
|
|
5083
|
-
lowerDigit: { regular: 1, bold: 1.0461 },
|
|
5084
|
-
other: { regular: 1, bold: 0.9159 }
|
|
5085
|
-
};
|
|
5086
|
-
var YAHEI = {
|
|
5087
|
-
space: { regular: 1, bold: 0.8511 },
|
|
5088
|
-
wide: NO_CORRECTION,
|
|
5089
|
-
upper: { regular: 1, bold: 1.0317 },
|
|
5090
|
-
lowerDigit: { regular: 1, bold: 1.0266 },
|
|
5091
|
-
other: { regular: 1, bold: 0.9593 }
|
|
5092
|
-
};
|
|
5093
|
-
var SIMSUN_KAITI = {
|
|
5094
|
-
space: { regular: 1.4286, bold: 1.4286 },
|
|
5095
|
-
wide: NO_CORRECTION,
|
|
5096
|
-
upper: { regular: 1, bold: 0.852 },
|
|
5097
|
-
lowerDigit: { regular: 1, bold: 1.048 },
|
|
5098
|
-
other: { regular: 1.2235, bold: 1.2235 }
|
|
5099
|
-
};
|
|
5100
|
-
var ENVELOPE = {
|
|
5101
|
-
space: { regular: 1, bold: Math.max(GEORGIA.space.bold, YAHEI.space.bold, SIMSUN_KAITI.space.bold) },
|
|
5102
|
-
wide: { regular: 1, bold: Math.max(GEORGIA.wide.bold, YAHEI.wide.bold, SIMSUN_KAITI.wide.bold) },
|
|
5103
|
-
upper: { regular: 1, bold: Math.max(GEORGIA.upper.bold, YAHEI.upper.bold, SIMSUN_KAITI.upper.bold) },
|
|
5104
|
-
lowerDigit: {
|
|
5105
|
-
regular: 1,
|
|
5106
|
-
bold: Math.max(GEORGIA.lowerDigit.bold, YAHEI.lowerDigit.bold, SIMSUN_KAITI.lowerDigit.bold)
|
|
5107
|
-
},
|
|
5108
|
-
other: { regular: 1, bold: Math.max(GEORGIA.other.bold, YAHEI.other.bold, SIMSUN_KAITI.other.bold) }
|
|
5109
|
-
};
|
|
5110
|
-
var GEORGIA_REGULAR_EXACT = { 32: 0.2412, 33: 0.3311, 34: 0.4116, 35: 0.6431, 36: 0.6099, 37: 0.8174, 38: 0.7104, 39: 0.2153, 40: 0.375, 41: 0.375, 42: 0.4722, 43: 0.6431, 44: 0.2695, 45: 0.374, 46: 0.2695, 47: 0.4688, 48: 0.6138, 49: 0.4297, 50: 0.5586, 51: 0.5518, 52: 0.5649, 53: 0.5283, 54: 0.5659, 55: 0.5024, 56: 0.5962, 57: 0.5659, 58: 0.3125, 59: 0.3125, 60: 0.6431, 61: 0.6431, 62: 0.6431, 63: 0.4785, 64: 0.9287, 65: 0.6709, 66: 0.6538, 67: 0.6421, 68: 0.749, 69: 0.6533, 70: 0.5991, 71: 0.7251, 72: 0.8149, 73: 0.3896, 74: 0.5176, 75: 0.6943, 76: 0.6035, 77: 0.9272, 78: 0.7671, 79: 0.7441, 80: 0.6099, 81: 0.7441, 82: 0.7017, 83: 0.561, 84: 0.6187, 85: 0.7563, 86: 0.6665, 87: 0.9756, 88: 0.7104, 89: 0.6152, 90: 0.6016, 91: 0.375, 92: 0.4688, 93: 0.375, 94: 0.6431, 95: 0.6431, 96: 0.5, 97: 0.5039, 98: 0.5601, 99: 0.4541, 100: 0.5742, 101: 0.4834, 102: 0.3252, 103: 0.5093, 104: 0.582, 105: 0.293, 106: 0.292, 107: 0.5356, 108: 0.2861, 109: 0.8809, 110: 0.5908, 111: 0.5391, 112: 0.5713, 113: 0.5596, 114: 0.4097, 115: 0.4321, 116: 0.3452, 117: 0.5752, 118: 0.4966, 119: 0.7373, 120: 0.5049, 121: 0.4922, 122: 0.4438, 123: 0.4302, 124: 0.375, 125: 0.4302, 126: 0.6431 };
|
|
5111
|
-
var GEORGIA_BOLD_EXACT = { 32: 0.2539, 33: 0.3765, 34: 0.5098, 35: 0.7031, 36: 0.6406, 37: 0.8794, 38: 0.7993, 39: 0.269, 40: 0.4468, 41: 0.4468, 42: 0.4819, 43: 0.7031, 44: 0.3281, 45: 0.3789, 46: 0.3281, 47: 0.4717, 48: 0.7012, 49: 0.4897, 50: 0.6265, 51: 0.6245, 52: 0.6494, 53: 0.5991, 54: 0.6479, 55: 0.5542, 56: 0.6763, 57: 0.6479, 58: 0.3672, 59: 0.3672, 60: 0.7031, 61: 0.7031, 62: 0.7031, 63: 0.5483, 64: 0.9668, 65: 0.7583, 66: 0.7573, 67: 0.7153, 68: 0.834, 69: 0.7212, 70: 0.6714, 71: 0.8071, 72: 0.9131, 73: 0.4458, 74: 0.5952, 75: 0.8169, 76: 0.6855, 77: 1.0234, 78: 0.8394, 79: 0.8198, 80: 0.7012, 81: 0.8198, 82: 0.7974, 83: 0.6489, 84: 0.6841, 85: 0.8335, 86: 0.7622, 87: 1.1265, 88: 0.8086, 89: 0.7319, 90: 0.6895, 91: 0.4468, 92: 0.4717, 93: 0.4468, 94: 0.7031, 95: 0.7031, 96: 0.5, 97: 0.5957, 98: 0.6455, 99: 0.5312, 100: 0.6631, 101: 0.5718, 102: 0.3931, 103: 0.5767, 104: 0.6797, 105: 0.3535, 106: 0.3462, 107: 0.6318, 108: 0.3442, 109: 1.0156, 110: 0.6899, 111: 0.6357, 112: 0.6577, 113: 0.6484, 114: 0.52, 115: 0.5127, 116: 0.3975, 117: 0.6768, 118: 0.5669, 119: 0.8633, 120: 0.5879, 121: 0.562, 122: 0.5254, 123: 0.5, 124: 0.3877, 125: 0.5, 126: 0.7031 };
|
|
5112
|
-
var YAHEI_REGULAR_EXACT = { 32: 0.2959, 33: 0.3125, 34: 0.4355, 35: 0.6382, 36: 0.5864, 37: 0.8896, 38: 0.8701, 39: 0.2563, 40: 0.334, 41: 0.334, 42: 0.4551, 43: 0.7417, 44: 0.2407, 45: 0.4326, 46: 0.2407, 47: 0.4272, 48: 0.5864, 49: 0.5864, 50: 0.5864, 51: 0.5864, 52: 0.5864, 53: 0.5864, 54: 0.5864, 55: 0.5864, 56: 0.5864, 57: 0.5864, 58: 0.2407, 59: 0.2407, 60: 0.7417, 61: 0.7417, 62: 0.7417, 63: 0.4829, 64: 1.0312, 65: 0.7036, 66: 0.6274, 67: 0.6689, 68: 0.7617, 69: 0.5498, 70: 0.5312, 71: 0.7437, 72: 0.7734, 73: 0.2939, 74: 0.396, 75: 0.6348, 76: 0.5132, 77: 0.9771, 78: 0.813, 79: 0.8149, 80: 0.6118, 81: 0.8149, 82: 0.6528, 83: 0.5771, 84: 0.5732, 85: 0.7466, 86: 0.6763, 87: 1.0176, 88: 0.645, 89: 0.6035, 90: 0.6201, 91: 0.334, 92: 0.416, 93: 0.334, 94: 0.7417, 95: 0.4482, 96: 0.2949, 97: 0.5527, 98: 0.6387, 99: 0.5015, 100: 0.6396, 101: 0.5674, 102: 0.3467, 103: 0.6396, 104: 0.6157, 105: 0.2661, 106: 0.2671, 107: 0.5444, 108: 0.2661, 109: 0.937, 110: 0.6162, 111: 0.6357, 112: 0.6387, 113: 0.6396, 114: 0.3818, 115: 0.4629, 116: 0.3726, 117: 0.6162, 118: 0.5249, 119: 0.7896, 120: 0.5068, 121: 0.5293, 122: 0.4917, 123: 0.334, 124: 0.269, 125: 0.334, 126: 0.7417 };
|
|
5113
|
-
var YAHEI_BOLD_EXACT = { 32: 0.2979, 33: 0.3486, 34: 0.521, 35: 0.6401, 36: 0.6167, 37: 0.9312, 38: 0.9111, 39: 0.3081, 40: 0.3896, 41: 0.3896, 42: 0.4873, 43: 0.7612, 44: 0.2856, 45: 0.4365, 46: 0.2856, 47: 0.4727, 48: 0.6167, 49: 0.6167, 50: 0.6167, 51: 0.6167, 52: 0.6167, 53: 0.6167, 54: 0.6167, 55: 0.6167, 56: 0.6167, 57: 0.6167, 58: 0.2856, 59: 0.2856, 60: 0.7612, 61: 0.7612, 62: 0.7612, 63: 0.4741, 64: 1.0298, 65: 0.752, 66: 0.6836, 67: 0.6733, 68: 0.7915, 69: 0.5718, 70: 0.5581, 71: 0.7651, 72: 0.8213, 73: 0.3354, 74: 0.4702, 75: 0.6929, 76: 0.5469, 77: 1.0283, 78: 0.8481, 79: 0.8184, 80: 0.6572, 81: 0.8184, 82: 0.6982, 83: 0.6016, 84: 0.6255, 85: 0.7764, 86: 0.7148, 87: 1.0762, 88: 0.7002, 89: 0.6484, 90: 0.6504, 91: 0.3896, 92: 0.4644, 93: 0.3896, 94: 0.7612, 95: 0.4482, 96: 0.3335, 97: 0.5776, 98: 0.666, 99: 0.5166, 100: 0.6646, 101: 0.582, 102: 0.4053, 103: 0.6646, 104: 0.6455, 105: 0.2959, 106: 0.3018, 107: 0.5962, 108: 0.2959, 109: 0.9819, 110: 0.6479, 111: 0.6572, 112: 0.666, 113: 0.6646, 114: 0.4238, 115: 0.4937, 116: 0.4141, 117: 0.6479, 118: 0.5771, 119: 0.8516, 120: 0.585, 121: 0.5742, 122: 0.5137, 123: 0.3896, 124: 0.3413, 125: 0.3896, 126: 0.7612 };
|
|
5114
|
-
var CLASS_TABLE_FOR = {
|
|
5115
|
-
georgia: GEORGIA,
|
|
5116
|
-
yahei: YAHEI,
|
|
5117
|
-
"simsun-kaiti": SIMSUN_KAITI,
|
|
5118
|
-
unknown: ENVELOPE
|
|
5119
|
-
};
|
|
5120
|
-
var EXACT_TABLE_FOR = {
|
|
5121
|
-
georgia: { regular: GEORGIA_REGULAR_EXACT, bold: GEORGIA_BOLD_EXACT },
|
|
5122
|
-
yahei: { regular: YAHEI_REGULAR_EXACT, bold: YAHEI_BOLD_EXACT }
|
|
5123
|
-
};
|
|
5124
|
-
function classifyFaceKey(fontFamily) {
|
|
5125
|
-
const first = fontFamily?.split(",")[0]?.replace(/['"]/g, "").trim().toLowerCase();
|
|
5126
|
-
if (!first) return "unknown";
|
|
5127
|
-
if (first === "georgia") return "georgia";
|
|
5128
|
-
if (first === "microsoft yahei" || first === "\u5FAE\u8F6F\u96C5\u9ED1") return "yahei";
|
|
5129
|
-
if (first === "simsun" || first === "\u5B8B\u4F53" || first === "kaiti" || first === "\u6977\u4F53") return "simsun-kaiti";
|
|
5130
|
-
return "unknown";
|
|
5131
|
-
}
|
|
5132
|
-
function classAverageUnits(char, table, mode) {
|
|
5133
|
-
if (/\s/.test(char)) return 0.35 * table.space[mode];
|
|
5134
|
-
if (WIDE_CHAR_RE.test(char)) return 1 * table.wide[mode];
|
|
5135
|
-
if (/[A-Z]/.test(char)) return 0.66 * table.upper[mode];
|
|
5136
|
-
if (/[a-z0-9]/.test(char)) return 0.56 * table.lowerDigit[mode];
|
|
5137
|
-
return 0.46 * table.other[mode];
|
|
5138
|
-
}
|
|
5139
|
-
function measureTextUnits(text, weight) {
|
|
5140
|
-
const mode = weight?.bold ? "bold" : "regular";
|
|
5141
|
-
const faceKey = classifyFaceKey(weight?.fontFamily);
|
|
5142
|
-
const classTable = CLASS_TABLE_FOR[faceKey];
|
|
5143
|
-
const exactTable = mode === "bold" ? EXACT_TABLE_FOR[faceKey]?.bold : void 0;
|
|
5144
|
-
return Array.from(text).reduce((sum, char) => {
|
|
5145
|
-
if (exactTable && !WIDE_CHAR_RE.test(char)) {
|
|
5146
|
-
const exact = exactTable[char.charCodeAt(0)];
|
|
5147
|
-
if (exact !== void 0) return sum + exact;
|
|
5148
|
-
}
|
|
5149
|
-
return sum + classAverageUnits(char, classTable, mode);
|
|
5150
|
-
}, 0);
|
|
5151
|
-
}
|
|
5152
|
-
var MONO_ADVANCE_EM = 1126 / 2048;
|
|
5153
|
-
function measureMonoTextUnits(text) {
|
|
5154
|
-
return Array.from(text).reduce((sum, char) => {
|
|
5155
|
-
if (WIDE_CHAR_RE.test(char)) return sum + 1;
|
|
5156
|
-
return sum + MONO_ADVANCE_EM;
|
|
5157
|
-
}, 0);
|
|
5158
|
-
}
|
|
5159
|
-
function splitLongToken(token, maxUnits, weight) {
|
|
5160
|
-
const chunks = [];
|
|
5161
|
-
let current = "";
|
|
5162
|
-
for (const char of Array.from(token)) {
|
|
5163
|
-
const candidate = `${current}${char}`;
|
|
5164
|
-
if (current && measureTextUnits(candidate, weight) > maxUnits) {
|
|
5165
|
-
chunks.push(current);
|
|
5166
|
-
current = char;
|
|
5167
|
-
} else {
|
|
5168
|
-
current = candidate;
|
|
5169
|
-
}
|
|
5170
|
-
}
|
|
5171
|
-
if (current) chunks.push(current);
|
|
5172
|
-
return chunks;
|
|
5173
|
-
}
|
|
5174
|
-
function tokenize(text) {
|
|
5175
|
-
const normalized = text.trim().replace(/\s+/g, " ");
|
|
5176
|
-
if (!normalized) return { tokens: [], spaceDelimited: false };
|
|
5177
|
-
const spaceDelimited = normalized.includes(" ");
|
|
5178
|
-
return {
|
|
5179
|
-
tokens: spaceDelimited ? normalized.split(" ") : Array.from(normalized),
|
|
5180
|
-
spaceDelimited
|
|
5181
|
-
};
|
|
5182
|
-
}
|
|
5183
|
-
function wrapWithUnits(text, maxUnits, weight) {
|
|
5184
|
-
const lines = [];
|
|
5185
|
-
for (const paragraph2 of text.split(/\n+/)) {
|
|
5186
|
-
const { tokens, spaceDelimited } = tokenize(paragraph2);
|
|
5187
|
-
let current = "";
|
|
5188
|
-
for (const token of tokens) {
|
|
5189
|
-
const tokenChunks = measureTextUnits(token, weight) > maxUnits ? splitLongToken(token, maxUnits, weight) : [token];
|
|
5190
|
-
for (const [chunkIndex, chunk] of tokenChunks.entries()) {
|
|
5191
|
-
const prefix = current && spaceDelimited && chunkIndex === 0 ? " " : "";
|
|
5192
|
-
const candidate = `${current}${prefix}${chunk}`;
|
|
5193
|
-
if (current && measureTextUnits(candidate, weight) > maxUnits) {
|
|
5194
|
-
lines.push(current);
|
|
5195
|
-
current = chunk;
|
|
5196
|
-
} else {
|
|
5197
|
-
current = candidate;
|
|
5198
|
-
}
|
|
5199
|
-
}
|
|
5200
|
-
}
|
|
5201
|
-
if (current) lines.push(current);
|
|
5202
|
-
}
|
|
5203
|
-
return lines;
|
|
5204
|
-
}
|
|
5205
|
-
function balanceWrappedLines(content, lines, weight) {
|
|
5206
|
-
if (lines.length < 2 || content.includes("\n")) return lines;
|
|
5207
|
-
const units = lines.map((l) => measureTextUnits(l, weight));
|
|
5208
|
-
const widest = Math.max(...units);
|
|
5209
|
-
if (units[units.length - 1] >= widest * 0.5) return lines;
|
|
5210
|
-
const total = units.reduce((sum, u) => sum + u, 0);
|
|
5211
|
-
const { tokens } = tokenize(content);
|
|
5212
|
-
const longestToken = Math.max(...tokens.map((t) => measureTextUnits(t, weight)), 0);
|
|
5213
|
-
let target = Math.max(total / lines.length, longestToken);
|
|
5214
|
-
for (let i = 0; i < 8; i += 1) {
|
|
5215
|
-
const candidate = wrapWithUnits(content, target, weight);
|
|
5216
|
-
if (candidate.length === lines.length) return candidate;
|
|
5217
|
-
if (candidate.length < lines.length) return lines;
|
|
5218
|
-
target *= 1.06;
|
|
5455
|
+
const picked = weightedPickBySeed(seed, salt, pool, weightOf);
|
|
5456
|
+
if (picked === previousEffectiveLayoutId && pool.length > 1) {
|
|
5457
|
+
const remainder = pool.filter((id) => id !== previousEffectiveLayoutId);
|
|
5458
|
+
return weightedPickBySeed(seed, salt, remainder, weightOf);
|
|
5219
5459
|
}
|
|
5220
|
-
return
|
|
5460
|
+
return picked;
|
|
5221
5461
|
}
|
|
5222
|
-
function
|
|
5223
|
-
|
|
5224
|
-
const budget = maxUnits - 1;
|
|
5225
|
-
let out = "";
|
|
5226
|
-
for (const ch of Array.from(text)) {
|
|
5227
|
-
if (measureTextUnits(out + ch, weight) > budget) break;
|
|
5228
|
-
out += ch;
|
|
5229
|
-
}
|
|
5230
|
-
if (out === "") {
|
|
5231
|
-
return measureTextUnits("\u2026", weight) > maxUnits ? "" : "\u2026";
|
|
5232
|
-
}
|
|
5233
|
-
return `${out}\u2026`;
|
|
5462
|
+
function resolveIrStrategy(ir) {
|
|
5463
|
+
return resolveNarrative(ir.narrative).strategy;
|
|
5234
5464
|
}
|
|
5235
|
-
function
|
|
5236
|
-
|
|
5237
|
-
const
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5465
|
+
function resolveOneEffectiveLayoutId(ir, slide, seed, strategy, pageKey, previousEffectiveLayoutId) {
|
|
5466
|
+
const tokens = resolveStyle(ir.theme.id, ir.theme.style);
|
|
5467
|
+
const bgSpec = slide.background ?? tokens.defaultBackgrounds[slide.type];
|
|
5468
|
+
const imageCoverTakeover = bgSpec.kind === "asset" && (slide.type === "cover" || slide.type === "chapter");
|
|
5469
|
+
if (imageCoverTakeover) return null;
|
|
5470
|
+
if (slide.layout) {
|
|
5471
|
+
const requestedLayoutDef = getLayout(slide.layout);
|
|
5472
|
+
if (requestedLayoutDef?.kind === "takeover" && findImageComponent(slide) != null) {
|
|
5473
|
+
return slide.layout;
|
|
5474
|
+
}
|
|
5242
5475
|
}
|
|
5243
|
-
|
|
5244
|
-
|
|
5476
|
+
const themeDef = getThemeDefinition(ir.theme.id);
|
|
5477
|
+
return resolveArchetypeId(
|
|
5478
|
+
slide.type,
|
|
5479
|
+
themeDef.layouts,
|
|
5480
|
+
seed,
|
|
5481
|
+
pageKey,
|
|
5482
|
+
slide.layout,
|
|
5483
|
+
strategy,
|
|
5484
|
+
previousEffectiveLayoutId,
|
|
5485
|
+
slide.beat
|
|
5486
|
+
);
|
|
5487
|
+
}
|
|
5488
|
+
var deckEffectiveLayoutIdsCache = /* @__PURE__ */ new WeakMap();
|
|
5489
|
+
function resolveDeckEffectiveLayoutIds(ir) {
|
|
5490
|
+
const cached = deckEffectiveLayoutIdsCache.get(ir);
|
|
5491
|
+
if (cached) return cached;
|
|
5492
|
+
const seed = cachedDeckSeed(ir);
|
|
5493
|
+
const strategy = resolveIrStrategy(ir);
|
|
5494
|
+
const deckIds = [];
|
|
5495
|
+
for (let i = 0; i < ir.slides.length; i++) {
|
|
5496
|
+
const slide = ir.slides[i];
|
|
5497
|
+
const previous = i > 0 ? deckIds[i - 1] : null;
|
|
5498
|
+
deckIds.push(resolveOneEffectiveLayoutId(ir, slide, seed, strategy, slide.id ?? String(i), previous));
|
|
5245
5499
|
}
|
|
5246
|
-
|
|
5500
|
+
deckEffectiveLayoutIdsCache.set(ir, deckIds);
|
|
5501
|
+
return deckIds;
|
|
5247
5502
|
}
|
|
5248
|
-
function
|
|
5249
|
-
|
|
5250
|
-
const letterSpacing = opts.letterSpacing ?? 0;
|
|
5251
|
-
const weight = { bold: opts.bold, fontFamily: opts.fontFamily };
|
|
5252
|
-
const units = measureTextUnits(text, weight);
|
|
5253
|
-
if (units <= 0) return { text, fontSize: opts.fontSize, truncated: false };
|
|
5254
|
-
const charCount = Array.from(text).length;
|
|
5255
|
-
const spacingBudget = Math.max(0, charCount - 1) * letterSpacing;
|
|
5256
|
-
const availableWidth = Math.max(0, opts.maxWidth - spacingBudget);
|
|
5257
|
-
const fitted = Math.min(opts.fontSize, Math.floor(availableWidth / units));
|
|
5258
|
-
if (fitted >= minFontSize) return { text, fontSize: fitted, truncated: false };
|
|
5259
|
-
return {
|
|
5260
|
-
text: truncateToUnits(text, availableWidth / minFontSize, weight),
|
|
5261
|
-
fontSize: minFontSize,
|
|
5262
|
-
truncated: true
|
|
5263
|
-
};
|
|
5503
|
+
function resolveEffectiveLayoutId(ir, slide, index) {
|
|
5504
|
+
return resolveDeckEffectiveLayoutIds(ir)[index] ?? null;
|
|
5264
5505
|
}
|
|
5265
|
-
function
|
|
5266
|
-
const
|
|
5267
|
-
const
|
|
5268
|
-
|
|
5269
|
-
const weight = { bold: options.bold, fontFamily: options.fontFamily };
|
|
5270
|
-
if (!content) {
|
|
5271
|
-
return { lines: [], fontSize: options.fontSize, lineHeight: 0, truncated: false };
|
|
5272
|
-
}
|
|
5273
|
-
const baseUnits = options.maxWidth / options.fontSize;
|
|
5274
|
-
let maxUnits = baseUnits;
|
|
5275
|
-
let lines = wrapWithUnits(content, maxUnits, weight);
|
|
5276
|
-
for (let i = 0; lines.length > maxLines && i < 8; i += 1) {
|
|
5277
|
-
maxUnits *= 1.14;
|
|
5278
|
-
lines = wrapWithUnits(content, maxUnits, weight);
|
|
5279
|
-
}
|
|
5280
|
-
if (lines.length > maxLines) {
|
|
5281
|
-
lines = [
|
|
5282
|
-
...lines.slice(0, maxLines - 1),
|
|
5283
|
-
lines.slice(maxLines - 1).join("")
|
|
5284
|
-
];
|
|
5285
|
-
}
|
|
5286
|
-
if (options.balanceLines) {
|
|
5287
|
-
lines = balanceWrappedLines(content, lines, weight);
|
|
5288
|
-
}
|
|
5289
|
-
const longest = Math.max(...lines.map((l) => measureTextUnits(l, weight)), 1);
|
|
5290
|
-
const fittedFontSize2 = Math.min(
|
|
5291
|
-
options.fontSize,
|
|
5292
|
-
Math.floor(options.maxWidth / longest)
|
|
5293
|
-
);
|
|
5294
|
-
const fontSize = Math.max(1, fittedFontSize2);
|
|
5295
|
-
return {
|
|
5296
|
-
lines,
|
|
5297
|
-
fontSize,
|
|
5298
|
-
lineHeight: Math.round(fontSize * lineHeightRatio),
|
|
5299
|
-
truncated: false
|
|
5300
|
-
};
|
|
5506
|
+
function resolveEffectiveLayoutBodyCapacity(ir, slide, index) {
|
|
5507
|
+
const layoutId = resolveEffectiveLayoutId(ir, slide, index);
|
|
5508
|
+
const capacity = layoutId === null ? void 0 : getLayout(layoutId)?.slots.find((s) => s.name === "body")?.capacity;
|
|
5509
|
+
return { layoutId, capacity };
|
|
5301
5510
|
}
|
|
5302
5511
|
|
|
5303
5512
|
// src/svg/ir-quality.ts
|
|
@@ -6600,82 +6809,6 @@ function ellipseToOp(el, gradients) {
|
|
|
6600
6809
|
return op;
|
|
6601
6810
|
}
|
|
6602
6811
|
|
|
6603
|
-
// src/svg/fonts.ts
|
|
6604
|
-
var SAFE_FONTS = new Set(
|
|
6605
|
-
[
|
|
6606
|
-
// Latin sans
|
|
6607
|
-
"Arial",
|
|
6608
|
-
"Calibri",
|
|
6609
|
-
"Tahoma",
|
|
6610
|
-
"Verdana",
|
|
6611
|
-
"Segoe UI",
|
|
6612
|
-
// Latin serif
|
|
6613
|
-
"Georgia",
|
|
6614
|
-
"Times New Roman",
|
|
6615
|
-
"Cambria",
|
|
6616
|
-
// Latin mono
|
|
6617
|
-
"Consolas",
|
|
6618
|
-
"Courier New",
|
|
6619
|
-
"Lucida Console",
|
|
6620
|
-
// CJK (Windows)
|
|
6621
|
-
"Microsoft YaHei",
|
|
6622
|
-
"\u5FAE\u8F6F\u96C5\u9ED1",
|
|
6623
|
-
"SimSun",
|
|
6624
|
-
"\u5B8B\u4F53",
|
|
6625
|
-
"SimHei",
|
|
6626
|
-
"\u9ED1\u4F53",
|
|
6627
|
-
"KaiTi",
|
|
6628
|
-
"\u6977\u4F53",
|
|
6629
|
-
"FangSong",
|
|
6630
|
-
"\u4EFF\u5B8B"
|
|
6631
|
-
].map((f) => f.toLowerCase())
|
|
6632
|
-
);
|
|
6633
|
-
var ROLE_DEFAULT = {
|
|
6634
|
-
heading: "Microsoft YaHei",
|
|
6635
|
-
body: "Microsoft YaHei",
|
|
6636
|
-
mono: "Consolas"
|
|
6637
|
-
};
|
|
6638
|
-
function resolveFontFace(stack, role) {
|
|
6639
|
-
for (const raw of stack) {
|
|
6640
|
-
const name = raw.replace(/['"]/g, "").trim();
|
|
6641
|
-
if (SAFE_FONTS.has(name.toLowerCase())) return name;
|
|
6642
|
-
}
|
|
6643
|
-
return ROLE_DEFAULT[role];
|
|
6644
|
-
}
|
|
6645
|
-
var CJK_SAFE_FACES = new Set(
|
|
6646
|
-
["Microsoft YaHei", "\u5FAE\u8F6F\u96C5\u9ED1", "SimSun", "\u5B8B\u4F53", "SimHei", "\u9ED1\u4F53", "KaiTi", "\u6977\u4F53", "FangSong", "\u4EFF\u5B8B"].map(
|
|
6647
|
-
(f) => f.toLowerCase()
|
|
6648
|
-
)
|
|
6649
|
-
);
|
|
6650
|
-
var EA_FALLBACK_FACE = ROLE_DEFAULT.heading;
|
|
6651
|
-
function eaFontFaceFor(latinFace) {
|
|
6652
|
-
const name = latinFace.replace(/['"]/g, "").trim();
|
|
6653
|
-
return CJK_SAFE_FACES.has(name.toLowerCase()) ? name : EA_FALLBACK_FACE;
|
|
6654
|
-
}
|
|
6655
|
-
var SERIF_SAFE_FACES = new Set(
|
|
6656
|
-
["Georgia", "Times New Roman", "Cambria", "SimSun", "\u5B8B\u4F53", "FangSong", "\u4EFF\u5B8B", "KaiTi", "\u6977\u4F53"].map(
|
|
6657
|
-
(f) => f.toLowerCase()
|
|
6658
|
-
)
|
|
6659
|
-
);
|
|
6660
|
-
var PREVIEW_FALLBACK = {
|
|
6661
|
-
serif: "Songti SC, STSong, serif",
|
|
6662
|
-
sans: "PingFang SC, Helvetica Neue, sans-serif",
|
|
6663
|
-
mono: "Menlo, monospace"
|
|
6664
|
-
};
|
|
6665
|
-
function resolveFontStack(stack, role) {
|
|
6666
|
-
const face = resolveFontFace(stack, role);
|
|
6667
|
-
const fallback = role === "mono" ? PREVIEW_FALLBACK.mono : SERIF_SAFE_FACES.has(face.toLowerCase()) ? PREVIEW_FALLBACK.serif : PREVIEW_FALLBACK.sans;
|
|
6668
|
-
return `${face}, ${fallback}`;
|
|
6669
|
-
}
|
|
6670
|
-
function isMonoFontFamily(fontFamily) {
|
|
6671
|
-
return fontFamily.endsWith(`, ${PREVIEW_FALLBACK.mono}`);
|
|
6672
|
-
}
|
|
6673
|
-
function isBold(weight) {
|
|
6674
|
-
if (!weight) return false;
|
|
6675
|
-
if (weight === "bold" || weight === "bolder") return true;
|
|
6676
|
-
return parseInt(weight, 10) >= 600;
|
|
6677
|
-
}
|
|
6678
|
-
|
|
6679
6812
|
// src/pptx/svg2pptx/text.ts
|
|
6680
6813
|
var ASCENT_RATIO = 0.8;
|
|
6681
6814
|
function num5(el, name, fallback = 0) {
|
|
@@ -6770,6 +6903,10 @@ function textToOp(el) {
|
|
|
6770
6903
|
}
|
|
6771
6904
|
|
|
6772
6905
|
// src/pptx/svg2pptx/line.ts
|
|
6906
|
+
var EMU_PER_IN = 914400;
|
|
6907
|
+
function roundsToZeroEmu(px) {
|
|
6908
|
+
return Math.round(Math.abs(px) / PX_PER_IN * EMU_PER_IN) === 0;
|
|
6909
|
+
}
|
|
6773
6910
|
function num6(el, name, fallback = 0) {
|
|
6774
6911
|
const v = el.getAttribute(name);
|
|
6775
6912
|
if (v == null) return fallback;
|
|
@@ -6789,7 +6926,7 @@ function lineToOp(el) {
|
|
|
6789
6926
|
const y2 = num6(el, "y2");
|
|
6790
6927
|
const dx = x2 - x1;
|
|
6791
6928
|
const dy = y2 - y1;
|
|
6792
|
-
const isPoint = dx
|
|
6929
|
+
const isPoint = roundsToZeroEmu(dx) && roundsToZeroEmu(dy);
|
|
6793
6930
|
const w = isPoint ? 0.75 : Math.abs(dx);
|
|
6794
6931
|
const h = isPoint ? 0.75 : Math.abs(dy);
|
|
6795
6932
|
const strokeColor = el.getAttribute("stroke") || "#000000";
|
|
@@ -8019,62 +8156,6 @@ var bullets = {
|
|
|
8019
8156
|
}
|
|
8020
8157
|
};
|
|
8021
8158
|
|
|
8022
|
-
// src/svg/ink.ts
|
|
8023
|
-
var LUMINANCE_INK_THRESHOLD = 0.4;
|
|
8024
|
-
var LARGE_TEXT_MIN_PX = 24;
|
|
8025
|
-
var CONTRAST_RATIO_LARGE = 3;
|
|
8026
|
-
var CONTRAST_RATIO_BODY = 4.5;
|
|
8027
|
-
function relativeLuminance(hex) {
|
|
8028
|
-
let h = hex.trim().replace(/^#/, "");
|
|
8029
|
-
if (h.length === 3 || h.length === 4) h = [...h].map((c) => c + c).join("");
|
|
8030
|
-
if (h.length === 8) h = h.slice(0, 6);
|
|
8031
|
-
if (!/^[0-9a-fA-F]{6}$/.test(h)) return 0;
|
|
8032
|
-
const n = parseInt(h, 16);
|
|
8033
|
-
const chan = [n >> 16 & 255, n >> 8 & 255, n & 255].map((v) => {
|
|
8034
|
-
const c = v / 255;
|
|
8035
|
-
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
8036
|
-
});
|
|
8037
|
-
return 0.2126 * chan[0] + 0.7152 * chan[1] + 0.0722 * chan[2];
|
|
8038
|
-
}
|
|
8039
|
-
function contrastRatio(hexA, hexB) {
|
|
8040
|
-
const la = relativeLuminance(hexA);
|
|
8041
|
-
const lb = relativeLuminance(hexB);
|
|
8042
|
-
const lighter = Math.max(la, lb);
|
|
8043
|
-
const darker = Math.min(la, lb);
|
|
8044
|
-
return (lighter + 0.05) / (darker + 0.05);
|
|
8045
|
-
}
|
|
8046
|
-
function requiredContrastRatio(fontSizePx) {
|
|
8047
|
-
return fontSizePx >= LARGE_TEXT_MIN_PX ? CONTRAST_RATIO_LARGE : CONTRAST_RATIO_BODY;
|
|
8048
|
-
}
|
|
8049
|
-
var DARK_INK = "#0A0E14";
|
|
8050
|
-
var LIGHT_INK = "#FFFFFF";
|
|
8051
|
-
function readableOn(bgHex) {
|
|
8052
|
-
const darkContrast = contrastRatio(DARK_INK, bgHex);
|
|
8053
|
-
const lightContrast = contrastRatio(LIGHT_INK, bgHex);
|
|
8054
|
-
if (darkContrast === lightContrast) {
|
|
8055
|
-
return relativeLuminance(bgHex) > LUMINANCE_INK_THRESHOLD ? DARK_INK : LIGHT_INK;
|
|
8056
|
-
}
|
|
8057
|
-
return darkContrast > lightContrast ? DARK_INK : LIGHT_INK;
|
|
8058
|
-
}
|
|
8059
|
-
function accessibleInk(preferredFill, bgHex, fontSizePx) {
|
|
8060
|
-
return contrastRatio(preferredFill, bgHex) >= requiredContrastRatio(fontSizePx) ? preferredFill : readableOn(bgHex);
|
|
8061
|
-
}
|
|
8062
|
-
function blendOver(fg, bg, alpha2) {
|
|
8063
|
-
const toRgb = (hex) => {
|
|
8064
|
-
const n = parseInt(hex.replace("#", ""), 16);
|
|
8065
|
-
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
8066
|
-
};
|
|
8067
|
-
const [fr, fgc, fb] = toRgb(fg);
|
|
8068
|
-
const [br, bgc, bb] = toRgb(bg);
|
|
8069
|
-
const mix = (f, b) => Math.round(f * alpha2 + b * (1 - alpha2));
|
|
8070
|
-
const toHex2 = (v) => v.toString(16).padStart(2, "0");
|
|
8071
|
-
return `#${toHex2(mix(fr, br))}${toHex2(mix(fgc, bgc))}${toHex2(mix(fb, bb))}`;
|
|
8072
|
-
}
|
|
8073
|
-
function accessibleOpacity(inkHex, bgHex, fontSizePx, preferredOpacity) {
|
|
8074
|
-
const blended = blendOver(inkHex, bgHex, preferredOpacity);
|
|
8075
|
-
return contrastRatio(blended, bgHex) >= requiredContrastRatio(fontSizePx) ? preferredOpacity : 1;
|
|
8076
|
-
}
|
|
8077
|
-
|
|
8078
8159
|
// src/svg/components/quote.tsx
|
|
8079
8160
|
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
8080
8161
|
var QUOTE_ZONE = 60;
|
|
@@ -9265,6 +9346,7 @@ function renderFunnel(series, palette, x0, y0, w, h, _mutedColor, _textColor, _a
|
|
|
9265
9346
|
}
|
|
9266
9347
|
var DUMBBELL_LABEL_W = 96;
|
|
9267
9348
|
var DUMBBELL_DOT_R = 5;
|
|
9349
|
+
var DUMBBELL_VALUE_LABEL_W = 56;
|
|
9268
9350
|
function renderDumbbell(series, _palette, x0, y0, w, h, mutedColor, textColor, accentColor2, _showGrid) {
|
|
9269
9351
|
const fromData = series[0]?.data ?? [];
|
|
9270
9352
|
const toData = series[1]?.data ?? [];
|
|
@@ -9274,7 +9356,7 @@ function renderDumbbell(series, _palette, x0, y0, w, h, mutedColor, textColor, a
|
|
|
9274
9356
|
const min = Math.min(0, ...all);
|
|
9275
9357
|
const max = Math.max(...all, 1);
|
|
9276
9358
|
const plotX = x0 + DUMBBELL_LABEL_W + 12;
|
|
9277
|
-
const plotW = Math.max(1, w - DUMBBELL_LABEL_W - 12 -
|
|
9359
|
+
const plotW = Math.max(1, w - DUMBBELL_LABEL_W - 12 - DUMBBELL_VALUE_LABEL_W);
|
|
9278
9360
|
const rowH = h / rows;
|
|
9279
9361
|
const vx = (v) => plotX + (v - min) / (max - min) * plotW;
|
|
9280
9362
|
return /* @__PURE__ */ jsx14(Fragment7, { children: Array.from({ length: rows }, (_, i) => {
|
|
@@ -9286,6 +9368,16 @@ function renderDumbbell(series, _palette, x0, y0, w, h, mutedColor, textColor, a
|
|
|
9286
9368
|
fontSize: 13,
|
|
9287
9369
|
minFontSize: 10
|
|
9288
9370
|
});
|
|
9371
|
+
const fromValueLabel = fitSvgLine(String(from.y), {
|
|
9372
|
+
maxWidth: DUMBBELL_VALUE_LABEL_W,
|
|
9373
|
+
fontSize: LABEL_FONT_SIZE,
|
|
9374
|
+
minFontSize: 10
|
|
9375
|
+
});
|
|
9376
|
+
const toValueLabel = fitSvgLine(String(to.y), {
|
|
9377
|
+
maxWidth: DUMBBELL_VALUE_LABEL_W,
|
|
9378
|
+
fontSize: 12.5,
|
|
9379
|
+
minFontSize: 10
|
|
9380
|
+
});
|
|
9289
9381
|
const x1 = vx(from.y);
|
|
9290
9382
|
const x2 = vx(to.y);
|
|
9291
9383
|
return /* @__PURE__ */ jsxs12("g", { children: [
|
|
@@ -9309,25 +9401,27 @@ function renderDumbbell(series, _palette, x0, y0, w, h, mutedColor, textColor, a
|
|
|
9309
9401
|
/* @__PURE__ */ jsx14(
|
|
9310
9402
|
"text",
|
|
9311
9403
|
{
|
|
9404
|
+
"data-truncated": fromValueLabel.truncated ? "1" : void 0,
|
|
9312
9405
|
x: x1,
|
|
9313
9406
|
y: cy - 11,
|
|
9314
9407
|
textAnchor: "middle",
|
|
9315
|
-
fontSize:
|
|
9408
|
+
fontSize: fromValueLabel.fontSize,
|
|
9316
9409
|
fill: mutedColor,
|
|
9317
9410
|
dominantBaseline: "alphabetic",
|
|
9318
|
-
children:
|
|
9411
|
+
children: fromValueLabel.text
|
|
9319
9412
|
}
|
|
9320
9413
|
),
|
|
9321
9414
|
/* @__PURE__ */ jsx14(
|
|
9322
9415
|
"text",
|
|
9323
9416
|
{
|
|
9417
|
+
"data-truncated": toValueLabel.truncated ? "1" : void 0,
|
|
9324
9418
|
x: x2 + DUMBBELL_DOT_R + 8,
|
|
9325
9419
|
y: cy + 4,
|
|
9326
|
-
fontSize:
|
|
9420
|
+
fontSize: toValueLabel.fontSize,
|
|
9327
9421
|
fontWeight: "bold",
|
|
9328
9422
|
fill: accentColor2,
|
|
9329
9423
|
dominantBaseline: "alphabetic",
|
|
9330
|
-
children:
|
|
9424
|
+
children: toValueLabel.text
|
|
9331
9425
|
}
|
|
9332
9426
|
)
|
|
9333
9427
|
] }, i);
|
|
@@ -11592,9 +11686,15 @@ function fitYTitleStack(text, availH) {
|
|
|
11592
11686
|
const kept = chars.slice(0, Math.max(0, maxChars - 1));
|
|
11593
11687
|
return { chars: [...kept, "\u2026"], truncated: true };
|
|
11594
11688
|
}
|
|
11595
|
-
function cellLayout2(item, cardW) {
|
|
11689
|
+
function cellLayout2(item, cardW, fontFamily) {
|
|
11596
11690
|
const contentW = cardW - PAD_X5 * 2;
|
|
11597
|
-
const title = fitSvgLine(item.title, {
|
|
11691
|
+
const title = fitSvgLine(item.title, {
|
|
11692
|
+
maxWidth: contentW,
|
|
11693
|
+
fontSize: TITLE_SIZE5,
|
|
11694
|
+
minFontSize: 12,
|
|
11695
|
+
bold: true,
|
|
11696
|
+
fontFamily
|
|
11697
|
+
});
|
|
11598
11698
|
const tag = item.tag ? fitSvgLine(item.tag, { maxWidth: contentW, fontSize: TAG_SIZE, minFontSize: 10 }) : null;
|
|
11599
11699
|
const contentH = TITLE_LH3 + (tag ? GAP_TITLE_TAG + TAG_LH : 0);
|
|
11600
11700
|
return { title, tag, contentH };
|
|
@@ -11666,7 +11766,7 @@ var matrix = {
|
|
|
11666
11766
|
const row = Math.floor(i / cols);
|
|
11667
11767
|
const x = box.x + gridX0 + col * (cardW + CARD_GAP2);
|
|
11668
11768
|
const y = gridTop + row * (rowH + CARD_GAP2);
|
|
11669
|
-
const cell = cellLayout2(item, cardW);
|
|
11769
|
+
const cell = cellLayout2(item, cardW, ctx.fonts.heading);
|
|
11670
11770
|
const titleBaseline = y + PAD_TOP3 + TITLE_SIZE5;
|
|
11671
11771
|
return /* @__PURE__ */ jsxs24("g", { children: [
|
|
11672
11772
|
/* @__PURE__ */ jsx26(
|
|
@@ -14851,6 +14951,7 @@ function fitHeadingLines(text, opts) {
|
|
|
14851
14951
|
maxLines,
|
|
14852
14952
|
lineHeightRatio,
|
|
14853
14953
|
balanceLines: true,
|
|
14954
|
+
minPt,
|
|
14854
14955
|
...weight
|
|
14855
14956
|
});
|
|
14856
14957
|
if (!content.trim() || first.fontSize >= minPt) return first;
|
|
@@ -14862,6 +14963,7 @@ function fitHeadingLines(text, opts) {
|
|
|
14862
14963
|
maxLines,
|
|
14863
14964
|
lineHeightRatio,
|
|
14864
14965
|
balanceLines: true,
|
|
14966
|
+
minPt,
|
|
14865
14967
|
...weight
|
|
14866
14968
|
});
|
|
14867
14969
|
return { ...result, truncated: truncatedContent !== content };
|
|
@@ -20726,7 +20828,7 @@ function resolveMotifId(ir, slide, index) {
|
|
|
20726
20828
|
|
|
20727
20829
|
// src/svg/FullSlideSvg.tsx
|
|
20728
20830
|
import { jsx as jsx89, jsxs as jsxs85 } from "react/jsx-runtime";
|
|
20729
|
-
function
|
|
20831
|
+
function resolveBackgroundHex2(spec, surfaceFallback) {
|
|
20730
20832
|
if (spec.kind === "color") return spec.value;
|
|
20731
20833
|
if (spec.kind === "gradient") return spec.from;
|
|
20732
20834
|
return surfaceFallback;
|
|
@@ -20734,7 +20836,7 @@ function resolveBackgroundHex(spec, surfaceFallback) {
|
|
|
20734
20836
|
function resolveOverrideBackgroundHex(spec, surfaceFallback, paintedFallback) {
|
|
20735
20837
|
if (spec.kind === "gradient") return gradientBands(spec.from, spec.to, 3)[1];
|
|
20736
20838
|
if (spec.kind === "asset") return paintedFallback;
|
|
20737
|
-
return
|
|
20839
|
+
return resolveBackgroundHex2(spec, surfaceFallback);
|
|
20738
20840
|
}
|
|
20739
20841
|
function buildCtx(tokens, images, components, defaultBg, bodyFontPx, chartPaletteOffset) {
|
|
20740
20842
|
return {
|
|
@@ -20779,7 +20881,7 @@ function FullSlideSvg({
|
|
|
20779
20881
|
preserveAspectRatio
|
|
20780
20882
|
}) {
|
|
20781
20883
|
const tokens = resolveStyle(ir.theme.id, ir.theme.style);
|
|
20782
|
-
const themeDefaultBg =
|
|
20884
|
+
const themeDefaultBg = resolveBackgroundHex2(tokens.defaultBackgrounds[slide.type], tokens.colors.surface);
|
|
20783
20885
|
const defaultBg = slide.background ? resolveOverrideBackgroundHex(slide.background, tokens.colors.surface, themeDefaultBg) : themeDefaultBg;
|
|
20784
20886
|
const bodyFontPx = PACING_BUDGETS[resolveNarrative(ir.narrative).pacing].bodyBaselinePx;
|
|
20785
20887
|
const chartPaletteOffset = resolveChartPaletteOffset(cachedDeckSeed(ir), tokens.colors.chartPalette.length);
|
|
@@ -22065,6 +22167,11 @@ function findContrastIssues(markup) {
|
|
|
22065
22167
|
function __collectImageBackedTextRuns(markup) {
|
|
22066
22168
|
return runContrastWalk(markup).imageBackedRuns;
|
|
22067
22169
|
}
|
|
22170
|
+
function resolveCandidateFill(rawFill) {
|
|
22171
|
+
if (rawFill?.startsWith("#")) return rawFill;
|
|
22172
|
+
if (rawFill?.startsWith("url(")) return null;
|
|
22173
|
+
return void 0;
|
|
22174
|
+
}
|
|
22068
22175
|
function runContrastWalk(markup) {
|
|
22069
22176
|
const root = parseSvg(markup);
|
|
22070
22177
|
const issues = [];
|
|
@@ -22132,7 +22239,8 @@ function runContrastWalk(markup) {
|
|
|
22132
22239
|
} else {
|
|
22133
22240
|
const shapeFill = el.getAttribute("fill");
|
|
22134
22241
|
const opaqueEnough = currentFillOpacity * currentOpacityProduct >= MIN_BG_OPACITY;
|
|
22135
|
-
|
|
22242
|
+
const resolvedFill = resolveCandidateFill(shapeFill);
|
|
22243
|
+
if (resolvedFill !== void 0 && opaqueEnough) {
|
|
22136
22244
|
if (localWedge) {
|
|
22137
22245
|
paintedShapes.push(
|
|
22138
22246
|
sectorShape(
|
|
@@ -22144,14 +22252,14 @@ function runContrastWalk(markup) {
|
|
|
22144
22252
|
startA: localWedge.startA,
|
|
22145
22253
|
span: localWedge.span
|
|
22146
22254
|
},
|
|
22147
|
-
|
|
22255
|
+
resolvedFill
|
|
22148
22256
|
)
|
|
22149
22257
|
);
|
|
22150
22258
|
} else {
|
|
22151
|
-
paintedShapes.push(rectShape(absX, absY, w, h,
|
|
22259
|
+
paintedShapes.push(rectShape(absX, absY, w, h, resolvedFill));
|
|
22152
22260
|
}
|
|
22153
22261
|
if (w * h >= MIN_BG_REGION_AREA) {
|
|
22154
|
-
regions.push({ x: absX, y: absY, w, h, fill:
|
|
22262
|
+
regions.push({ x: absX, y: absY, w, h, fill: resolvedFill });
|
|
22155
22263
|
}
|
|
22156
22264
|
}
|
|
22157
22265
|
}
|
|
@@ -22163,9 +22271,10 @@ function runContrastWalk(markup) {
|
|
|
22163
22271
|
const localRy = Number(el.getAttribute(tag === "circle" ? "r" : "ry") ?? 0);
|
|
22164
22272
|
const shapeFill = el.getAttribute("fill");
|
|
22165
22273
|
const opaqueEnough = currentFillOpacity * currentOpacityProduct >= MIN_BG_OPACITY;
|
|
22166
|
-
|
|
22274
|
+
const resolvedFill = resolveCandidateFill(shapeFill);
|
|
22275
|
+
if (!inDecorSubtree && resolvedFill !== void 0 && opaqueEnough) {
|
|
22167
22276
|
paintedShapes.push(
|
|
22168
|
-
ellipseShape(ax + cx * as, ay + cy * as, localRx * as, localRy * as,
|
|
22277
|
+
ellipseShape(ax + cx * as, ay + cy * as, localRx * as, localRy * as, resolvedFill)
|
|
22169
22278
|
);
|
|
22170
22279
|
}
|
|
22171
22280
|
} else if (tag === "text" || tag === "tspan") {
|
|
@@ -22432,7 +22541,7 @@ function auditDeck(ir, opts = {}) {
|
|
|
22432
22541
|
return runPixelPass(ir, report);
|
|
22433
22542
|
}
|
|
22434
22543
|
async function runPixelPass(ir, report) {
|
|
22435
|
-
const { runPixelContrastAudit } = await import("./pixel-audit-
|
|
22544
|
+
const { runPixelContrastAudit } = await import("./pixel-audit-ZB4RSPHG.js");
|
|
22436
22545
|
const pixelFindings = await runPixelContrastAudit(ir);
|
|
22437
22546
|
return {
|
|
22438
22547
|
...report,
|
|
@@ -22487,4 +22596,4 @@ export {
|
|
|
22487
22596
|
__collectImageBackedTextRuns,
|
|
22488
22597
|
auditDeck
|
|
22489
22598
|
};
|
|
22490
|
-
//# sourceMappingURL=chunk-
|
|
22599
|
+
//# sourceMappingURL=chunk-6JJGXB5S.js.map
|