Skip to content

Commit 00f4120

Browse files
devvaannshabose
authored andcommitted
fix: large lorem emmet abbreviations is freezing phoenix
1 parent 352d2df commit 00f4120

File tree

1 file changed

+60
-0
lines changed
  • src/extensions/default/HTMLCodeHints

1 file changed

+60
-0
lines changed

src/extensions/default/HTMLCodeHints/main.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,60 @@ define(function (require, exports, module) {
449449
}
450450
}
451451

452+
/**
453+
* to validate whether a lorem abbreviation is safe to expand without crashing the app
454+
* so there are many problematic patters like lorem1000000, li*10>lorem50000 etc
455+
* we put a max constraint of 100000, above which we don't show the code hint at all
456+
*
457+
* @param {String} word - the abbreviation to validate
458+
* @returns {Boolean} - true if safe to expand otherwise false
459+
*/
460+
function isLoremSafeToExpand(word) {
461+
const MAX_LOREM_WORDS = 100000;
462+
463+
// extract all lorem word counts (handles lorem123, loremru123, lorem10-200, etc.)
464+
const loremPattern = /lorem[a-z]*(\d+)(?:-(\d+))?/gi;
465+
const loremMatches = [...word.matchAll(loremPattern)];
466+
// if no lorem is there, it means its safe
467+
if (loremMatches.length === 0) {
468+
return true;
469+
}
470+
471+
// find the maximum lorem word count
472+
let maxLoremCount = 0;
473+
for (const match of loremMatches) {
474+
const count1 = parseInt(match[1]) || 0;
475+
// for ranges like lorem10-200, take the second (max) number
476+
const count2 = match[2] ? parseInt(match[2]) : count1;
477+
const maxCount = Math.max(count1, count2);
478+
maxLoremCount = Math.max(maxLoremCount, maxCount);
479+
}
480+
481+
// if any single lorem exceeds the limit, for ex: `lorem1000000` or `lorem5000000`
482+
if (maxLoremCount > MAX_LOREM_WORDS) {
483+
return false;
484+
}
485+
486+
// handle the multiplication cases, for ex: `li*10>lorem500000`
487+
const multiplierPattern = /\*(\d+)/g;
488+
const multipliers = [...word.matchAll(multiplierPattern)].map(m => parseInt(m[1]));
489+
490+
// if no multipliers, just check the max lorem count
491+
if (multipliers.length === 0) {
492+
return true;
493+
}
494+
495+
// calc total multiplication factor (capped at 400 due to maxRepeat)
496+
const totalMultiplier = Math.min(
497+
multipliers.reduce((product, num) => product * num, 1),
498+
400
499+
);
500+
501+
// worst case: max lorem count × total multiplier
502+
const estimatedTotal = maxLoremCount * totalMultiplier;
503+
504+
return estimatedTotal <= MAX_LOREM_WORDS;
505+
}
452506

453507
/**
454508
* This function checks whether the abbreviation can be expanded or not.
@@ -496,6 +550,12 @@ define(function (require, exports, module) {
496550
positiveSymbols.some(symbol => word.includes(symbol)) ||
497551
word.toLowerCase().includes('lorem')
498552
) {
553+
// we need to check if this is safe to expand because cases like
554+
// `lorem100000000` will crash phoenix
555+
// read functions jsdoc for more details
556+
if (word.toLowerCase().includes('lorem') && !isLoremSafeToExpand(word)) {
557+
return null;
558+
}
499559

500560
try {
501561
return expandAbbr(word, { syntax: "html", type: "markup", maxRepeat: 400 }); // expanded

0 commit comments

Comments
 (0)