claude-presentation-master 4.2.0 → 4.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.mts +172 -6
- package/dist/index.d.ts +172 -6
- package/dist/index.js +815 -88
- package/dist/index.mjs +748 -24
- package/package.json +5 -3
package/dist/index.js
CHANGED
|
@@ -243,9 +243,9 @@ function isFunction(value) {
|
|
|
243
243
|
return typeof value === "function";
|
|
244
244
|
}
|
|
245
245
|
function createErrorClass(createImpl) {
|
|
246
|
-
var _super = function(
|
|
247
|
-
Error.call(
|
|
248
|
-
|
|
246
|
+
var _super = function(instance10) {
|
|
247
|
+
Error.call(instance10);
|
|
248
|
+
instance10.stack = new Error().stack;
|
|
249
249
|
};
|
|
250
250
|
var ctorFunc = createImpl(_super);
|
|
251
251
|
ctorFunc.prototype = Object.create(Error.prototype);
|
|
@@ -55351,7 +55351,7 @@ var require_util2 = __commonJS({
|
|
|
55351
55351
|
return path13;
|
|
55352
55352
|
}
|
|
55353
55353
|
exports2.normalize = normalize2;
|
|
55354
|
-
function
|
|
55354
|
+
function join7(aRoot, aPath) {
|
|
55355
55355
|
if (aRoot === "") {
|
|
55356
55356
|
aRoot = ".";
|
|
55357
55357
|
}
|
|
@@ -55383,7 +55383,7 @@ var require_util2 = __commonJS({
|
|
|
55383
55383
|
}
|
|
55384
55384
|
return joined;
|
|
55385
55385
|
}
|
|
55386
|
-
exports2.join =
|
|
55386
|
+
exports2.join = join7;
|
|
55387
55387
|
exports2.isAbsolute = function(aPath) {
|
|
55388
55388
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
55389
55389
|
};
|
|
@@ -55556,7 +55556,7 @@ var require_util2 = __commonJS({
|
|
|
55556
55556
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
55557
55557
|
}
|
|
55558
55558
|
}
|
|
55559
|
-
sourceURL =
|
|
55559
|
+
sourceURL = join7(urlGenerate(parsed), sourceURL);
|
|
55560
55560
|
}
|
|
55561
55561
|
return normalize2(sourceURL);
|
|
55562
55562
|
}
|
|
@@ -57367,7 +57367,7 @@ var require_escodegen = __commonJS({
|
|
|
57367
57367
|
function noEmptySpace() {
|
|
57368
57368
|
return space ? space : " ";
|
|
57369
57369
|
}
|
|
57370
|
-
function
|
|
57370
|
+
function join7(left2, right2) {
|
|
57371
57371
|
var leftSource, rightSource, leftCharCode, rightCharCode;
|
|
57372
57372
|
leftSource = toSourceNodeWhenNeeded(left2).toString();
|
|
57373
57373
|
if (leftSource.length === 0) {
|
|
@@ -57698,8 +57698,8 @@ var require_escodegen = __commonJS({
|
|
|
57698
57698
|
} else {
|
|
57699
57699
|
result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
|
|
57700
57700
|
}
|
|
57701
|
-
result =
|
|
57702
|
-
result = [
|
|
57701
|
+
result = join7(result, operator);
|
|
57702
|
+
result = [join7(
|
|
57703
57703
|
result,
|
|
57704
57704
|
that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
|
|
57705
57705
|
), ")"];
|
|
@@ -57842,11 +57842,11 @@ var require_escodegen = __commonJS({
|
|
|
57842
57842
|
var result, fragment;
|
|
57843
57843
|
result = ["class"];
|
|
57844
57844
|
if (stmt.id) {
|
|
57845
|
-
result =
|
|
57845
|
+
result = join7(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
|
|
57846
57846
|
}
|
|
57847
57847
|
if (stmt.superClass) {
|
|
57848
|
-
fragment =
|
|
57849
|
-
result =
|
|
57848
|
+
fragment = join7("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
|
|
57849
|
+
result = join7(result, fragment);
|
|
57850
57850
|
}
|
|
57851
57851
|
result.push(space);
|
|
57852
57852
|
result.push(this.generateStatement(stmt.body, S_TFFT));
|
|
@@ -57859,9 +57859,9 @@ var require_escodegen = __commonJS({
|
|
|
57859
57859
|
return escapeDirective(stmt.directive) + this.semicolon(flags);
|
|
57860
57860
|
},
|
|
57861
57861
|
DoWhileStatement: function(stmt, flags) {
|
|
57862
|
-
var result =
|
|
57862
|
+
var result = join7("do", this.maybeBlock(stmt.body, S_TFFF));
|
|
57863
57863
|
result = this.maybeBlockSuffix(stmt.body, result);
|
|
57864
|
-
return
|
|
57864
|
+
return join7(result, [
|
|
57865
57865
|
"while" + space + "(",
|
|
57866
57866
|
this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
|
|
57867
57867
|
")" + this.semicolon(flags)
|
|
@@ -57897,11 +57897,11 @@ var require_escodegen = __commonJS({
|
|
|
57897
57897
|
ExportDefaultDeclaration: function(stmt, flags) {
|
|
57898
57898
|
var result = ["export"], bodyFlags;
|
|
57899
57899
|
bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
|
|
57900
|
-
result =
|
|
57900
|
+
result = join7(result, "default");
|
|
57901
57901
|
if (isStatement(stmt.declaration)) {
|
|
57902
|
-
result =
|
|
57902
|
+
result = join7(result, this.generateStatement(stmt.declaration, bodyFlags));
|
|
57903
57903
|
} else {
|
|
57904
|
-
result =
|
|
57904
|
+
result = join7(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
|
|
57905
57905
|
}
|
|
57906
57906
|
return result;
|
|
57907
57907
|
},
|
|
@@ -57909,15 +57909,15 @@ var require_escodegen = __commonJS({
|
|
|
57909
57909
|
var result = ["export"], bodyFlags, that = this;
|
|
57910
57910
|
bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
|
|
57911
57911
|
if (stmt.declaration) {
|
|
57912
|
-
return
|
|
57912
|
+
return join7(result, this.generateStatement(stmt.declaration, bodyFlags));
|
|
57913
57913
|
}
|
|
57914
57914
|
if (stmt.specifiers) {
|
|
57915
57915
|
if (stmt.specifiers.length === 0) {
|
|
57916
|
-
result =
|
|
57916
|
+
result = join7(result, "{" + space + "}");
|
|
57917
57917
|
} else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
|
|
57918
|
-
result =
|
|
57918
|
+
result = join7(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
|
|
57919
57919
|
} else {
|
|
57920
|
-
result =
|
|
57920
|
+
result = join7(result, "{");
|
|
57921
57921
|
withIndent(function(indent2) {
|
|
57922
57922
|
var i, iz;
|
|
57923
57923
|
result.push(newline);
|
|
@@ -57935,7 +57935,7 @@ var require_escodegen = __commonJS({
|
|
|
57935
57935
|
result.push(base + "}");
|
|
57936
57936
|
}
|
|
57937
57937
|
if (stmt.source) {
|
|
57938
|
-
result =
|
|
57938
|
+
result = join7(result, [
|
|
57939
57939
|
"from" + space,
|
|
57940
57940
|
// ModuleSpecifier
|
|
57941
57941
|
this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
|
|
@@ -58023,7 +58023,7 @@ var require_escodegen = __commonJS({
|
|
|
58023
58023
|
];
|
|
58024
58024
|
cursor = 0;
|
|
58025
58025
|
if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
|
|
58026
|
-
result =
|
|
58026
|
+
result = join7(result, [
|
|
58027
58027
|
this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
|
|
58028
58028
|
]);
|
|
58029
58029
|
++cursor;
|
|
@@ -58033,7 +58033,7 @@ var require_escodegen = __commonJS({
|
|
|
58033
58033
|
result.push(",");
|
|
58034
58034
|
}
|
|
58035
58035
|
if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
|
|
58036
|
-
result =
|
|
58036
|
+
result = join7(result, [
|
|
58037
58037
|
space,
|
|
58038
58038
|
this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
|
|
58039
58039
|
]);
|
|
@@ -58062,7 +58062,7 @@ var require_escodegen = __commonJS({
|
|
|
58062
58062
|
}
|
|
58063
58063
|
}
|
|
58064
58064
|
}
|
|
58065
|
-
result =
|
|
58065
|
+
result = join7(result, [
|
|
58066
58066
|
"from" + space,
|
|
58067
58067
|
// ModuleSpecifier
|
|
58068
58068
|
this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
|
|
@@ -58116,7 +58116,7 @@ var require_escodegen = __commonJS({
|
|
|
58116
58116
|
return result;
|
|
58117
58117
|
},
|
|
58118
58118
|
ThrowStatement: function(stmt, flags) {
|
|
58119
|
-
return [
|
|
58119
|
+
return [join7(
|
|
58120
58120
|
"throw",
|
|
58121
58121
|
this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
|
|
58122
58122
|
), this.semicolon(flags)];
|
|
@@ -58127,7 +58127,7 @@ var require_escodegen = __commonJS({
|
|
|
58127
58127
|
result = this.maybeBlockSuffix(stmt.block, result);
|
|
58128
58128
|
if (stmt.handlers) {
|
|
58129
58129
|
for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
|
|
58130
|
-
result =
|
|
58130
|
+
result = join7(result, this.generateStatement(stmt.handlers[i], S_TFFF));
|
|
58131
58131
|
if (stmt.finalizer || i + 1 !== iz) {
|
|
58132
58132
|
result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
|
|
58133
58133
|
}
|
|
@@ -58135,7 +58135,7 @@ var require_escodegen = __commonJS({
|
|
|
58135
58135
|
} else {
|
|
58136
58136
|
guardedHandlers = stmt.guardedHandlers || [];
|
|
58137
58137
|
for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
|
|
58138
|
-
result =
|
|
58138
|
+
result = join7(result, this.generateStatement(guardedHandlers[i], S_TFFF));
|
|
58139
58139
|
if (stmt.finalizer || i + 1 !== iz) {
|
|
58140
58140
|
result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
|
|
58141
58141
|
}
|
|
@@ -58143,13 +58143,13 @@ var require_escodegen = __commonJS({
|
|
|
58143
58143
|
if (stmt.handler) {
|
|
58144
58144
|
if (Array.isArray(stmt.handler)) {
|
|
58145
58145
|
for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
|
|
58146
|
-
result =
|
|
58146
|
+
result = join7(result, this.generateStatement(stmt.handler[i], S_TFFF));
|
|
58147
58147
|
if (stmt.finalizer || i + 1 !== iz) {
|
|
58148
58148
|
result = this.maybeBlockSuffix(stmt.handler[i].body, result);
|
|
58149
58149
|
}
|
|
58150
58150
|
}
|
|
58151
58151
|
} else {
|
|
58152
|
-
result =
|
|
58152
|
+
result = join7(result, this.generateStatement(stmt.handler, S_TFFF));
|
|
58153
58153
|
if (stmt.finalizer) {
|
|
58154
58154
|
result = this.maybeBlockSuffix(stmt.handler.body, result);
|
|
58155
58155
|
}
|
|
@@ -58157,7 +58157,7 @@ var require_escodegen = __commonJS({
|
|
|
58157
58157
|
}
|
|
58158
58158
|
}
|
|
58159
58159
|
if (stmt.finalizer) {
|
|
58160
|
-
result =
|
|
58160
|
+
result = join7(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
|
|
58161
58161
|
}
|
|
58162
58162
|
return result;
|
|
58163
58163
|
},
|
|
@@ -58191,7 +58191,7 @@ var require_escodegen = __commonJS({
|
|
|
58191
58191
|
withIndent(function() {
|
|
58192
58192
|
if (stmt.test) {
|
|
58193
58193
|
result = [
|
|
58194
|
-
|
|
58194
|
+
join7("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
|
|
58195
58195
|
":"
|
|
58196
58196
|
];
|
|
58197
58197
|
} else {
|
|
@@ -58239,9 +58239,9 @@ var require_escodegen = __commonJS({
|
|
|
58239
58239
|
result.push(this.maybeBlock(stmt.consequent, S_TFFF));
|
|
58240
58240
|
result = this.maybeBlockSuffix(stmt.consequent, result);
|
|
58241
58241
|
if (stmt.alternate.type === Syntax.IfStatement) {
|
|
58242
|
-
result =
|
|
58242
|
+
result = join7(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
|
|
58243
58243
|
} else {
|
|
58244
|
-
result =
|
|
58244
|
+
result = join7(result, join7("else", this.maybeBlock(stmt.alternate, bodyFlags)));
|
|
58245
58245
|
}
|
|
58246
58246
|
} else {
|
|
58247
58247
|
result.push(this.maybeBlock(stmt.consequent, bodyFlags));
|
|
@@ -58342,7 +58342,7 @@ var require_escodegen = __commonJS({
|
|
|
58342
58342
|
},
|
|
58343
58343
|
ReturnStatement: function(stmt, flags) {
|
|
58344
58344
|
if (stmt.argument) {
|
|
58345
|
-
return [
|
|
58345
|
+
return [join7(
|
|
58346
58346
|
"return",
|
|
58347
58347
|
this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
|
|
58348
58348
|
), this.semicolon(flags)];
|
|
@@ -58431,14 +58431,14 @@ var require_escodegen = __commonJS({
|
|
|
58431
58431
|
if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
|
|
58432
58432
|
result = [fragment, noEmptySpace(), expr.operator];
|
|
58433
58433
|
} else {
|
|
58434
|
-
result =
|
|
58434
|
+
result = join7(fragment, expr.operator);
|
|
58435
58435
|
}
|
|
58436
58436
|
fragment = this.generateExpression(expr.right, rightPrecedence, flags);
|
|
58437
58437
|
if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
|
|
58438
58438
|
result.push(noEmptySpace());
|
|
58439
58439
|
result.push(fragment);
|
|
58440
58440
|
} else {
|
|
58441
|
-
result =
|
|
58441
|
+
result = join7(result, fragment);
|
|
58442
58442
|
}
|
|
58443
58443
|
if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
|
|
58444
58444
|
return ["(", result, ")"];
|
|
@@ -58478,7 +58478,7 @@ var require_escodegen = __commonJS({
|
|
|
58478
58478
|
var result, length, i, iz, itemFlags;
|
|
58479
58479
|
length = expr["arguments"].length;
|
|
58480
58480
|
itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
|
|
58481
|
-
result =
|
|
58481
|
+
result = join7(
|
|
58482
58482
|
"new",
|
|
58483
58483
|
this.generateExpression(expr.callee, Precedence.New, itemFlags)
|
|
58484
58484
|
);
|
|
@@ -58528,11 +58528,11 @@ var require_escodegen = __commonJS({
|
|
|
58528
58528
|
var result, fragment, rightCharCode, leftSource, leftCharCode;
|
|
58529
58529
|
fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
|
|
58530
58530
|
if (space === "") {
|
|
58531
|
-
result =
|
|
58531
|
+
result = join7(expr.operator, fragment);
|
|
58532
58532
|
} else {
|
|
58533
58533
|
result = [expr.operator];
|
|
58534
58534
|
if (expr.operator.length > 2) {
|
|
58535
|
-
result =
|
|
58535
|
+
result = join7(result, fragment);
|
|
58536
58536
|
} else {
|
|
58537
58537
|
leftSource = toSourceNodeWhenNeeded(result).toString();
|
|
58538
58538
|
leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
|
|
@@ -58555,7 +58555,7 @@ var require_escodegen = __commonJS({
|
|
|
58555
58555
|
result = "yield";
|
|
58556
58556
|
}
|
|
58557
58557
|
if (expr.argument) {
|
|
58558
|
-
result =
|
|
58558
|
+
result = join7(
|
|
58559
58559
|
result,
|
|
58560
58560
|
this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
|
|
58561
58561
|
);
|
|
@@ -58563,7 +58563,7 @@ var require_escodegen = __commonJS({
|
|
|
58563
58563
|
return parenthesize(result, Precedence.Yield, precedence);
|
|
58564
58564
|
},
|
|
58565
58565
|
AwaitExpression: function(expr, precedence, flags) {
|
|
58566
|
-
var result =
|
|
58566
|
+
var result = join7(
|
|
58567
58567
|
expr.all ? "await*" : "await",
|
|
58568
58568
|
this.generateExpression(expr.argument, Precedence.Await, E_TTT)
|
|
58569
58569
|
);
|
|
@@ -58646,11 +58646,11 @@ var require_escodegen = __commonJS({
|
|
|
58646
58646
|
var result, fragment;
|
|
58647
58647
|
result = ["class"];
|
|
58648
58648
|
if (expr.id) {
|
|
58649
|
-
result =
|
|
58649
|
+
result = join7(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
|
|
58650
58650
|
}
|
|
58651
58651
|
if (expr.superClass) {
|
|
58652
|
-
fragment =
|
|
58653
|
-
result =
|
|
58652
|
+
fragment = join7("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
|
|
58653
|
+
result = join7(result, fragment);
|
|
58654
58654
|
}
|
|
58655
58655
|
result.push(space);
|
|
58656
58656
|
result.push(this.generateStatement(expr.body, S_TFFT));
|
|
@@ -58665,7 +58665,7 @@ var require_escodegen = __commonJS({
|
|
|
58665
58665
|
}
|
|
58666
58666
|
if (expr.kind === "get" || expr.kind === "set") {
|
|
58667
58667
|
fragment = [
|
|
58668
|
-
|
|
58668
|
+
join7(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
|
|
58669
58669
|
this.generateFunctionBody(expr.value)
|
|
58670
58670
|
];
|
|
58671
58671
|
} else {
|
|
@@ -58675,7 +58675,7 @@ var require_escodegen = __commonJS({
|
|
|
58675
58675
|
this.generateFunctionBody(expr.value)
|
|
58676
58676
|
];
|
|
58677
58677
|
}
|
|
58678
|
-
return
|
|
58678
|
+
return join7(result, fragment);
|
|
58679
58679
|
},
|
|
58680
58680
|
Property: function(expr, precedence, flags) {
|
|
58681
58681
|
if (expr.kind === "get" || expr.kind === "set") {
|
|
@@ -58870,7 +58870,7 @@ var require_escodegen = __commonJS({
|
|
|
58870
58870
|
for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
|
|
58871
58871
|
fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
|
|
58872
58872
|
if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
|
|
58873
|
-
result =
|
|
58873
|
+
result = join7(result, fragment);
|
|
58874
58874
|
} else {
|
|
58875
58875
|
result.push(fragment);
|
|
58876
58876
|
}
|
|
@@ -58878,13 +58878,13 @@ var require_escodegen = __commonJS({
|
|
|
58878
58878
|
});
|
|
58879
58879
|
}
|
|
58880
58880
|
if (expr.filter) {
|
|
58881
|
-
result =
|
|
58881
|
+
result = join7(result, "if" + space);
|
|
58882
58882
|
fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
|
|
58883
|
-
result =
|
|
58883
|
+
result = join7(result, ["(", fragment, ")"]);
|
|
58884
58884
|
}
|
|
58885
58885
|
if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
|
|
58886
58886
|
fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
|
|
58887
|
-
result =
|
|
58887
|
+
result = join7(result, fragment);
|
|
58888
58888
|
}
|
|
58889
58889
|
result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
|
|
58890
58890
|
return result;
|
|
@@ -58900,8 +58900,8 @@ var require_escodegen = __commonJS({
|
|
|
58900
58900
|
} else {
|
|
58901
58901
|
fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
|
|
58902
58902
|
}
|
|
58903
|
-
fragment =
|
|
58904
|
-
fragment =
|
|
58903
|
+
fragment = join7(fragment, expr.of ? "of" : "in");
|
|
58904
|
+
fragment = join7(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
|
|
58905
58905
|
return ["for" + space + "(", fragment, ")"];
|
|
58906
58906
|
},
|
|
58907
58907
|
SpreadElement: function(expr, precedence, flags) {
|
|
@@ -72706,9 +72706,9 @@ var require_dist9 = __commonJS({
|
|
|
72706
72706
|
var singleton = void 0;
|
|
72707
72707
|
var singletonPromise = void 0;
|
|
72708
72708
|
async function getQuickJS() {
|
|
72709
|
-
singletonPromise ?? (singletonPromise = (0, variants_1.newQuickJSWASMModule)().then((
|
|
72710
|
-
singleton =
|
|
72711
|
-
return
|
|
72709
|
+
singletonPromise ?? (singletonPromise = (0, variants_1.newQuickJSWASMModule)().then((instance10) => {
|
|
72710
|
+
singleton = instance10;
|
|
72711
|
+
return instance10;
|
|
72712
72712
|
}));
|
|
72713
72713
|
return await singletonPromise;
|
|
72714
72714
|
}
|
|
@@ -84924,9 +84924,9 @@ async function getConnectionTransport(options) {
|
|
|
84924
84924
|
throw new Error("Could not detect required browser platform");
|
|
84925
84925
|
}
|
|
84926
84926
|
const { convertPuppeteerChannelToBrowsersChannel: convertPuppeteerChannelToBrowsersChannel2 } = await Promise.resolve().then(() => (init_LaunchOptions(), LaunchOptions_exports));
|
|
84927
|
-
const { join:
|
|
84927
|
+
const { join: join7 } = await import("path");
|
|
84928
84928
|
const userDataDir = resolveDefaultUserDataDir3(Browser4.CHROME, platform, convertPuppeteerChannelToBrowsersChannel2(options.channel));
|
|
84929
|
-
const portPath =
|
|
84929
|
+
const portPath = join7(userDataDir, "DevToolsActivePort");
|
|
84930
84930
|
try {
|
|
84931
84931
|
const fileContent = await environment.value.fs.promises.readFile(portPath, "ascii");
|
|
84932
84932
|
const [rawPort, rawPath] = fileContent.split("\n").map((line) => {
|
|
@@ -90544,7 +90544,7 @@ var require_env_paths = __commonJS({
|
|
|
90544
90544
|
var path13 = require("path");
|
|
90545
90545
|
var os9 = require("os");
|
|
90546
90546
|
var homedir2 = os9.homedir();
|
|
90547
|
-
var
|
|
90547
|
+
var tmpdir3 = os9.tmpdir();
|
|
90548
90548
|
var { env: env2 } = process;
|
|
90549
90549
|
var macos = (name) => {
|
|
90550
90550
|
const library = path13.join(homedir2, "Library");
|
|
@@ -90553,7 +90553,7 @@ var require_env_paths = __commonJS({
|
|
|
90553
90553
|
config: path13.join(library, "Preferences", name),
|
|
90554
90554
|
cache: path13.join(library, "Caches", name),
|
|
90555
90555
|
log: path13.join(library, "Logs", name),
|
|
90556
|
-
temp: path13.join(
|
|
90556
|
+
temp: path13.join(tmpdir3, name)
|
|
90557
90557
|
};
|
|
90558
90558
|
};
|
|
90559
90559
|
var windows = (name) => {
|
|
@@ -90565,7 +90565,7 @@ var require_env_paths = __commonJS({
|
|
|
90565
90565
|
config: path13.join(appData, name, "Config"),
|
|
90566
90566
|
cache: path13.join(localAppData, name, "Cache"),
|
|
90567
90567
|
log: path13.join(localAppData, name, "Log"),
|
|
90568
|
-
temp: path13.join(
|
|
90568
|
+
temp: path13.join(tmpdir3, name)
|
|
90569
90569
|
};
|
|
90570
90570
|
};
|
|
90571
90571
|
var linux = (name) => {
|
|
@@ -90576,7 +90576,7 @@ var require_env_paths = __commonJS({
|
|
|
90576
90576
|
cache: path13.join(env2.XDG_CACHE_HOME || path13.join(homedir2, ".cache"), name),
|
|
90577
90577
|
// https://wiki.debian.org/XDGBaseDirectorySpecification#state
|
|
90578
90578
|
log: path13.join(env2.XDG_STATE_HOME || path13.join(homedir2, ".local", "state"), name),
|
|
90579
|
-
temp: path13.join(
|
|
90579
|
+
temp: path13.join(tmpdir3, username, name)
|
|
90580
90580
|
};
|
|
90581
90581
|
};
|
|
90582
90582
|
var envPaths = (name, options) => {
|
|
@@ -91688,6 +91688,7 @@ __export(index_exports, {
|
|
|
91688
91688
|
SlideQualityReviewer: () => SlideQualityReviewer,
|
|
91689
91689
|
VERSION: () => VERSION,
|
|
91690
91690
|
VisualDesignSystem: () => VisualDesignSystem,
|
|
91691
|
+
VisualQAEngine: () => VisualQAEngine,
|
|
91691
91692
|
createNanoBananaProvider: () => createNanoBananaProvider,
|
|
91692
91693
|
createPresentationEngineV2: () => createPresentationEngineV2,
|
|
91693
91694
|
createRendererV2: () => createRendererV2,
|
|
@@ -91703,6 +91704,7 @@ __export(index_exports, {
|
|
|
91703
91704
|
getSlideGenerator: () => getSlideGenerator,
|
|
91704
91705
|
getSlideQualityReviewer: () => getSlideQualityReviewer,
|
|
91705
91706
|
getVisualDesignSystem: () => getVisualDesignSystem,
|
|
91707
|
+
getVisualQAEngine: () => getVisualQAEngine,
|
|
91706
91708
|
initContentAnalyzer: () => initContentAnalyzer,
|
|
91707
91709
|
initDeckQualityReviewer: () => initDeckQualityReviewer,
|
|
91708
91710
|
initKB: () => initKB,
|
|
@@ -91711,6 +91713,7 @@ __export(index_exports, {
|
|
|
91711
91713
|
initSlideGenerator: () => initSlideGenerator,
|
|
91712
91714
|
initSlideQualityReviewer: () => initSlideQualityReviewer,
|
|
91713
91715
|
initVisualDesignSystem: () => initVisualDesignSystem,
|
|
91716
|
+
initVisualQAEngine: () => initVisualQAEngine,
|
|
91714
91717
|
runCodeQualityCheck: () => runCodeQualityCheck,
|
|
91715
91718
|
validateCodeQuality: () => validateCodeQuality
|
|
91716
91719
|
});
|
|
@@ -95098,6 +95101,7 @@ ${content}
|
|
|
95098
95101
|
--accent-red: #dc3545;
|
|
95099
95102
|
--border-color: ${isLight ? "#dee2e6" : "rgba(255,255,255,0.1)"};
|
|
95100
95103
|
--header-bar: ${p.primary};
|
|
95104
|
+
--mckinsey-blue: ${p.accent};
|
|
95101
95105
|
}`;
|
|
95102
95106
|
}
|
|
95103
95107
|
/**
|
|
@@ -95606,8 +95610,615 @@ function createRendererV2(presentationType = "consulting_deck", kb) {
|
|
|
95606
95610
|
return new RendererV2(presentationType, kb);
|
|
95607
95611
|
}
|
|
95608
95612
|
|
|
95609
|
-
// src/
|
|
95613
|
+
// src/qa/VisualQAEngine.ts
|
|
95610
95614
|
var import_fs9 = require("fs");
|
|
95615
|
+
var import_path6 = require("path");
|
|
95616
|
+
var import_os = require("os");
|
|
95617
|
+
var VisualQAEngine = class {
|
|
95618
|
+
kb;
|
|
95619
|
+
browser = null;
|
|
95620
|
+
initialized = false;
|
|
95621
|
+
// KB-loaded thresholds
|
|
95622
|
+
minWhitespace = 0.35;
|
|
95623
|
+
minContrast = 4.5;
|
|
95624
|
+
// WCAG AA
|
|
95625
|
+
maxWordsPerSlide = 50;
|
|
95626
|
+
targetScore = 95;
|
|
95627
|
+
constructor() {
|
|
95628
|
+
this.kb = getKB();
|
|
95629
|
+
}
|
|
95630
|
+
/**
|
|
95631
|
+
* Initialize Playwright browser.
|
|
95632
|
+
*/
|
|
95633
|
+
async initialize() {
|
|
95634
|
+
if (this.initialized) return;
|
|
95635
|
+
const playwright = await import("playwright");
|
|
95636
|
+
this.browser = await playwright.chromium.launch({
|
|
95637
|
+
headless: true,
|
|
95638
|
+
args: ["--no-sandbox", "--disable-setuid-sandbox"]
|
|
95639
|
+
});
|
|
95640
|
+
await this.loadKBThresholds();
|
|
95641
|
+
this.initialized = true;
|
|
95642
|
+
console.log("[VisualQA] Initialized with Playwright");
|
|
95643
|
+
}
|
|
95644
|
+
/**
|
|
95645
|
+
* Load quality thresholds from Knowledge Base.
|
|
95646
|
+
*/
|
|
95647
|
+
async loadKBThresholds() {
|
|
95648
|
+
try {
|
|
95649
|
+
const whitespaceResult = this.kb.queryOptional("design_system.whitespace_rules");
|
|
95650
|
+
if (whitespaceResult.value?.min) {
|
|
95651
|
+
this.minWhitespace = whitespaceResult.value.min;
|
|
95652
|
+
}
|
|
95653
|
+
} catch {
|
|
95654
|
+
}
|
|
95655
|
+
}
|
|
95656
|
+
/**
|
|
95657
|
+
* Capture screenshots of all slides in a presentation.
|
|
95658
|
+
*/
|
|
95659
|
+
async captureSlides(html) {
|
|
95660
|
+
await this.initialize();
|
|
95661
|
+
if (!this.browser) throw new Error("Browser not initialized");
|
|
95662
|
+
const tempDir = (0, import_fs9.mkdtempSync)((0, import_path6.join)((0, import_os.tmpdir)(), "visual-qa-"));
|
|
95663
|
+
const tempFile = (0, import_path6.join)(tempDir, "presentation.html");
|
|
95664
|
+
const modifiedHtml = html.replace(
|
|
95665
|
+
/hash:\s*true/g,
|
|
95666
|
+
"hash: false"
|
|
95667
|
+
);
|
|
95668
|
+
(0, import_fs9.writeFileSync)(tempFile, modifiedHtml);
|
|
95669
|
+
const page = await this.browser.newPage();
|
|
95670
|
+
await page.setViewportSize({ width: 1920, height: 1080 });
|
|
95671
|
+
await page.goto(`file://${tempFile}`, { waitUntil: "networkidle" });
|
|
95672
|
+
await page.waitForTimeout(1500);
|
|
95673
|
+
const slideCount = await page.evaluate(() => {
|
|
95674
|
+
const reveal = window.Reveal;
|
|
95675
|
+
if (reveal) {
|
|
95676
|
+
return reveal.getTotalSlides();
|
|
95677
|
+
}
|
|
95678
|
+
return document.querySelectorAll(".slides > section").length;
|
|
95679
|
+
});
|
|
95680
|
+
console.log(`[VisualQA] Capturing ${slideCount} slides...`);
|
|
95681
|
+
const screenshots = [];
|
|
95682
|
+
for (let i = 0; i < slideCount; i++) {
|
|
95683
|
+
await page.evaluate((index) => {
|
|
95684
|
+
const reveal = window.Reveal;
|
|
95685
|
+
if (reveal) {
|
|
95686
|
+
reveal.slide(index, 0, 0);
|
|
95687
|
+
}
|
|
95688
|
+
}, i);
|
|
95689
|
+
await page.waitForTimeout(400);
|
|
95690
|
+
const screenshot = await page.screenshot({
|
|
95691
|
+
type: "png",
|
|
95692
|
+
fullPage: false
|
|
95693
|
+
});
|
|
95694
|
+
screenshots.push(screenshot);
|
|
95695
|
+
console.log(`[VisualQA] Captured slide ${i + 1}/${slideCount}`);
|
|
95696
|
+
}
|
|
95697
|
+
await page.close();
|
|
95698
|
+
try {
|
|
95699
|
+
(0, import_fs9.unlinkSync)(tempFile);
|
|
95700
|
+
} catch {
|
|
95701
|
+
}
|
|
95702
|
+
return screenshots;
|
|
95703
|
+
}
|
|
95704
|
+
/**
|
|
95705
|
+
* Analyze a single slide screenshot.
|
|
95706
|
+
*/
|
|
95707
|
+
async analyzeSlide(screenshot, slideIndex, slideTitle, presentationType) {
|
|
95708
|
+
const issues = [];
|
|
95709
|
+
let score = 100;
|
|
95710
|
+
const typeThresholds = this.getTypeThresholds(presentationType);
|
|
95711
|
+
const whitespacePercentage = await this.measureWhitespace(screenshot);
|
|
95712
|
+
if (whitespacePercentage < typeThresholds.minWhitespace) {
|
|
95713
|
+
const penalty = Math.round((typeThresholds.minWhitespace - whitespacePercentage) * 100);
|
|
95714
|
+
score -= penalty;
|
|
95715
|
+
issues.push({
|
|
95716
|
+
severity: penalty > 15 ? "critical" : "major",
|
|
95717
|
+
category: "whitespace",
|
|
95718
|
+
issue: `Whitespace is ${(whitespacePercentage * 100).toFixed(1)}% (need ${typeThresholds.minWhitespace * 100}%+)`,
|
|
95719
|
+
measurement: whitespacePercentage,
|
|
95720
|
+
threshold: typeThresholds.minWhitespace,
|
|
95721
|
+
fix: "Reduce content or increase margins"
|
|
95722
|
+
});
|
|
95723
|
+
}
|
|
95724
|
+
const colorContrast = await this.measureContrast(screenshot);
|
|
95725
|
+
if (colorContrast < this.minContrast) {
|
|
95726
|
+
score -= 20;
|
|
95727
|
+
issues.push({
|
|
95728
|
+
severity: "critical",
|
|
95729
|
+
category: "contrast",
|
|
95730
|
+
issue: `Contrast ratio is ${colorContrast.toFixed(1)}:1 (WCAG AA requires 4.5:1)`,
|
|
95731
|
+
measurement: colorContrast,
|
|
95732
|
+
threshold: this.minContrast,
|
|
95733
|
+
fix: "Increase contrast between text and background"
|
|
95734
|
+
});
|
|
95735
|
+
}
|
|
95736
|
+
const textDensity = await this.measureTextDensity(screenshot);
|
|
95737
|
+
const maxDensity = typeThresholds.maxWordsPerSlide / 100;
|
|
95738
|
+
if (textDensity > maxDensity) {
|
|
95739
|
+
score -= 15;
|
|
95740
|
+
issues.push({
|
|
95741
|
+
severity: "major",
|
|
95742
|
+
category: "density",
|
|
95743
|
+
issue: `Text is too dense for ${presentationType}`,
|
|
95744
|
+
measurement: textDensity,
|
|
95745
|
+
threshold: maxDensity,
|
|
95746
|
+
fix: "Split content across multiple slides"
|
|
95747
|
+
});
|
|
95748
|
+
}
|
|
95749
|
+
const visualBalance = await this.measureBalance(screenshot);
|
|
95750
|
+
const balanceThreshold = ["ted_keynote", "sales_pitch"].includes(presentationType) ? 20 : 60;
|
|
95751
|
+
if (visualBalance < balanceThreshold) {
|
|
95752
|
+
score -= 10;
|
|
95753
|
+
issues.push({
|
|
95754
|
+
severity: "minor",
|
|
95755
|
+
category: "balance",
|
|
95756
|
+
issue: `Visual balance score is ${visualBalance}/100`,
|
|
95757
|
+
measurement: visualBalance,
|
|
95758
|
+
threshold: balanceThreshold,
|
|
95759
|
+
fix: "Redistribute content for better visual balance"
|
|
95760
|
+
});
|
|
95761
|
+
}
|
|
95762
|
+
const hierarchyClear = await this.checkHierarchy(screenshot);
|
|
95763
|
+
if (!hierarchyClear) {
|
|
95764
|
+
score -= 10;
|
|
95765
|
+
issues.push({
|
|
95766
|
+
severity: "major",
|
|
95767
|
+
category: "hierarchy",
|
|
95768
|
+
issue: "No clear visual hierarchy detected",
|
|
95769
|
+
fix: "Add distinct title styling or increase heading size"
|
|
95770
|
+
});
|
|
95771
|
+
}
|
|
95772
|
+
const glanceTestPassed = textDensity < 0.3 && hierarchyClear;
|
|
95773
|
+
if (!glanceTestPassed && presentationType !== "investment_banking") {
|
|
95774
|
+
score -= 10;
|
|
95775
|
+
issues.push({
|
|
95776
|
+
severity: "major",
|
|
95777
|
+
category: "density",
|
|
95778
|
+
issue: "Fails 3-second glance test",
|
|
95779
|
+
fix: "Simplify to one clear message per slide"
|
|
95780
|
+
});
|
|
95781
|
+
}
|
|
95782
|
+
const minBalanceForPro = ["ted_keynote", "sales_pitch"].includes(presentationType) ? 20 : 50;
|
|
95783
|
+
const professionalLook = whitespacePercentage >= typeThresholds.minWhitespace * 0.9 && colorContrast >= this.minContrast * 0.9 && visualBalance >= minBalanceForPro;
|
|
95784
|
+
if (!professionalLook) {
|
|
95785
|
+
score -= 5;
|
|
95786
|
+
issues.push({
|
|
95787
|
+
severity: "minor",
|
|
95788
|
+
category: "professional",
|
|
95789
|
+
issue: "Slide lacks professional polish",
|
|
95790
|
+
fix: "Review spacing, colors, and alignment"
|
|
95791
|
+
});
|
|
95792
|
+
}
|
|
95793
|
+
return {
|
|
95794
|
+
slideIndex,
|
|
95795
|
+
title: slideTitle,
|
|
95796
|
+
screenshot,
|
|
95797
|
+
whitespacePercentage,
|
|
95798
|
+
textDensity,
|
|
95799
|
+
colorContrast,
|
|
95800
|
+
visualBalance,
|
|
95801
|
+
glanceTestPassed,
|
|
95802
|
+
hierarchyClear,
|
|
95803
|
+
professionalLook,
|
|
95804
|
+
score: Math.max(0, Math.min(100, score)),
|
|
95805
|
+
issues,
|
|
95806
|
+
passed: score >= this.targetScore
|
|
95807
|
+
};
|
|
95808
|
+
}
|
|
95809
|
+
/**
|
|
95810
|
+
* Analyze entire deck visually.
|
|
95811
|
+
*/
|
|
95812
|
+
async analyzeDeck(html, slides, presentationType) {
|
|
95813
|
+
console.log(`[VisualQA] Starting visual analysis of ${slides.length} slides...`);
|
|
95814
|
+
const screenshots = await this.captureSlides(html);
|
|
95815
|
+
const slideAnalyses = [];
|
|
95816
|
+
for (let i = 0; i < screenshots.length; i++) {
|
|
95817
|
+
const slide = slides[i];
|
|
95818
|
+
const analysis = await this.analyzeSlide(
|
|
95819
|
+
screenshots[i],
|
|
95820
|
+
i,
|
|
95821
|
+
slide?.title || `Slide ${i + 1}`,
|
|
95822
|
+
presentationType
|
|
95823
|
+
);
|
|
95824
|
+
slideAnalyses.push(analysis);
|
|
95825
|
+
console.log(`[VisualQA] Slide ${i + 1}: ${analysis.score}/100 ${analysis.passed ? "\u2713" : "\u2717"}`);
|
|
95826
|
+
}
|
|
95827
|
+
const consistency = this.calculateConsistency(slideAnalyses);
|
|
95828
|
+
const deckIssues = [];
|
|
95829
|
+
const failingSlides = slideAnalyses.filter((s) => !s.passed);
|
|
95830
|
+
if (failingSlides.length > 0) {
|
|
95831
|
+
deckIssues.push(`${failingSlides.length} slides below quality threshold`);
|
|
95832
|
+
}
|
|
95833
|
+
if (consistency < 80) {
|
|
95834
|
+
deckIssues.push(`Visual inconsistency across slides (${consistency}/100)`);
|
|
95835
|
+
}
|
|
95836
|
+
const avgScore = slideAnalyses.reduce((sum, s) => sum + s.score, 0) / slideAnalyses.length;
|
|
95837
|
+
const consistencyBonus = consistency >= 90 ? 2 : consistency >= 80 ? 0 : -3;
|
|
95838
|
+
const overallScore = Math.round(Math.min(100, Math.max(0, avgScore + consistencyBonus)));
|
|
95839
|
+
const passed = overallScore >= this.targetScore && failingSlides.length === 0;
|
|
95840
|
+
const summary = passed ? `\u2705 Visual QA PASSED: ${overallScore}/100 with ${consistency}% consistency` : `\u274C Visual QA FAILED: ${overallScore}/100, ${failingSlides.length} slides need work`;
|
|
95841
|
+
console.log(`[VisualQA] ${summary}`);
|
|
95842
|
+
return {
|
|
95843
|
+
slides: slideAnalyses,
|
|
95844
|
+
overallScore,
|
|
95845
|
+
passed,
|
|
95846
|
+
consistency,
|
|
95847
|
+
deckIssues,
|
|
95848
|
+
summary
|
|
95849
|
+
};
|
|
95850
|
+
}
|
|
95851
|
+
/**
|
|
95852
|
+
* Generate remediation feedback for failing slides.
|
|
95853
|
+
*/
|
|
95854
|
+
generateRemediationFeedback(analysis) {
|
|
95855
|
+
const feedback = [];
|
|
95856
|
+
for (const slide of analysis.slides) {
|
|
95857
|
+
if (!slide.passed) {
|
|
95858
|
+
const fixes = [];
|
|
95859
|
+
const problems = [];
|
|
95860
|
+
for (const issue of slide.issues) {
|
|
95861
|
+
problems.push(issue.issue);
|
|
95862
|
+
fixes.push(issue.fix);
|
|
95863
|
+
}
|
|
95864
|
+
feedback.push({
|
|
95865
|
+
slideIndex: slide.slideIndex,
|
|
95866
|
+
currentScore: slide.score,
|
|
95867
|
+
targetScore: this.targetScore,
|
|
95868
|
+
specificFixes: fixes,
|
|
95869
|
+
visualProblems: problems
|
|
95870
|
+
});
|
|
95871
|
+
}
|
|
95872
|
+
}
|
|
95873
|
+
return feedback;
|
|
95874
|
+
}
|
|
95875
|
+
/**
|
|
95876
|
+
* Run the full QA loop until passing or max iterations.
|
|
95877
|
+
*/
|
|
95878
|
+
async runQALoop(generateFn, remediateFn, presentationType, maxIterations = 3) {
|
|
95879
|
+
console.log(`[VisualQA] Starting QA loop (max ${maxIterations} iterations)...`);
|
|
95880
|
+
let iteration = 0;
|
|
95881
|
+
let currentAnalysis = null;
|
|
95882
|
+
let initialScore = 0;
|
|
95883
|
+
const improvements = [];
|
|
95884
|
+
while (iteration < maxIterations) {
|
|
95885
|
+
iteration++;
|
|
95886
|
+
console.log(`
|
|
95887
|
+
[VisualQA] === Iteration ${iteration} ===`);
|
|
95888
|
+
const { html, slides } = await generateFn();
|
|
95889
|
+
currentAnalysis = await this.analyzeDeck(html, slides, presentationType);
|
|
95890
|
+
if (iteration === 1) {
|
|
95891
|
+
initialScore = currentAnalysis.overallScore;
|
|
95892
|
+
}
|
|
95893
|
+
if (currentAnalysis.passed) {
|
|
95894
|
+
console.log(`[VisualQA] \u2705 PASSED on iteration ${iteration}!`);
|
|
95895
|
+
break;
|
|
95896
|
+
}
|
|
95897
|
+
const feedback = this.generateRemediationFeedback(currentAnalysis);
|
|
95898
|
+
console.log(`[VisualQA] ${feedback.length} slides need remediation`);
|
|
95899
|
+
for (const fb of feedback) {
|
|
95900
|
+
console.log(` Slide ${fb.slideIndex + 1}: ${fb.currentScore}\u2192${fb.targetScore}`);
|
|
95901
|
+
for (const fix of fb.specificFixes.slice(0, 2)) {
|
|
95902
|
+
console.log(` - ${fix}`);
|
|
95903
|
+
}
|
|
95904
|
+
}
|
|
95905
|
+
improvements.push(`Iteration ${iteration}: ${currentAnalysis.overallScore}/100`);
|
|
95906
|
+
if (iteration < maxIterations) {
|
|
95907
|
+
await remediateFn(feedback);
|
|
95908
|
+
}
|
|
95909
|
+
}
|
|
95910
|
+
if (!currentAnalysis) {
|
|
95911
|
+
throw new Error("No analysis performed");
|
|
95912
|
+
}
|
|
95913
|
+
return {
|
|
95914
|
+
finalScore: currentAnalysis.overallScore,
|
|
95915
|
+
passed: currentAnalysis.passed,
|
|
95916
|
+
iterations: iteration,
|
|
95917
|
+
initialScore,
|
|
95918
|
+
improvements,
|
|
95919
|
+
finalAnalysis: currentAnalysis
|
|
95920
|
+
};
|
|
95921
|
+
}
|
|
95922
|
+
/**
|
|
95923
|
+
* Close browser and cleanup.
|
|
95924
|
+
*/
|
|
95925
|
+
async cleanup() {
|
|
95926
|
+
if (this.browser) {
|
|
95927
|
+
await this.browser.close();
|
|
95928
|
+
this.browser = null;
|
|
95929
|
+
this.initialized = false;
|
|
95930
|
+
}
|
|
95931
|
+
}
|
|
95932
|
+
// =============================================================================
|
|
95933
|
+
// PIXEL ANALYSIS METHODS
|
|
95934
|
+
// =============================================================================
|
|
95935
|
+
/**
|
|
95936
|
+
* Measure whitespace percentage from screenshot.
|
|
95937
|
+
* Uses actual pixel analysis.
|
|
95938
|
+
*/
|
|
95939
|
+
async measureWhitespace(screenshot) {
|
|
95940
|
+
try {
|
|
95941
|
+
const sharp = await import("sharp");
|
|
95942
|
+
const image = sharp.default(screenshot);
|
|
95943
|
+
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
95944
|
+
const totalPixels = info.width * info.height;
|
|
95945
|
+
let backgroundPixels = 0;
|
|
95946
|
+
const bgColor = this.detectBackgroundColor(data, info.width, info.height, info.channels);
|
|
95947
|
+
for (let i = 0; i < data.length; i += info.channels) {
|
|
95948
|
+
const r = data[i];
|
|
95949
|
+
const g = data[i + 1];
|
|
95950
|
+
const b = data[i + 2];
|
|
95951
|
+
if (this.isSimilarColor(r, g, b, bgColor.r, bgColor.g, bgColor.b, 30)) {
|
|
95952
|
+
backgroundPixels++;
|
|
95953
|
+
}
|
|
95954
|
+
}
|
|
95955
|
+
return backgroundPixels / totalPixels;
|
|
95956
|
+
} catch {
|
|
95957
|
+
return 0.4;
|
|
95958
|
+
}
|
|
95959
|
+
}
|
|
95960
|
+
/**
|
|
95961
|
+
* Measure color contrast ratio.
|
|
95962
|
+
*/
|
|
95963
|
+
async measureContrast(screenshot) {
|
|
95964
|
+
try {
|
|
95965
|
+
const sharp = await import("sharp");
|
|
95966
|
+
const image = sharp.default(screenshot);
|
|
95967
|
+
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
95968
|
+
const bgColor = this.detectBackgroundColor(data, info.width, info.height, info.channels);
|
|
95969
|
+
const textColor = this.detectTextColor(data, info.width, info.height, info.channels, bgColor);
|
|
95970
|
+
const bgLuminance = this.relativeLuminance(bgColor.r, bgColor.g, bgColor.b);
|
|
95971
|
+
const textLuminance = this.relativeLuminance(textColor.r, textColor.g, textColor.b);
|
|
95972
|
+
const lighter = Math.max(bgLuminance, textLuminance);
|
|
95973
|
+
const darker = Math.min(bgLuminance, textLuminance);
|
|
95974
|
+
return (lighter + 0.05) / (darker + 0.05);
|
|
95975
|
+
} catch {
|
|
95976
|
+
return 7;
|
|
95977
|
+
}
|
|
95978
|
+
}
|
|
95979
|
+
/**
|
|
95980
|
+
* Measure text density (approximation based on non-background pixels).
|
|
95981
|
+
*/
|
|
95982
|
+
async measureTextDensity(screenshot) {
|
|
95983
|
+
try {
|
|
95984
|
+
const sharp = await import("sharp");
|
|
95985
|
+
const image = sharp.default(screenshot);
|
|
95986
|
+
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
95987
|
+
const bgColor = this.detectBackgroundColor(data, info.width, info.height, info.channels);
|
|
95988
|
+
let contentPixels = 0;
|
|
95989
|
+
const totalPixels = info.width * info.height;
|
|
95990
|
+
for (let i = 0; i < data.length; i += info.channels) {
|
|
95991
|
+
const r = data[i];
|
|
95992
|
+
const g = data[i + 1];
|
|
95993
|
+
const b = data[i + 2];
|
|
95994
|
+
if (!this.isSimilarColor(r, g, b, bgColor.r, bgColor.g, bgColor.b, 30)) {
|
|
95995
|
+
contentPixels++;
|
|
95996
|
+
}
|
|
95997
|
+
}
|
|
95998
|
+
return contentPixels / totalPixels;
|
|
95999
|
+
} catch {
|
|
96000
|
+
return 0.2;
|
|
96001
|
+
}
|
|
96002
|
+
}
|
|
96003
|
+
/**
|
|
96004
|
+
* Measure visual balance (how evenly distributed is the content).
|
|
96005
|
+
* Uses a 3x3 grid to properly detect centered layouts (common in keynotes).
|
|
96006
|
+
*/
|
|
96007
|
+
async measureBalance(screenshot) {
|
|
96008
|
+
try {
|
|
96009
|
+
const sharp = await import("sharp");
|
|
96010
|
+
const image = sharp.default(screenshot);
|
|
96011
|
+
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
96012
|
+
const bgColor = this.detectBackgroundColor(data, info.width, info.height, info.channels);
|
|
96013
|
+
const grid = [0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
96014
|
+
const thirdW = Math.floor(info.width / 3);
|
|
96015
|
+
const thirdH = Math.floor(info.height / 3);
|
|
96016
|
+
for (let y = 0; y < info.height; y++) {
|
|
96017
|
+
for (let x = 0; x < info.width; x++) {
|
|
96018
|
+
const i = (y * info.width + x) * info.channels;
|
|
96019
|
+
const r = data[i];
|
|
96020
|
+
const g = data[i + 1];
|
|
96021
|
+
const b = data[i + 2];
|
|
96022
|
+
if (!this.isSimilarColor(r, g, b, bgColor.r, bgColor.g, bgColor.b, 30)) {
|
|
96023
|
+
const col = x < thirdW ? 0 : x < thirdW * 2 ? 1 : 2;
|
|
96024
|
+
const row = y < thirdH ? 0 : y < thirdH * 2 ? 1 : 2;
|
|
96025
|
+
const cellIndex = row * 3 + col;
|
|
96026
|
+
grid[cellIndex] = (grid[cellIndex] ?? 0) + 1;
|
|
96027
|
+
}
|
|
96028
|
+
}
|
|
96029
|
+
}
|
|
96030
|
+
const total = grid.reduce((a, b) => a + b, 0);
|
|
96031
|
+
if (total === 0) return 100;
|
|
96032
|
+
const centerColumn = (grid[1] ?? 0) + (grid[4] ?? 0) + (grid[7] ?? 0);
|
|
96033
|
+
const leftColumn = (grid[0] ?? 0) + (grid[3] ?? 0) + (grid[6] ?? 0);
|
|
96034
|
+
const rightColumn = (grid[2] ?? 0) + (grid[5] ?? 0) + (grid[8] ?? 0);
|
|
96035
|
+
const centerRatio = centerColumn / total;
|
|
96036
|
+
if (centerRatio > 0.6) {
|
|
96037
|
+
const sideBalance = leftColumn > 0 && rightColumn > 0 ? Math.min(leftColumn, rightColumn) / Math.max(leftColumn, rightColumn) : 1;
|
|
96038
|
+
return Math.round(70 + sideBalance * 30);
|
|
96039
|
+
}
|
|
96040
|
+
const leftTotal = leftColumn + (grid[1] ?? 0) / 2 + (grid[4] ?? 0) / 2 + (grid[7] ?? 0) / 2;
|
|
96041
|
+
const rightTotal = rightColumn + (grid[1] ?? 0) / 2 + (grid[4] ?? 0) / 2 + (grid[7] ?? 0) / 2;
|
|
96042
|
+
const topRow = (grid[0] ?? 0) + (grid[1] ?? 0) + (grid[2] ?? 0);
|
|
96043
|
+
const bottomRow = (grid[6] ?? 0) + (grid[7] ?? 0) + (grid[8] ?? 0);
|
|
96044
|
+
const hBalance = leftTotal > 0 && rightTotal > 0 ? Math.min(leftTotal, rightTotal) / Math.max(leftTotal, rightTotal) : 0.5;
|
|
96045
|
+
const vBalance = topRow > 0 && bottomRow > 0 ? Math.min(topRow, bottomRow) / Math.max(topRow, bottomRow) : 0.5;
|
|
96046
|
+
const score = (hBalance * 0.6 + vBalance * 0.4) * 100;
|
|
96047
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
96048
|
+
} catch {
|
|
96049
|
+
return 75;
|
|
96050
|
+
}
|
|
96051
|
+
}
|
|
96052
|
+
/**
|
|
96053
|
+
* Check if there's clear visual hierarchy.
|
|
96054
|
+
*/
|
|
96055
|
+
async checkHierarchy(screenshot) {
|
|
96056
|
+
try {
|
|
96057
|
+
const sharp = await import("sharp");
|
|
96058
|
+
const image = sharp.default(screenshot);
|
|
96059
|
+
const { data, info } = await image.raw().toBuffer({ resolveWithObject: true });
|
|
96060
|
+
const bgColor = this.detectBackgroundColor(data, info.width, info.height, info.channels);
|
|
96061
|
+
const topRegionHeight = Math.floor(info.height * 0.2);
|
|
96062
|
+
let topContentPixels = 0;
|
|
96063
|
+
let bottomContentPixels = 0;
|
|
96064
|
+
for (let y = 0; y < info.height; y++) {
|
|
96065
|
+
for (let x = 0; x < info.width; x++) {
|
|
96066
|
+
const i = (y * info.width + x) * info.channels;
|
|
96067
|
+
const r = data[i];
|
|
96068
|
+
const g = data[i + 1];
|
|
96069
|
+
const b = data[i + 2];
|
|
96070
|
+
if (!this.isSimilarColor(r, g, b, bgColor.r, bgColor.g, bgColor.b, 30)) {
|
|
96071
|
+
if (y < topRegionHeight) {
|
|
96072
|
+
topContentPixels++;
|
|
96073
|
+
} else {
|
|
96074
|
+
bottomContentPixels++;
|
|
96075
|
+
}
|
|
96076
|
+
}
|
|
96077
|
+
}
|
|
96078
|
+
}
|
|
96079
|
+
const topDensity = topContentPixels / (info.width * topRegionHeight);
|
|
96080
|
+
const bottomDensity = bottomContentPixels / (info.width * (info.height - topRegionHeight));
|
|
96081
|
+
return topDensity > 0.01 && topDensity < 0.3;
|
|
96082
|
+
} catch {
|
|
96083
|
+
return true;
|
|
96084
|
+
}
|
|
96085
|
+
}
|
|
96086
|
+
// =============================================================================
|
|
96087
|
+
// HELPER METHODS
|
|
96088
|
+
// =============================================================================
|
|
96089
|
+
getTypeThresholds(type) {
|
|
96090
|
+
const thresholds = {
|
|
96091
|
+
ted_keynote: { minWhitespace: 0.6, maxWordsPerSlide: 15 },
|
|
96092
|
+
sales_pitch: { minWhitespace: 0.5, maxWordsPerSlide: 30 },
|
|
96093
|
+
investor_pitch: { minWhitespace: 0.5, maxWordsPerSlide: 35 },
|
|
96094
|
+
consulting_deck: { minWhitespace: 0.35, maxWordsPerSlide: 70 },
|
|
96095
|
+
investment_banking: { minWhitespace: 0.3, maxWordsPerSlide: 100 },
|
|
96096
|
+
technical_presentation: { minWhitespace: 0.45, maxWordsPerSlide: 45 },
|
|
96097
|
+
all_hands: { minWhitespace: 0.4, maxWordsPerSlide: 50 }
|
|
96098
|
+
};
|
|
96099
|
+
return thresholds[type] || { minWhitespace: 0.4, maxWordsPerSlide: 50 };
|
|
96100
|
+
}
|
|
96101
|
+
detectBackgroundColor(data, width, height, channels) {
|
|
96102
|
+
const colorBuckets = /* @__PURE__ */ new Map();
|
|
96103
|
+
for (let y = 0; y < height; y += 4) {
|
|
96104
|
+
for (let x = 0; x < width; x += 4) {
|
|
96105
|
+
const i = (y * width + x) * channels;
|
|
96106
|
+
const r = data[i];
|
|
96107
|
+
const g = data[i + 1];
|
|
96108
|
+
const b = data[i + 2];
|
|
96109
|
+
const key = `${Math.floor(r / 16)},${Math.floor(g / 16)},${Math.floor(b / 16)}`;
|
|
96110
|
+
const existing = colorBuckets.get(key);
|
|
96111
|
+
if (existing) {
|
|
96112
|
+
existing.count++;
|
|
96113
|
+
} else {
|
|
96114
|
+
colorBuckets.set(key, { r, g, b, count: 1 });
|
|
96115
|
+
}
|
|
96116
|
+
}
|
|
96117
|
+
}
|
|
96118
|
+
let maxCount = 0;
|
|
96119
|
+
let dominantColor = { r: 240, g: 240, b: 240 };
|
|
96120
|
+
for (const color of colorBuckets.values()) {
|
|
96121
|
+
if (color.count > maxCount) {
|
|
96122
|
+
maxCount = color.count;
|
|
96123
|
+
dominantColor = { r: color.r, g: color.g, b: color.b };
|
|
96124
|
+
}
|
|
96125
|
+
}
|
|
96126
|
+
return dominantColor;
|
|
96127
|
+
}
|
|
96128
|
+
detectTextColor(data, width, height, channels, bgColor) {
|
|
96129
|
+
const bgLuminance = this.relativeLuminance(bgColor.r, bgColor.g, bgColor.b);
|
|
96130
|
+
const isDarkBg = bgLuminance < 0.5;
|
|
96131
|
+
const luminanceBuckets = /* @__PURE__ */ new Map();
|
|
96132
|
+
const startY = Math.floor(height * 0.05);
|
|
96133
|
+
const endY = Math.floor(height * 0.95);
|
|
96134
|
+
const startX = Math.floor(width * 0.05);
|
|
96135
|
+
const endX = Math.floor(width * 0.95);
|
|
96136
|
+
for (let y = startY; y < endY; y += 2) {
|
|
96137
|
+
for (let x = startX; x < endX; x += 2) {
|
|
96138
|
+
const i = (y * width + x) * channels;
|
|
96139
|
+
const r = data[i];
|
|
96140
|
+
const g = data[i + 1];
|
|
96141
|
+
const b = data[i + 2];
|
|
96142
|
+
if (this.isSimilarColor(r, g, b, bgColor.r, bgColor.g, bgColor.b, 25)) {
|
|
96143
|
+
continue;
|
|
96144
|
+
}
|
|
96145
|
+
const lum = this.relativeLuminance(r, g, b);
|
|
96146
|
+
const bucket = Math.floor(lum * 10);
|
|
96147
|
+
const existing = luminanceBuckets.get(bucket);
|
|
96148
|
+
if (existing) {
|
|
96149
|
+
const total = existing.count + 1;
|
|
96150
|
+
existing.r = Math.round((existing.r * existing.count + r) / total);
|
|
96151
|
+
existing.g = Math.round((existing.g * existing.count + g) / total);
|
|
96152
|
+
existing.b = Math.round((existing.b * existing.count + b) / total);
|
|
96153
|
+
existing.count = total;
|
|
96154
|
+
} else {
|
|
96155
|
+
luminanceBuckets.set(bucket, { r, g, b, count: 1 });
|
|
96156
|
+
}
|
|
96157
|
+
}
|
|
96158
|
+
}
|
|
96159
|
+
const totalPixels = Array.from(luminanceBuckets.values()).reduce((sum, b) => sum + b.count, 0);
|
|
96160
|
+
const minCount = Math.max(50, totalPixels * 5e-3);
|
|
96161
|
+
let textColor = isDarkBg ? { r: 255, g: 255, b: 255 } : { r: 0, g: 0, b: 0 };
|
|
96162
|
+
if (isDarkBg) {
|
|
96163
|
+
for (let bucket = 10; bucket >= 0; bucket--) {
|
|
96164
|
+
const colors = luminanceBuckets.get(bucket);
|
|
96165
|
+
if (colors && colors.count >= minCount) {
|
|
96166
|
+
textColor = { r: colors.r, g: colors.g, b: colors.b };
|
|
96167
|
+
break;
|
|
96168
|
+
}
|
|
96169
|
+
}
|
|
96170
|
+
} else {
|
|
96171
|
+
for (let bucket = 0; bucket <= 10; bucket++) {
|
|
96172
|
+
const colors = luminanceBuckets.get(bucket);
|
|
96173
|
+
if (colors && colors.count >= minCount) {
|
|
96174
|
+
textColor = { r: colors.r, g: colors.g, b: colors.b };
|
|
96175
|
+
break;
|
|
96176
|
+
}
|
|
96177
|
+
}
|
|
96178
|
+
}
|
|
96179
|
+
return textColor;
|
|
96180
|
+
}
|
|
96181
|
+
isSimilarColor(r1, g1, b1, r2, g2, b2, threshold) {
|
|
96182
|
+
return Math.abs(r1 - r2) < threshold && Math.abs(g1 - g2) < threshold && Math.abs(b1 - b2) < threshold;
|
|
96183
|
+
}
|
|
96184
|
+
relativeLuminance(r, g, b) {
|
|
96185
|
+
const sRGB = [r, g, b].map((c) => {
|
|
96186
|
+
c = c / 255;
|
|
96187
|
+
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
96188
|
+
});
|
|
96189
|
+
return 0.2126 * sRGB[0] + 0.7152 * sRGB[1] + 0.0722 * sRGB[2];
|
|
96190
|
+
}
|
|
96191
|
+
calculateConsistency(slides) {
|
|
96192
|
+
if (slides.length < 2) return 100;
|
|
96193
|
+
const whitespaces = slides.map((s) => s.whitespacePercentage);
|
|
96194
|
+
const densities = slides.map((s) => s.textDensity);
|
|
96195
|
+
const wsVariance = this.variance(whitespaces);
|
|
96196
|
+
const densityVariance = this.variance(densities);
|
|
96197
|
+
const maxVariance = 0.1;
|
|
96198
|
+
const wsScore = Math.max(0, 100 - wsVariance / maxVariance * 50);
|
|
96199
|
+
const densityScore = Math.max(0, 100 - densityVariance / maxVariance * 50);
|
|
96200
|
+
return Math.round((wsScore + densityScore) / 2);
|
|
96201
|
+
}
|
|
96202
|
+
variance(values) {
|
|
96203
|
+
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
|
96204
|
+
return values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length;
|
|
96205
|
+
}
|
|
96206
|
+
};
|
|
96207
|
+
var instance5 = null;
|
|
96208
|
+
function getVisualQAEngine() {
|
|
96209
|
+
if (!instance5) {
|
|
96210
|
+
instance5 = new VisualQAEngine();
|
|
96211
|
+
}
|
|
96212
|
+
return instance5;
|
|
96213
|
+
}
|
|
96214
|
+
async function initVisualQAEngine() {
|
|
96215
|
+
const engine = getVisualQAEngine();
|
|
96216
|
+
await engine.initialize();
|
|
96217
|
+
return engine;
|
|
96218
|
+
}
|
|
96219
|
+
|
|
96220
|
+
// src/core/PresentationEngineV2.ts
|
|
96221
|
+
var import_fs10 = require("fs");
|
|
95611
96222
|
var PALETTE_TO_THEME = {
|
|
95612
96223
|
dark_executive: "dark",
|
|
95613
96224
|
modern_business: "light",
|
|
@@ -95668,6 +96279,80 @@ function getQualityCriteria(specs, type) {
|
|
|
95668
96279
|
requireDataSources: specs.sourcesRequired
|
|
95669
96280
|
};
|
|
95670
96281
|
}
|
|
96282
|
+
function convertV1SlideToV2(slide) {
|
|
96283
|
+
const data = slide.data;
|
|
96284
|
+
const typeMap = {
|
|
96285
|
+
title: "title",
|
|
96286
|
+
title_impact: "title",
|
|
96287
|
+
agenda: "bullets",
|
|
96288
|
+
section_divider: "section",
|
|
96289
|
+
thank_you: "thank_you",
|
|
96290
|
+
single_statement: "statement",
|
|
96291
|
+
big_idea: "statement",
|
|
96292
|
+
big_number: "metrics",
|
|
96293
|
+
quote: "statement",
|
|
96294
|
+
star_moment: "statement",
|
|
96295
|
+
call_to_action: "call_to_action",
|
|
96296
|
+
three_points: "bullets",
|
|
96297
|
+
bullet_points: "bullets",
|
|
96298
|
+
two_column: "bullets",
|
|
96299
|
+
comparison: "bullets",
|
|
96300
|
+
metrics_grid: "metrics",
|
|
96301
|
+
data_insight: "metrics",
|
|
96302
|
+
problem_statement: "statement",
|
|
96303
|
+
solution_overview: "bullets",
|
|
96304
|
+
recommendation: "bullets",
|
|
96305
|
+
next_steps: "bullets"
|
|
96306
|
+
};
|
|
96307
|
+
const v2Type = typeMap[slide.type] || "bullets";
|
|
96308
|
+
const content = {};
|
|
96309
|
+
if (data.bullets && data.bullets.length > 0) {
|
|
96310
|
+
content.bullets = data.bullets;
|
|
96311
|
+
}
|
|
96312
|
+
if (data.metrics && data.metrics.length > 0) {
|
|
96313
|
+
content.metrics = data.metrics.map((m) => {
|
|
96314
|
+
const metric = {
|
|
96315
|
+
value: String(m.value),
|
|
96316
|
+
label: m.label
|
|
96317
|
+
};
|
|
96318
|
+
if (m.trend) {
|
|
96319
|
+
metric.trend = m.trend;
|
|
96320
|
+
}
|
|
96321
|
+
return metric;
|
|
96322
|
+
});
|
|
96323
|
+
}
|
|
96324
|
+
if (v2Type === "statement") {
|
|
96325
|
+
const statement = data.keyMessage || data.quote || data.body || "";
|
|
96326
|
+
if (statement) {
|
|
96327
|
+
content.statement = statement;
|
|
96328
|
+
}
|
|
96329
|
+
if (data.attribution) {
|
|
96330
|
+
content.subtext = data.attribution;
|
|
96331
|
+
}
|
|
96332
|
+
}
|
|
96333
|
+
if (data.body && v2Type !== "statement") {
|
|
96334
|
+
content.body = data.body;
|
|
96335
|
+
}
|
|
96336
|
+
if (data.source) {
|
|
96337
|
+
content.source = data.source;
|
|
96338
|
+
}
|
|
96339
|
+
if (data.subtitle) {
|
|
96340
|
+
content.subtext = data.subtitle;
|
|
96341
|
+
}
|
|
96342
|
+
const v2Slide = {
|
|
96343
|
+
index: slide.index,
|
|
96344
|
+
type: v2Type,
|
|
96345
|
+
title: data.title || "",
|
|
96346
|
+
content
|
|
96347
|
+
};
|
|
96348
|
+
if (slide.notes) {
|
|
96349
|
+
v2Slide.notes = slide.notes;
|
|
96350
|
+
}
|
|
96351
|
+
return v2Slide;
|
|
96352
|
+
}
|
|
96353
|
+
function convertV1SlidesToV2(slides) {
|
|
96354
|
+
return slides.map(convertV1SlideToV2);
|
|
96355
|
+
}
|
|
95671
96356
|
var PresentationEngineV2 = class {
|
|
95672
96357
|
options;
|
|
95673
96358
|
kb = null;
|
|
@@ -95678,7 +96363,10 @@ var PresentationEngineV2 = class {
|
|
|
95678
96363
|
imageApiKey: options.imageApiKey || process.env.GEMINI_API_KEY || process.env.OPENAI_API_KEY || "",
|
|
95679
96364
|
minScore: options.minScore ?? 95,
|
|
95680
96365
|
verbose: options.verbose ?? false,
|
|
95681
|
-
maxRemediationAttempts: options.maxRemediationAttempts ?? 3
|
|
96366
|
+
maxRemediationAttempts: options.maxRemediationAttempts ?? 3,
|
|
96367
|
+
runVisualQA: options.runVisualQA ?? false,
|
|
96368
|
+
useRichPipeline: options.useRichPipeline ?? true
|
|
96369
|
+
// Default to V1's rich pipeline
|
|
95682
96370
|
};
|
|
95683
96371
|
}
|
|
95684
96372
|
log(message) {
|
|
@@ -95710,8 +96398,21 @@ var PresentationEngineV2 = class {
|
|
|
95710
96398
|
this.log(` Words/slide: ${designSpecs.wordsPerSlide.min}-${designSpecs.wordsPerSlide.max}`);
|
|
95711
96399
|
this.log(` Experts: ${designSpecs.experts.slice(0, 2).join(", ")}...`);
|
|
95712
96400
|
this.log("Step 3: Generating slides...");
|
|
95713
|
-
|
|
95714
|
-
|
|
96401
|
+
let slides;
|
|
96402
|
+
if (this.options.useRichPipeline) {
|
|
96403
|
+
this.log(" Using V1 rich pipeline...");
|
|
96404
|
+
const contentAnalyzer = await initContentAnalyzer();
|
|
96405
|
+
const slideGenerator = await initSlideGenerator();
|
|
96406
|
+
const analysis = await contentAnalyzer.analyze(markdown, "markdown");
|
|
96407
|
+
this.log(` Content analysis: ${analysis.sections.length} sections, ${analysis.dataPoints.length} data points`);
|
|
96408
|
+
const v1Slides = await slideGenerator.generate(analysis, presentationType);
|
|
96409
|
+
this.log(` V1 generated ${v1Slides.length} slides`);
|
|
96410
|
+
slides = convertV1SlidesToV2(v1Slides);
|
|
96411
|
+
} else {
|
|
96412
|
+
this.log(" Using V2 minimalist pipeline...");
|
|
96413
|
+
const generator = createSlideGeneratorV2(presentationType);
|
|
96414
|
+
slides = generator.generate(markdown, title);
|
|
96415
|
+
}
|
|
95715
96416
|
this.log(` Generated ${slides.length} slides`);
|
|
95716
96417
|
if (!this.options.imageApiKey) {
|
|
95717
96418
|
const shouldUseImages = this.shouldRecommendImages(slides, presentationType);
|
|
@@ -95763,10 +96464,29 @@ Summary: ${review.summary}`
|
|
|
95763
96464
|
this.log("Step 7: Rendering output...");
|
|
95764
96465
|
const renderer = createRendererV2(presentationType, this.kb);
|
|
95765
96466
|
const html = renderer.render(slides, title || "Presentation");
|
|
96467
|
+
let visualQA;
|
|
96468
|
+
if (this.options.runVisualQA) {
|
|
96469
|
+
this.log("Step 8: Running Visual QA analysis...");
|
|
96470
|
+
try {
|
|
96471
|
+
const visualQAEngine = await initVisualQAEngine();
|
|
96472
|
+
visualQA = await visualQAEngine.analyzeDeck(html, slides, presentationType);
|
|
96473
|
+
await visualQAEngine.cleanup();
|
|
96474
|
+
if (!visualQA.passed) {
|
|
96475
|
+
warnings.push(`Visual QA detected issues: ${visualQA.summary}`);
|
|
96476
|
+
this.log(`Visual QA: ${visualQA.overallScore}/100 - ${visualQA.deckIssues.length} issues found`);
|
|
96477
|
+
} else {
|
|
96478
|
+
this.log(`Visual QA PASSED: ${visualQA.overallScore}/100`);
|
|
96479
|
+
}
|
|
96480
|
+
} catch (error) {
|
|
96481
|
+
const errMsg = error instanceof Error ? error.message : "Unknown error";
|
|
96482
|
+
warnings.push(`Visual QA failed: ${errMsg}`);
|
|
96483
|
+
this.log(`Visual QA error: ${errMsg}`);
|
|
96484
|
+
}
|
|
96485
|
+
}
|
|
95766
96486
|
this.log(`
|
|
95767
96487
|
SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
95768
96488
|
this.log(`Flow: ${review.flow}`);
|
|
95769
|
-
|
|
96489
|
+
const result = {
|
|
95770
96490
|
slides,
|
|
95771
96491
|
html,
|
|
95772
96492
|
presentationType,
|
|
@@ -95774,6 +96494,10 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95774
96494
|
review,
|
|
95775
96495
|
warnings
|
|
95776
96496
|
};
|
|
96497
|
+
if (visualQA) {
|
|
96498
|
+
result.visualQA = visualQA;
|
|
96499
|
+
}
|
|
96500
|
+
return result;
|
|
95777
96501
|
}
|
|
95778
96502
|
/**
|
|
95779
96503
|
* Detect presentation type from content analysis.
|
|
@@ -95868,7 +96592,7 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95868
96592
|
const issues = [];
|
|
95869
96593
|
const suggestions = [];
|
|
95870
96594
|
let score = 100;
|
|
95871
|
-
if (slide.type === "title" || slide.type === "thank_you") {
|
|
96595
|
+
if (slide.type === "title" || slide.type === "thank_you" || slide.type === "section") {
|
|
95872
96596
|
return {
|
|
95873
96597
|
slideIndex: index,
|
|
95874
96598
|
title: slide.title,
|
|
@@ -95926,7 +96650,7 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95926
96650
|
score -= 10;
|
|
95927
96651
|
}
|
|
95928
96652
|
}
|
|
95929
|
-
const hasContent = slide.content.bullets && slide.content.bullets.length > 0 || slide.content.table || slide.content.statement || slide.content.body;
|
|
96653
|
+
const hasContent = slide.content.bullets && slide.content.bullets.length > 0 || slide.content.table || slide.content.metrics && slide.content.metrics.length > 0 || slide.content.statement || slide.content.body;
|
|
95930
96654
|
if (!hasContent) {
|
|
95931
96655
|
issues.push("Slide has no content");
|
|
95932
96656
|
score -= 30;
|
|
@@ -96109,7 +96833,7 @@ async function generatePresentation(markdown, options) {
|
|
|
96109
96833
|
const result = await engine.generate(markdown, options?.title);
|
|
96110
96834
|
if (options?.outputPath) {
|
|
96111
96835
|
const htmlPath = options.outputPath.replace(/\.[^.]+$/, "") + ".html";
|
|
96112
|
-
(0,
|
|
96836
|
+
(0, import_fs10.writeFileSync)(htmlPath, result.html);
|
|
96113
96837
|
console.log(`
|
|
96114
96838
|
Output: ${htmlPath}`);
|
|
96115
96839
|
}
|
|
@@ -96853,12 +97577,12 @@ var SlideQualityReviewer = class {
|
|
|
96853
97577
|
};
|
|
96854
97578
|
}
|
|
96855
97579
|
};
|
|
96856
|
-
var
|
|
97580
|
+
var instance6 = null;
|
|
96857
97581
|
function getSlideQualityReviewer() {
|
|
96858
|
-
if (!
|
|
96859
|
-
|
|
97582
|
+
if (!instance6) {
|
|
97583
|
+
instance6 = new SlideQualityReviewer();
|
|
96860
97584
|
}
|
|
96861
|
-
return
|
|
97585
|
+
return instance6;
|
|
96862
97586
|
}
|
|
96863
97587
|
async function initSlideQualityReviewer() {
|
|
96864
97588
|
const reviewer = getSlideQualityReviewer();
|
|
@@ -97388,12 +98112,12 @@ var DeckQualityReviewer = class {
|
|
|
97388
98112
|
return Math.max(0, 100 - deduction);
|
|
97389
98113
|
}
|
|
97390
98114
|
};
|
|
97391
|
-
var
|
|
98115
|
+
var instance7 = null;
|
|
97392
98116
|
function getDeckQualityReviewer() {
|
|
97393
|
-
if (!
|
|
97394
|
-
|
|
98117
|
+
if (!instance7) {
|
|
98118
|
+
instance7 = new DeckQualityReviewer();
|
|
97395
98119
|
}
|
|
97396
|
-
return
|
|
98120
|
+
return instance7;
|
|
97397
98121
|
}
|
|
97398
98122
|
async function initDeckQualityReviewer() {
|
|
97399
98123
|
const reviewer = getDeckQualityReviewer();
|
|
@@ -97698,12 +98422,12 @@ var Remediator = class {
|
|
|
97698
98422
|
return text.split(/\s+/).filter((w) => w.length > 0).length;
|
|
97699
98423
|
}
|
|
97700
98424
|
};
|
|
97701
|
-
var
|
|
98425
|
+
var instance8 = null;
|
|
97702
98426
|
function getRemediator() {
|
|
97703
|
-
if (!
|
|
97704
|
-
|
|
98427
|
+
if (!instance8) {
|
|
98428
|
+
instance8 = new Remediator();
|
|
97705
98429
|
}
|
|
97706
|
-
return
|
|
98430
|
+
return instance8;
|
|
97707
98431
|
}
|
|
97708
98432
|
async function initRemediator() {
|
|
97709
98433
|
const remediator = getRemediator();
|
|
@@ -98675,12 +99399,12 @@ ${content}
|
|
|
98675
99399
|
return html;
|
|
98676
99400
|
}
|
|
98677
99401
|
};
|
|
98678
|
-
var
|
|
99402
|
+
var instance9 = null;
|
|
98679
99403
|
function getRenderer() {
|
|
98680
|
-
if (!
|
|
98681
|
-
|
|
99404
|
+
if (!instance9) {
|
|
99405
|
+
instance9 = new Renderer();
|
|
98682
99406
|
}
|
|
98683
|
-
return
|
|
99407
|
+
return instance9;
|
|
98684
99408
|
}
|
|
98685
99409
|
async function initRenderer() {
|
|
98686
99410
|
const renderer = getRenderer();
|
|
@@ -98908,7 +99632,7 @@ function getNanoBananaPrompt(style, concept, presentationType) {
|
|
|
98908
99632
|
}
|
|
98909
99633
|
|
|
98910
99634
|
// src/image/ImageMatcher.ts
|
|
98911
|
-
var
|
|
99635
|
+
var import_fs11 = require("fs");
|
|
98912
99636
|
function analyzeImage(imagePath) {
|
|
98913
99637
|
const parts = imagePath.split("/");
|
|
98914
99638
|
const filename = parts[parts.length - 1] || "unknown";
|
|
@@ -99139,7 +99863,7 @@ async function analyzeImageWithVision(imagePath) {
|
|
|
99139
99863
|
return basicInfo;
|
|
99140
99864
|
}
|
|
99141
99865
|
try {
|
|
99142
|
-
const imageBuffer = (0,
|
|
99866
|
+
const imageBuffer = (0, import_fs11.readFileSync)(imagePath);
|
|
99143
99867
|
const base64Image = imageBuffer.toString("base64");
|
|
99144
99868
|
const mimeType = getMimeType(basicInfo.extension);
|
|
99145
99869
|
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
|
|
@@ -99738,6 +100462,7 @@ function countWords(slide) {
|
|
|
99738
100462
|
SlideQualityReviewer,
|
|
99739
100463
|
VERSION,
|
|
99740
100464
|
VisualDesignSystem,
|
|
100465
|
+
VisualQAEngine,
|
|
99741
100466
|
createNanoBananaProvider,
|
|
99742
100467
|
createPresentationEngineV2,
|
|
99743
100468
|
createRendererV2,
|
|
@@ -99753,6 +100478,7 @@ function countWords(slide) {
|
|
|
99753
100478
|
getSlideGenerator,
|
|
99754
100479
|
getSlideQualityReviewer,
|
|
99755
100480
|
getVisualDesignSystem,
|
|
100481
|
+
getVisualQAEngine,
|
|
99756
100482
|
initContentAnalyzer,
|
|
99757
100483
|
initDeckQualityReviewer,
|
|
99758
100484
|
initKB,
|
|
@@ -99761,6 +100487,7 @@ function countWords(slide) {
|
|
|
99761
100487
|
initSlideGenerator,
|
|
99762
100488
|
initSlideQualityReviewer,
|
|
99763
100489
|
initVisualDesignSystem,
|
|
100490
|
+
initVisualQAEngine,
|
|
99764
100491
|
runCodeQualityCheck,
|
|
99765
100492
|
validateCodeQuality
|
|
99766
100493
|
});
|