rampkit-expo-dev 0.0.44 → 0.0.46

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.
@@ -424,25 +424,82 @@ function preloadRampkitOverlay(opts) {
424
424
  // best-effort preloading; ignore errors
425
425
  }
426
426
  }
427
+ /**
428
+ * Decode HTML entities in a string
429
+ */
430
+ function decodeHtmlEntities(str) {
431
+ return str
432
+ .replace(/"/g, '"')
433
+ .replace(/"/g, '"')
434
+ .replace(/"/g, '"')
435
+ .replace(/'/g, "'")
436
+ .replace(/'/g, "'")
437
+ .replace(/'/g, "'")
438
+ .replace(/&lt;/g, '<')
439
+ .replace(/&gt;/g, '>')
440
+ .replace(/&amp;/g, '&');
441
+ }
442
+ /**
443
+ * Strip surrounding quotes from a string value
444
+ * Handles: "value", 'value', \"value\", \'value\', "value", 'value' (unicode curly quotes)
445
+ * Also handles multiple layers and escaped quotes
446
+ */
447
+ function stripQuotes(str) {
448
+ let value = str.trim();
449
+ // Handle backslash-escaped quotes at start/end: \"value\" -> value
450
+ if (value.startsWith('\\"') && value.endsWith('\\"') && value.length >= 4) {
451
+ value = value.slice(2, -2);
452
+ }
453
+ else if (value.startsWith("\\'") && value.endsWith("\\'") && value.length >= 4) {
454
+ value = value.slice(2, -2);
455
+ }
456
+ // Handle regular double quotes: "value" -> value
457
+ else if (value.startsWith('"') && value.endsWith('"') && value.length >= 2) {
458
+ value = value.slice(1, -1);
459
+ }
460
+ // Handle regular single quotes: 'value' -> value
461
+ else if (value.startsWith("'") && value.endsWith("'") && value.length >= 2) {
462
+ value = value.slice(1, -1);
463
+ }
464
+ // Handle unicode left/right double quotes: "value" -> value
465
+ else if (value.startsWith('\u201C') && value.endsWith('\u201D') && value.length >= 2) {
466
+ value = value.slice(1, -1);
467
+ }
468
+ // Handle unicode left/right single quotes: 'value' -> value
469
+ else if (value.startsWith('\u2018') && value.endsWith('\u2019') && value.length >= 2) {
470
+ value = value.slice(1, -1);
471
+ }
472
+ // Check if there's still another layer of quotes (handles double-quoted values)
473
+ const trimmed = value.trim();
474
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"') && trimmed.length >= 2) ||
475
+ (trimmed.startsWith("'") && trimmed.endsWith("'") && trimmed.length >= 2) ||
476
+ (trimmed.startsWith('\\"') && trimmed.endsWith('\\"') && trimmed.length >= 4) ||
477
+ (trimmed.startsWith("\\'") && trimmed.endsWith("\\'") && trimmed.length >= 4)) {
478
+ return stripQuotes(trimmed);
479
+ }
480
+ return value;
481
+ }
427
482
  /**
428
483
  * Evaluate a comparison condition against variables
429
484
  * Supports: ==, !=, >, <, >=, <=, and truthy checks
430
485
  */
431
486
  function evaluateCondition(condition, vars) {
432
- condition = condition.trim();
487
+ condition = decodeHtmlEntities(condition.trim());
433
488
  // Match comparison operators: ==, !=, >=, <=, >, <
434
489
  const comparisonMatch = condition.match(/^([A-Za-z_][A-Za-z0-9_.]*)\s*(==|!=|>=|<=|>|<)\s*(.+)$/);
435
490
  if (comparisonMatch) {
436
491
  const [, varName, operator, rawRight] = comparisonMatch;
437
492
  const leftValue = vars.hasOwnProperty(varName) ? vars[varName] : undefined;
438
- let rightValue = rawRight.trim();
439
- // Parse right side - could be a quoted string or a number or a variable
440
- if ((rightValue.startsWith('"') && rightValue.endsWith('"')) ||
441
- (rightValue.startsWith("'") && rightValue.endsWith("'"))) {
442
- // Quoted string literal
443
- rightValue = rightValue.slice(1, -1);
493
+ let rightValue = decodeHtmlEntities(rawRight.trim());
494
+ // Check if right side looks like a quoted string
495
+ const looksLikeQuotedString = (rightValue.startsWith('"') || rightValue.startsWith("'") ||
496
+ rightValue.startsWith('\\"') || rightValue.startsWith("\\'") ||
497
+ rightValue.startsWith('\u201C') || rightValue.startsWith('\u2018'));
498
+ if (looksLikeQuotedString) {
499
+ // Quoted string literal - strip the quotes
500
+ rightValue = stripQuotes(rightValue);
444
501
  }
445
- else if (!isNaN(Number(rightValue))) {
502
+ else if (!isNaN(Number(rightValue)) && rightValue !== '') {
446
503
  // Numeric literal
447
504
  rightValue = Number(rightValue);
448
505
  }
@@ -494,15 +551,18 @@ function evaluateCondition(condition, vars) {
494
551
  * Returns the resolved value, handling both quoted strings and variable references
495
552
  */
496
553
  function parseTernaryValue(value, vars) {
497
- value = value.trim();
498
- // Check if it's a quoted string
499
- if ((value.startsWith('"') && value.endsWith('"')) ||
500
- (value.startsWith("'") && value.endsWith("'"))) {
501
- return value.slice(1, -1);
554
+ let decoded = decodeHtmlEntities(value.trim());
555
+ // Check if this looks like a quoted string
556
+ const looksLikeQuotedString = (decoded.startsWith('"') || decoded.startsWith("'") ||
557
+ decoded.startsWith('\\"') || decoded.startsWith("\\'") ||
558
+ decoded.startsWith('\u201C') || decoded.startsWith('\u2018'));
559
+ if (looksLikeQuotedString) {
560
+ // Strip quotes and return the inner value
561
+ return stripQuotes(decoded);
502
562
  }
503
563
  // Otherwise treat as a variable reference
504
- if (vars.hasOwnProperty(value)) {
505
- const varValue = vars[value];
564
+ if (vars.hasOwnProperty(decoded)) {
565
+ const varValue = vars[decoded];
506
566
  if (varValue === undefined || varValue === null)
507
567
  return "";
508
568
  if (typeof varValue === "boolean")
@@ -512,20 +572,22 @@ function parseTernaryValue(value, vars) {
512
572
  return String(varValue);
513
573
  }
514
574
  // Return as-is if not found (could be a literal like a number)
515
- return value;
575
+ return decoded;
516
576
  }
517
577
  /**
518
578
  * Parse a ternary expression and find the colon that separates true/false values
519
- * Handles nested quotes properly
579
+ * Handles nested quotes properly (including HTML-encoded quotes)
520
580
  */
521
581
  function splitTernary(expr) {
582
+ // First decode HTML entities to normalize the expression
583
+ const decodedExpr = decodeHtmlEntities(expr);
522
584
  // Find the ? that starts the ternary
523
585
  let questionIdx = -1;
524
586
  let inQuote = false;
525
587
  let quoteChar = "";
526
- for (let i = 0; i < expr.length; i++) {
527
- const char = expr[i];
528
- const prevChar = i > 0 ? expr[i - 1] : "";
588
+ for (let i = 0; i < decodedExpr.length; i++) {
589
+ const char = decodedExpr[i];
590
+ const prevChar = i > 0 ? decodedExpr[i - 1] : "";
529
591
  if ((char === '"' || char === "'") && prevChar !== "\\") {
530
592
  if (!inQuote) {
531
593
  inQuote = true;
@@ -542,8 +604,8 @@ function splitTernary(expr) {
542
604
  }
543
605
  if (questionIdx === -1)
544
606
  return null;
545
- const condition = expr.slice(0, questionIdx).trim();
546
- const rest = expr.slice(questionIdx + 1);
607
+ const condition = decodedExpr.slice(0, questionIdx).trim();
608
+ const rest = decodedExpr.slice(questionIdx + 1);
547
609
  // Find the : that separates true/false values
548
610
  let colonIdx = -1;
549
611
  inQuote = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.44",
3
+ "version": "0.0.46",
4
4
  "description": "The Expo SDK for RampKit. Build, test, and personalize app onboardings with instant updates.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",