mirror of
https://github.com/MrUnknownDE/VRCX.git
synced 2026-04-18 22:33:50 +02:00
Highlight the differences of the updated bio text in Feed (#972)
Co-authored-by: EbonCorvin <{ID}+{username}@users.noreply.github.com>
This commit is contained in:
132
html/src/app.js
132
html/src/app.js
@@ -5697,6 +5697,138 @@ speechSynthesis.getVoices();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Function that prepare the Longest Common Subsequence (LCS) scores matrix
|
||||
* @param {*} s1 String 1
|
||||
* @param {*} s2 String 2
|
||||
* @returns
|
||||
*/
|
||||
$app.methods.lcsMatrix = function (s1, s2) {
|
||||
const m = s1.length;
|
||||
const n = s2.length;
|
||||
const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
|
||||
|
||||
// Fill the matrix for LCS
|
||||
for (let i = 1; i <= m; i++) {
|
||||
for (let j = 1; j <= n; j++) {
|
||||
if (s1[i - 1] === s2[j - 1]) {
|
||||
dp[i][j] = dp[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dp;
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that find the differences between both strings, and return the differences and their position in the strings.
|
||||
* @param {*} s1 String 1
|
||||
* @param {*} s2 String 2
|
||||
* @returns
|
||||
*/
|
||||
$app.methods.findDifferences = function (s1, s2) {
|
||||
const dp = $app.lcsMatrix(s1, s2);
|
||||
const differencesS1 = [];
|
||||
const differencesS2 = [];
|
||||
let i = s1.length;
|
||||
let j = s2.length;
|
||||
|
||||
// Backtrack to find differences
|
||||
while (i > 0 && j > 0) {
|
||||
if (s1[i - 1] === s2[j - 1]) {
|
||||
i--;
|
||||
j--;
|
||||
} else if (dp[i - 1][j] >= dp[i][j - 1]) {
|
||||
differencesS1.push({ index: i - 1, char: s1[i - 1] }); // Deletion in s1
|
||||
i--;
|
||||
} else {
|
||||
differencesS2.push({ index: j - 1, char: s2[j - 1] }); // Insertion in s2
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
// Remaining characters in s1 (deletions)
|
||||
while (i > 0) {
|
||||
differencesS1.push({ index: i - 1, char: s1[i - 1] });
|
||||
i--;
|
||||
}
|
||||
|
||||
// Remaining characters in s2 (insertions)
|
||||
while (j > 0) {
|
||||
differencesS2.push({ index: j - 1, char: s2[j - 1] });
|
||||
j--;
|
||||
}
|
||||
|
||||
return {
|
||||
differencesS1: differencesS1.reverse(), // Reverse to maintain original order
|
||||
differencesS2: differencesS2.reverse()
|
||||
};
|
||||
};
|
||||
|
||||
$app.methods.findSequeces = function (arr) {
|
||||
if (arr.length === 0) return [];
|
||||
return arr.reduce(
|
||||
(p, c, i) => {
|
||||
if (i === 0) return p;
|
||||
let lastSeq = p.pop();
|
||||
p.push(lastSeq);
|
||||
if (c - lastSeq[1] !== 1) {
|
||||
p.push([c, c]);
|
||||
} else {
|
||||
lastSeq[1] = c;
|
||||
}
|
||||
return p;
|
||||
},
|
||||
[[arr[0], arr[0]]]
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Function that format the differences between two strings with HTML tags
|
||||
* markerStartTag and markerEndTag are optional, if emitted, the differences will be highlighted with yellow and underlined.
|
||||
* @param {*} s1
|
||||
* @param {*} s2
|
||||
* @param {*} markerStartTag
|
||||
* @param {*} markerEndTag
|
||||
* @returns An array that contains both the string 1 and string 2, which the differences are formated with HTML tags
|
||||
*/
|
||||
$app.methods.formatDifference = function (
|
||||
s1,
|
||||
s2,
|
||||
markerStartTag = '<u><font color="yellow">',
|
||||
markerEndTag = '</font></u>'
|
||||
) {
|
||||
const texts = [s1, s2];
|
||||
const differs = $app.findDifferences(s1, s2);
|
||||
return Object.values(differs)
|
||||
.map((i) => $app.findSequeces(i.map((j) => j.index)))
|
||||
.map((i, k) => {
|
||||
let stringBuilder = [];
|
||||
let lastPos = 0;
|
||||
let key = Date.now();
|
||||
i.forEach((j) => {
|
||||
stringBuilder.push(texts[k].substring(lastPos, j[0]));
|
||||
stringBuilder.push(
|
||||
`{{diffTag-${key}}}${texts[k].substring(j[0], j[1] + 1)}{{diffTagClose-${key}}}`
|
||||
);
|
||||
lastPos = j[1] + 1;
|
||||
});
|
||||
stringBuilder.push(texts[k].substr(lastPos, texts[k].length));
|
||||
let returnVal = stringBuilder
|
||||
.join('')
|
||||
.replaceAll(/&/g, '&')
|
||||
.replaceAll(/</g, '<')
|
||||
.replaceAll(/>/g, '>')
|
||||
.replaceAll(/"/g, '"')
|
||||
.replaceAll(/'/g, ''')
|
||||
.replaceAll(`{{diffTag-${key}}}`, markerStartTag)
|
||||
.replaceAll(`{{diffTagClose-${key}}}`, markerEndTag);
|
||||
return returnVal;
|
||||
});
|
||||
};
|
||||
|
||||
// #endregion
|
||||
// #region | App: gameLog
|
||||
|
||||
|
||||
@@ -65,10 +65,10 @@ mixin feedTab()
|
||||
i.x-user-status(:class="statusClass(scope.row.status)")
|
||||
span(v-text="scope.row.statusDescription")
|
||||
template(v-else-if="scope.row.type === 'Bio'")
|
||||
pre(v-text="scope.row.previousBio" style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0")
|
||||
span
|
||||
i.el-icon-right
|
||||
pre(v-text="scope.row.bio" style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0")
|
||||
template(v-for="(bio,idx) in formatDifference(scope.row.previousBio,scope.row.bio)")
|
||||
pre(v-html="bio" style="font-family:inherit;font-size:12px;white-space:pre-wrap;margin:0 0.5em 0 0")
|
||||
span(v-if="idx===0")
|
||||
i.el-icon-right
|
||||
el-table-column(:label="$t('table.feed.date')" prop="created_at" sortable="custom" width="120")
|
||||
template(v-once #default="scope")
|
||||
el-tooltip(placement="right")
|
||||
|
||||
Reference in New Issue
Block a user