claude-presentation-master 4.1.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/bin/cli.js +2 -2
- package/dist/index.d.mts +207 -22
- package/dist/index.d.ts +207 -22
- package/dist/index.js +968 -185
- package/dist/index.mjs +901 -121
- 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
|
});
|
|
@@ -94205,69 +94208,112 @@ function createSlideGeneratorV2(type = "consulting_deck") {
|
|
|
94205
94208
|
|
|
94206
94209
|
// src/output/RendererV2.ts
|
|
94207
94210
|
var import_fs8 = require("fs");
|
|
94208
|
-
var
|
|
94209
|
-
|
|
94210
|
-
|
|
94211
|
-
|
|
94212
|
-
|
|
94213
|
-
|
|
94214
|
-
|
|
94211
|
+
var FALLBACK_PALETTES = {
|
|
94212
|
+
consulting_classic: {
|
|
94213
|
+
background: "#FAFAF9",
|
|
94214
|
+
primary: "#0F172A",
|
|
94215
|
+
secondary: "#475569",
|
|
94216
|
+
accent: "#0369A1",
|
|
94217
|
+
text: "#18181B",
|
|
94218
|
+
name: "Consulting Classic"
|
|
94215
94219
|
},
|
|
94216
|
-
|
|
94217
|
-
|
|
94218
|
-
|
|
94219
|
-
|
|
94220
|
-
|
|
94220
|
+
dark_executive: {
|
|
94221
|
+
background: "#18181B",
|
|
94222
|
+
primary: "#FAFAFA",
|
|
94223
|
+
secondary: "#A1A1AA",
|
|
94224
|
+
accent: "#F59E0B",
|
|
94225
|
+
text: "#F4F4F5",
|
|
94226
|
+
name: "Dark Executive"
|
|
94221
94227
|
},
|
|
94222
|
-
|
|
94223
|
-
|
|
94224
|
-
|
|
94225
|
-
|
|
94226
|
-
|
|
94228
|
+
modern_business: {
|
|
94229
|
+
background: "#F8FAFC",
|
|
94230
|
+
primary: "#1E293B",
|
|
94231
|
+
secondary: "#64748B",
|
|
94232
|
+
accent: "#0891B2",
|
|
94233
|
+
text: "#0F172A",
|
|
94234
|
+
name: "Modern Business"
|
|
94227
94235
|
},
|
|
94228
|
-
|
|
94229
|
-
|
|
94230
|
-
|
|
94231
|
-
|
|
94232
|
-
|
|
94233
|
-
|
|
94236
|
+
executive_professional: {
|
|
94237
|
+
background: "#F5F5F4",
|
|
94238
|
+
primary: "#1E3A5F",
|
|
94239
|
+
secondary: "#64748B",
|
|
94240
|
+
accent: "#D97706",
|
|
94241
|
+
text: "#1F2937",
|
|
94242
|
+
name: "Executive Professional"
|
|
94234
94243
|
},
|
|
94235
|
-
|
|
94236
|
-
|
|
94237
|
-
|
|
94238
|
-
|
|
94239
|
-
|
|
94244
|
+
strategy_growth: {
|
|
94245
|
+
background: "#FAF9F7",
|
|
94246
|
+
primary: "#292524",
|
|
94247
|
+
secondary: "#78716C",
|
|
94248
|
+
accent: "#059669",
|
|
94249
|
+
text: "#1C1917",
|
|
94250
|
+
name: "Strategy Growth"
|
|
94240
94251
|
}
|
|
94241
94252
|
};
|
|
94242
|
-
|
|
94243
|
-
|
|
94244
|
-
|
|
94245
|
-
// Sales → Dark dramatic style (persuasion, impact)
|
|
94246
|
-
sales_pitch: "dark",
|
|
94247
|
-
// Consulting/Analysis decks → McKinsey white style (data-heavy, professional)
|
|
94248
|
-
consulting_deck: "mckinsey",
|
|
94249
|
-
// Investment Banking → McKinsey style (financial, dense data)
|
|
94250
|
-
investment_banking: "mckinsey",
|
|
94251
|
-
// Investor Pitch → Startup dark style (modern, VC audiences)
|
|
94252
|
-
investor_pitch: "startup",
|
|
94253
|
-
// Technical → Dark style (engineering audiences like dark mode)
|
|
94254
|
-
technical_presentation: "dark",
|
|
94255
|
-
// All Hands → Minimal clean style (readable, accessible)
|
|
94256
|
-
all_hands: "minimal"
|
|
94257
|
-
};
|
|
94253
|
+
function getPaletteStyle(paletteName) {
|
|
94254
|
+
return paletteName === "dark_executive" ? "dark" : "light";
|
|
94255
|
+
}
|
|
94258
94256
|
var RendererV2 = class {
|
|
94259
94257
|
theme;
|
|
94260
94258
|
presentationType;
|
|
94259
|
+
kb;
|
|
94261
94260
|
/**
|
|
94262
|
-
* Create renderer with theme
|
|
94263
|
-
* @param presentationType - The type of deck being created (determines
|
|
94264
|
-
* @param
|
|
94261
|
+
* Create renderer with theme loaded from Knowledge Base.
|
|
94262
|
+
* @param presentationType - The type of deck being created (determines palette)
|
|
94263
|
+
* @param kb - Knowledge Base gateway (optional, will use global if not provided)
|
|
94265
94264
|
*/
|
|
94266
|
-
constructor(presentationType = "consulting_deck",
|
|
94265
|
+
constructor(presentationType = "consulting_deck", kb) {
|
|
94267
94266
|
this.presentationType = presentationType;
|
|
94268
|
-
|
|
94269
|
-
this.theme =
|
|
94270
|
-
console.log(`[RendererV2] Using "${this.theme.
|
|
94267
|
+
this.kb = kb || getKB();
|
|
94268
|
+
this.theme = this.loadThemeFromKB(presentationType);
|
|
94269
|
+
console.log(`[RendererV2] Using "${this.theme.paletteName}" palette (${this.theme.style} style) for "${presentationType}" deck`);
|
|
94270
|
+
}
|
|
94271
|
+
/**
|
|
94272
|
+
* Load theme configuration from Knowledge Base.
|
|
94273
|
+
* Falls back to hardcoded values only if KB fails.
|
|
94274
|
+
*/
|
|
94275
|
+
loadThemeFromKB(type) {
|
|
94276
|
+
try {
|
|
94277
|
+
const paletteName = this.kb.queryOptional(`presentation_types.${type}.color_palette`).value || this.getDefaultPaletteName(type);
|
|
94278
|
+
const kbPalette = this.kb.queryOptional(`color_palettes.${paletteName}`).value;
|
|
94279
|
+
if (kbPalette) {
|
|
94280
|
+
console.log(`[RendererV2] Loaded "${paletteName}" palette from KB: bg=${kbPalette.background}, accent=${kbPalette.accent}`);
|
|
94281
|
+
return {
|
|
94282
|
+
style: getPaletteStyle(paletteName),
|
|
94283
|
+
palette: kbPalette,
|
|
94284
|
+
paletteName
|
|
94285
|
+
};
|
|
94286
|
+
}
|
|
94287
|
+
const fallback = FALLBACK_PALETTES[paletteName] ?? FALLBACK_PALETTES.consulting_classic;
|
|
94288
|
+
console.log(`[RendererV2] Using fallback "${paletteName}" palette`);
|
|
94289
|
+
return {
|
|
94290
|
+
style: getPaletteStyle(paletteName),
|
|
94291
|
+
palette: fallback,
|
|
94292
|
+
paletteName
|
|
94293
|
+
};
|
|
94294
|
+
} catch {
|
|
94295
|
+
const defaultPalette = FALLBACK_PALETTES.consulting_classic;
|
|
94296
|
+
return {
|
|
94297
|
+
style: "light",
|
|
94298
|
+
palette: defaultPalette,
|
|
94299
|
+
paletteName: "consulting_classic"
|
|
94300
|
+
};
|
|
94301
|
+
}
|
|
94302
|
+
}
|
|
94303
|
+
/**
|
|
94304
|
+
* Default palette mapping per presentation type (used if KB doesn't specify).
|
|
94305
|
+
*/
|
|
94306
|
+
getDefaultPaletteName(type) {
|
|
94307
|
+
const defaults = {
|
|
94308
|
+
ted_keynote: "dark_executive",
|
|
94309
|
+
sales_pitch: "modern_business",
|
|
94310
|
+
consulting_deck: "consulting_classic",
|
|
94311
|
+
investment_banking: "executive_professional",
|
|
94312
|
+
investor_pitch: "modern_business",
|
|
94313
|
+
technical_presentation: "dark_executive",
|
|
94314
|
+
all_hands: "strategy_growth"
|
|
94315
|
+
};
|
|
94316
|
+
return defaults[type] || "consulting_classic";
|
|
94271
94317
|
}
|
|
94272
94318
|
/**
|
|
94273
94319
|
* Render slides to complete HTML document.
|
|
@@ -94357,15 +94403,15 @@ ${slidesHtml}
|
|
|
94357
94403
|
const content = this.renderSlideContent(slide);
|
|
94358
94404
|
return `<div class="slide slide-${slide.type}">${content}</div>`;
|
|
94359
94405
|
}).join("\n");
|
|
94360
|
-
if (this.theme.style === "
|
|
94361
|
-
return this.
|
|
94406
|
+
if (this.theme.style === "light") {
|
|
94407
|
+
return this.getLightPrintHTML(title, slidesHtml);
|
|
94362
94408
|
}
|
|
94363
94409
|
return this.getDarkPrintHTML(title, slidesHtml);
|
|
94364
94410
|
}
|
|
94365
94411
|
/**
|
|
94366
|
-
*
|
|
94412
|
+
* Light theme print HTML (professional, white background).
|
|
94367
94413
|
*/
|
|
94368
|
-
|
|
94414
|
+
getLightPrintHTML(title, slidesHtml) {
|
|
94369
94415
|
return `<!DOCTYPE html>
|
|
94370
94416
|
<html lang="en">
|
|
94371
94417
|
<head>
|
|
@@ -95021,34 +95067,60 @@ ${content}
|
|
|
95021
95067
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
95022
95068
|
}
|
|
95023
95069
|
/**
|
|
95024
|
-
*
|
|
95070
|
+
* Generate CSS with colors from Knowledge Base.
|
|
95025
95071
|
*/
|
|
95026
95072
|
getCSS() {
|
|
95027
|
-
if (this.theme.style === "
|
|
95028
|
-
return this.
|
|
95073
|
+
if (this.theme.style === "light") {
|
|
95074
|
+
return this.getLightThemeCSS();
|
|
95029
95075
|
}
|
|
95030
|
-
return this.
|
|
95076
|
+
return this.getDarkThemeCSS();
|
|
95031
95077
|
}
|
|
95032
95078
|
/**
|
|
95033
|
-
*
|
|
95079
|
+
* Generate CSS variables from KB palette.
|
|
95034
95080
|
*/
|
|
95035
|
-
|
|
95081
|
+
getCSSVariables() {
|
|
95082
|
+
const p = this.theme.palette;
|
|
95083
|
+
const isLight = this.theme.style === "light";
|
|
95084
|
+
const bgSecondary = isLight ? this.lightenColor(p.background, -5) : this.lightenColor(p.background, 10);
|
|
95085
|
+
const bgAccent = isLight ? this.lightenColor(p.background, -10) : this.lightenColor(p.background, 15);
|
|
95086
|
+
const textMuted = isLight ? this.lightenColor(p.text, 40) : this.lightenColor(p.text, -30);
|
|
95036
95087
|
return `
|
|
95037
|
-
/*
|
|
95088
|
+
/* ${this.theme.paletteName} Theme - Loaded from Knowledge Base */
|
|
95038
95089
|
:root {
|
|
95039
|
-
--
|
|
95040
|
-
--bg-
|
|
95041
|
-
--bg-
|
|
95042
|
-
--
|
|
95043
|
-
--text-
|
|
95044
|
-
--text-
|
|
95045
|
-
--
|
|
95046
|
-
--
|
|
95090
|
+
--kb-palette: "${this.theme.paletteName}";
|
|
95091
|
+
--bg-primary: ${p.background};
|
|
95092
|
+
--bg-secondary: ${bgSecondary};
|
|
95093
|
+
--bg-accent: ${bgAccent};
|
|
95094
|
+
--text-primary: ${p.text};
|
|
95095
|
+
--text-secondary: ${p.secondary};
|
|
95096
|
+
--text-muted: ${textMuted};
|
|
95097
|
+
--color-primary: ${p.primary};
|
|
95098
|
+
--color-accent: ${p.accent};
|
|
95099
|
+
--accent-blue: ${p.accent};
|
|
95047
95100
|
--accent-green: #28a745;
|
|
95048
95101
|
--accent-red: #dc3545;
|
|
95049
|
-
--border-color: #dee2e6;
|
|
95050
|
-
--header-bar:
|
|
95051
|
-
|
|
95102
|
+
--border-color: ${isLight ? "#dee2e6" : "rgba(255,255,255,0.1)"};
|
|
95103
|
+
--header-bar: ${p.primary};
|
|
95104
|
+
--mckinsey-blue: ${p.accent};
|
|
95105
|
+
}`;
|
|
95106
|
+
}
|
|
95107
|
+
/**
|
|
95108
|
+
* Lighten or darken a hex color.
|
|
95109
|
+
*/
|
|
95110
|
+
lightenColor(hex, percent) {
|
|
95111
|
+
const num = parseInt(hex.replace("#", ""), 16);
|
|
95112
|
+
const amt = Math.round(2.55 * percent);
|
|
95113
|
+
const R = Math.max(0, Math.min(255, (num >> 16) + amt));
|
|
95114
|
+
const G = Math.max(0, Math.min(255, (num >> 8 & 255) + amt));
|
|
95115
|
+
const B = Math.max(0, Math.min(255, (num & 255) + amt));
|
|
95116
|
+
return `#${(16777216 + R * 65536 + G * 256 + B).toString(16).slice(1)}`;
|
|
95117
|
+
}
|
|
95118
|
+
/**
|
|
95119
|
+
* Light theme CSS (consulting style) with KB palette colors.
|
|
95120
|
+
*/
|
|
95121
|
+
getLightThemeCSS() {
|
|
95122
|
+
return `
|
|
95123
|
+
${this.getCSSVariables()}
|
|
95052
95124
|
|
|
95053
95125
|
.reveal {
|
|
95054
95126
|
font-family: 'Georgia', 'Times New Roman', serif;
|
|
@@ -95319,23 +95391,11 @@ ${content}
|
|
|
95319
95391
|
`;
|
|
95320
95392
|
}
|
|
95321
95393
|
/**
|
|
95322
|
-
* Dark theme CSS
|
|
95394
|
+
* Dark theme CSS with KB palette colors.
|
|
95323
95395
|
*/
|
|
95324
|
-
|
|
95396
|
+
getDarkThemeCSS() {
|
|
95325
95397
|
return `
|
|
95326
|
-
|
|
95327
|
-
:root {
|
|
95328
|
-
--bg-primary: #1a1a2e;
|
|
95329
|
-
--bg-secondary: #16213e;
|
|
95330
|
-
--bg-accent: #0f3460;
|
|
95331
|
-
--text-primary: #ffffff;
|
|
95332
|
-
--text-secondary: rgba(255, 255, 255, 0.85);
|
|
95333
|
-
--text-muted: rgba(255, 255, 255, 0.6);
|
|
95334
|
-
--accent-blue: #4a9eff;
|
|
95335
|
-
--accent-green: #00d4aa;
|
|
95336
|
-
--accent-orange: #ff9f43;
|
|
95337
|
-
--border-color: rgba(255, 255, 255, 0.1);
|
|
95338
|
-
}
|
|
95398
|
+
${this.getCSSVariables()}
|
|
95339
95399
|
|
|
95340
95400
|
.reveal {
|
|
95341
95401
|
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
@@ -95546,18 +95606,625 @@ ${content}
|
|
|
95546
95606
|
`;
|
|
95547
95607
|
}
|
|
95548
95608
|
};
|
|
95549
|
-
function createRendererV2(presentationType = "consulting_deck",
|
|
95550
|
-
return new RendererV2(presentationType,
|
|
95609
|
+
function createRendererV2(presentationType = "consulting_deck", kb) {
|
|
95610
|
+
return new RendererV2(presentationType, kb);
|
|
95551
95611
|
}
|
|
95552
95612
|
|
|
95553
|
-
// src/
|
|
95613
|
+
// src/qa/VisualQAEngine.ts
|
|
95554
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");
|
|
95555
96222
|
var PALETTE_TO_THEME = {
|
|
95556
96223
|
dark_executive: "dark",
|
|
95557
|
-
modern_business: "
|
|
95558
|
-
consulting_classic: "
|
|
95559
|
-
executive_professional: "
|
|
95560
|
-
strategy_growth: "
|
|
96224
|
+
modern_business: "light",
|
|
96225
|
+
consulting_classic: "light",
|
|
96226
|
+
executive_professional: "light",
|
|
96227
|
+
strategy_growth: "light"
|
|
95561
96228
|
};
|
|
95562
96229
|
async function loadDesignSpecsFromKB(kb, type) {
|
|
95563
96230
|
const typeConfig = kb.queryRequired(`presentation_types.${type}`);
|
|
@@ -95568,7 +96235,7 @@ async function loadDesignSpecsFromKB(kb, type) {
|
|
|
95568
96235
|
const typography = typeConfig.value.typography;
|
|
95569
96236
|
const primaryExperts = typeConfig.value.primary_experts;
|
|
95570
96237
|
const colorPalette = typeConfig.value.color_palette || "consulting_classic";
|
|
95571
|
-
const theme = PALETTE_TO_THEME[colorPalette] || "
|
|
96238
|
+
const theme = PALETTE_TO_THEME[colorPalette] || "light";
|
|
95572
96239
|
const scoringWeights = typeConfig.value.scoring_weights;
|
|
95573
96240
|
let structure = "General presentation structure";
|
|
95574
96241
|
if (primaryExperts.some((e) => e.includes("Minto") || e.includes("McKinsey"))) {
|
|
@@ -95612,6 +96279,80 @@ function getQualityCriteria(specs, type) {
|
|
|
95612
96279
|
requireDataSources: specs.sourcesRequired
|
|
95613
96280
|
};
|
|
95614
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
|
+
}
|
|
95615
96356
|
var PresentationEngineV2 = class {
|
|
95616
96357
|
options;
|
|
95617
96358
|
kb = null;
|
|
@@ -95622,7 +96363,10 @@ var PresentationEngineV2 = class {
|
|
|
95622
96363
|
imageApiKey: options.imageApiKey || process.env.GEMINI_API_KEY || process.env.OPENAI_API_KEY || "",
|
|
95623
96364
|
minScore: options.minScore ?? 95,
|
|
95624
96365
|
verbose: options.verbose ?? false,
|
|
95625
|
-
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
|
|
95626
96370
|
};
|
|
95627
96371
|
}
|
|
95628
96372
|
log(message) {
|
|
@@ -95654,8 +96398,21 @@ var PresentationEngineV2 = class {
|
|
|
95654
96398
|
this.log(` Words/slide: ${designSpecs.wordsPerSlide.min}-${designSpecs.wordsPerSlide.max}`);
|
|
95655
96399
|
this.log(` Experts: ${designSpecs.experts.slice(0, 2).join(", ")}...`);
|
|
95656
96400
|
this.log("Step 3: Generating slides...");
|
|
95657
|
-
|
|
95658
|
-
|
|
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
|
+
}
|
|
95659
96416
|
this.log(` Generated ${slides.length} slides`);
|
|
95660
96417
|
if (!this.options.imageApiKey) {
|
|
95661
96418
|
const shouldUseImages = this.shouldRecommendImages(slides, presentationType);
|
|
@@ -95705,12 +96462,31 @@ Summary: ${review.summary}`
|
|
|
95705
96462
|
);
|
|
95706
96463
|
}
|
|
95707
96464
|
this.log("Step 7: Rendering output...");
|
|
95708
|
-
const renderer = createRendererV2(presentationType, this.
|
|
96465
|
+
const renderer = createRendererV2(presentationType, this.kb);
|
|
95709
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
|
+
}
|
|
95710
96486
|
this.log(`
|
|
95711
96487
|
SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
95712
96488
|
this.log(`Flow: ${review.flow}`);
|
|
95713
|
-
|
|
96489
|
+
const result = {
|
|
95714
96490
|
slides,
|
|
95715
96491
|
html,
|
|
95716
96492
|
presentationType,
|
|
@@ -95718,6 +96494,10 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95718
96494
|
review,
|
|
95719
96495
|
warnings
|
|
95720
96496
|
};
|
|
96497
|
+
if (visualQA) {
|
|
96498
|
+
result.visualQA = visualQA;
|
|
96499
|
+
}
|
|
96500
|
+
return result;
|
|
95721
96501
|
}
|
|
95722
96502
|
/**
|
|
95723
96503
|
* Detect presentation type from content analysis.
|
|
@@ -95812,7 +96592,7 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95812
96592
|
const issues = [];
|
|
95813
96593
|
const suggestions = [];
|
|
95814
96594
|
let score = 100;
|
|
95815
|
-
if (slide.type === "title" || slide.type === "thank_you") {
|
|
96595
|
+
if (slide.type === "title" || slide.type === "thank_you" || slide.type === "section") {
|
|
95816
96596
|
return {
|
|
95817
96597
|
slideIndex: index,
|
|
95818
96598
|
title: slide.title,
|
|
@@ -95870,7 +96650,7 @@ SUCCESS: Generated ${slides.length} slides scoring ${review.overallScore}/100`);
|
|
|
95870
96650
|
score -= 10;
|
|
95871
96651
|
}
|
|
95872
96652
|
}
|
|
95873
|
-
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;
|
|
95874
96654
|
if (!hasContent) {
|
|
95875
96655
|
issues.push("Slide has no content");
|
|
95876
96656
|
score -= 30;
|
|
@@ -96053,7 +96833,7 @@ async function generatePresentation(markdown, options) {
|
|
|
96053
96833
|
const result = await engine.generate(markdown, options?.title);
|
|
96054
96834
|
if (options?.outputPath) {
|
|
96055
96835
|
const htmlPath = options.outputPath.replace(/\.[^.]+$/, "") + ".html";
|
|
96056
|
-
(0,
|
|
96836
|
+
(0, import_fs10.writeFileSync)(htmlPath, result.html);
|
|
96057
96837
|
console.log(`
|
|
96058
96838
|
Output: ${htmlPath}`);
|
|
96059
96839
|
}
|
|
@@ -96797,12 +97577,12 @@ var SlideQualityReviewer = class {
|
|
|
96797
97577
|
};
|
|
96798
97578
|
}
|
|
96799
97579
|
};
|
|
96800
|
-
var
|
|
97580
|
+
var instance6 = null;
|
|
96801
97581
|
function getSlideQualityReviewer() {
|
|
96802
|
-
if (!
|
|
96803
|
-
|
|
97582
|
+
if (!instance6) {
|
|
97583
|
+
instance6 = new SlideQualityReviewer();
|
|
96804
97584
|
}
|
|
96805
|
-
return
|
|
97585
|
+
return instance6;
|
|
96806
97586
|
}
|
|
96807
97587
|
async function initSlideQualityReviewer() {
|
|
96808
97588
|
const reviewer = getSlideQualityReviewer();
|
|
@@ -97332,12 +98112,12 @@ var DeckQualityReviewer = class {
|
|
|
97332
98112
|
return Math.max(0, 100 - deduction);
|
|
97333
98113
|
}
|
|
97334
98114
|
};
|
|
97335
|
-
var
|
|
98115
|
+
var instance7 = null;
|
|
97336
98116
|
function getDeckQualityReviewer() {
|
|
97337
|
-
if (!
|
|
97338
|
-
|
|
98117
|
+
if (!instance7) {
|
|
98118
|
+
instance7 = new DeckQualityReviewer();
|
|
97339
98119
|
}
|
|
97340
|
-
return
|
|
98120
|
+
return instance7;
|
|
97341
98121
|
}
|
|
97342
98122
|
async function initDeckQualityReviewer() {
|
|
97343
98123
|
const reviewer = getDeckQualityReviewer();
|
|
@@ -97642,12 +98422,12 @@ var Remediator = class {
|
|
|
97642
98422
|
return text.split(/\s+/).filter((w) => w.length > 0).length;
|
|
97643
98423
|
}
|
|
97644
98424
|
};
|
|
97645
|
-
var
|
|
98425
|
+
var instance8 = null;
|
|
97646
98426
|
function getRemediator() {
|
|
97647
|
-
if (!
|
|
97648
|
-
|
|
98427
|
+
if (!instance8) {
|
|
98428
|
+
instance8 = new Remediator();
|
|
97649
98429
|
}
|
|
97650
|
-
return
|
|
98430
|
+
return instance8;
|
|
97651
98431
|
}
|
|
97652
98432
|
async function initRemediator() {
|
|
97653
98433
|
const remediator = getRemediator();
|
|
@@ -98619,12 +99399,12 @@ ${content}
|
|
|
98619
99399
|
return html;
|
|
98620
99400
|
}
|
|
98621
99401
|
};
|
|
98622
|
-
var
|
|
99402
|
+
var instance9 = null;
|
|
98623
99403
|
function getRenderer() {
|
|
98624
|
-
if (!
|
|
98625
|
-
|
|
99404
|
+
if (!instance9) {
|
|
99405
|
+
instance9 = new Renderer();
|
|
98626
99406
|
}
|
|
98627
|
-
return
|
|
99407
|
+
return instance9;
|
|
98628
99408
|
}
|
|
98629
99409
|
async function initRenderer() {
|
|
98630
99410
|
const renderer = getRenderer();
|
|
@@ -98852,7 +99632,7 @@ function getNanoBananaPrompt(style, concept, presentationType) {
|
|
|
98852
99632
|
}
|
|
98853
99633
|
|
|
98854
99634
|
// src/image/ImageMatcher.ts
|
|
98855
|
-
var
|
|
99635
|
+
var import_fs11 = require("fs");
|
|
98856
99636
|
function analyzeImage(imagePath) {
|
|
98857
99637
|
const parts = imagePath.split("/");
|
|
98858
99638
|
const filename = parts[parts.length - 1] || "unknown";
|
|
@@ -99083,7 +99863,7 @@ async function analyzeImageWithVision(imagePath) {
|
|
|
99083
99863
|
return basicInfo;
|
|
99084
99864
|
}
|
|
99085
99865
|
try {
|
|
99086
|
-
const imageBuffer = (0,
|
|
99866
|
+
const imageBuffer = (0, import_fs11.readFileSync)(imagePath);
|
|
99087
99867
|
const base64Image = imageBuffer.toString("base64");
|
|
99088
99868
|
const mimeType = getMimeType(basicInfo.extension);
|
|
99089
99869
|
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
|
|
@@ -99494,7 +100274,7 @@ if (typeof process !== "undefined" && process.argv[1]?.includes("CodeQualityVali
|
|
|
99494
100274
|
}
|
|
99495
100275
|
|
|
99496
100276
|
// src/index.ts
|
|
99497
|
-
var VERSION = "4.
|
|
100277
|
+
var VERSION = "4.2.0";
|
|
99498
100278
|
async function generate(options) {
|
|
99499
100279
|
const {
|
|
99500
100280
|
content,
|
|
@@ -99682,6 +100462,7 @@ function countWords(slide) {
|
|
|
99682
100462
|
SlideQualityReviewer,
|
|
99683
100463
|
VERSION,
|
|
99684
100464
|
VisualDesignSystem,
|
|
100465
|
+
VisualQAEngine,
|
|
99685
100466
|
createNanoBananaProvider,
|
|
99686
100467
|
createPresentationEngineV2,
|
|
99687
100468
|
createRendererV2,
|
|
@@ -99697,6 +100478,7 @@ function countWords(slide) {
|
|
|
99697
100478
|
getSlideGenerator,
|
|
99698
100479
|
getSlideQualityReviewer,
|
|
99699
100480
|
getVisualDesignSystem,
|
|
100481
|
+
getVisualQAEngine,
|
|
99700
100482
|
initContentAnalyzer,
|
|
99701
100483
|
initDeckQualityReviewer,
|
|
99702
100484
|
initKB,
|
|
@@ -99705,6 +100487,7 @@ function countWords(slide) {
|
|
|
99705
100487
|
initSlideGenerator,
|
|
99706
100488
|
initSlideQualityReviewer,
|
|
99707
100489
|
initVisualDesignSystem,
|
|
100490
|
+
initVisualQAEngine,
|
|
99708
100491
|
runCodeQualityCheck,
|
|
99709
100492
|
validateCodeQuality
|
|
99710
100493
|
});
|