Merge pull request #2408 from thelounge/xpaw/parser-merger

Minor optimization in style parser
This commit is contained in:
Jérémie Astori 2018-05-01 19:37:10 -04:00 committed by GitHub
commit 9558a1af58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 21 deletions

View File

@ -13,23 +13,34 @@ function assign(textPart, fragment) {
return Object.assign({}, fragment, {start, end, text}); return Object.assign({}, fragment, {start, end, text});
} }
// Merge the style fragments withing the text parts, taking into account function sortParts(a, b) {
return a.start - b.start || b.end - a.end;
}
// Merge the style fragments within the text parts, taking into account
// boundaries and text sections that have not matched to links or channels. // boundaries and text sections that have not matched to links or channels.
// For example, given a string "foobar" where "foo" and "bar" have been // For example, given a string "foobar" where "foo" and "bar" have been
// identified as parts (channels, links, etc.) and "fo", "ob" and "ar" have 3 // identified as parts (channels, links, etc.) and "fo", "ob" and "ar" have 3
// different styles, the first resulting part will contain fragments "fo" and // different styles, the first resulting part will contain fragments "fo" and
// "o", and the second resulting part will contain "b" and "ar". "o" and "b" // "o", and the second resulting part will contain "b" and "ar". "o" and "b"
// fragments will contain duplicate styling attributes. // fragments will contain duplicate styling attributes.
function merge(textParts, styleFragments) { function merge(textParts, styleFragments, cleanText) {
// Re-build the overall text (without control codes) from the style fragments
const cleanText = styleFragments.reduce((acc, frag) => acc + frag.text, "");
// Every section of the original text that has not been captured in a "part" // Every section of the original text that has not been captured in a "part"
// is filled with "text" parts, dummy objects with start/end but no extra // is filled with "text" parts, dummy objects with start/end but no extra
// metadata. // metadata.
const allParts = textParts const allParts = textParts
.sort(sortParts) // Sort all parts identified based on their position in the original text
.concat(fill(textParts, cleanText)) .concat(fill(textParts, cleanText))
.sort((a, b) => a.start - b.start); .sort(sortParts) // Sort them again after filling in unstyled text
.reduce((prev, curr) => {
const intersection = prev.some((p) => anyIntersection(p, curr));
if (intersection) {
return prev;
}
return prev.concat([curr]);
}, []);
// Distribute the style fragments within the text parts // Distribute the style fragments within the text parts
return allParts.map((textPart) => { return allParts.map((textPart) => {

View File

@ -2,7 +2,6 @@
const Handlebars = require("handlebars/runtime"); const Handlebars = require("handlebars/runtime");
const parseStyle = require("./ircmessageparser/parseStyle"); const parseStyle = require("./ircmessageparser/parseStyle");
const anyIntersection = require("./ircmessageparser/anyIntersection");
const findChannels = require("./ircmessageparser/findChannels"); const findChannels = require("./ircmessageparser/findChannels");
const findLinks = require("./ircmessageparser/findLinks"); const findLinks = require("./ircmessageparser/findLinks");
const findEmoji = require("./ircmessageparser/findEmoji"); const findEmoji = require("./ircmessageparser/findEmoji");
@ -85,25 +84,14 @@ module.exports = function parse(text, users) {
const emojiParts = findEmoji(cleanText); const emojiParts = findEmoji(cleanText);
const nameParts = findNames(cleanText, (users || [])); const nameParts = findNames(cleanText, (users || []));
// Sort all parts identified based on their position in the original text
const parts = channelParts const parts = channelParts
.concat(linkParts) .concat(linkParts)
.concat(emojiParts) .concat(emojiParts)
.concat(nameParts) .concat(nameParts);
.sort((a, b) => a.start - b.start || b.end - a.end)
.reduce((prev, curr) => {
const intersection = prev.some((p) => anyIntersection(p, curr));
if (intersection) {
return prev;
}
return prev.concat([curr]);
}, []);
// Merge the styling information with the channels / URLs / nicks / text objects and // Merge the styling information with the channels / URLs / nicks / text objects and
// generate HTML strings with the resulting fragments // generate HTML strings with the resulting fragments
return merge(parts, styleFragments).map((textPart) => { return merge(parts, styleFragments, cleanText).map((textPart) => {
// Create HTML strings with styling information // Create HTML strings with styling information
const fragments = textPart.fragments.map(createFragment).join(""); const fragments = textPart.fragments.map(createFragment).join("");

View File

@ -56,7 +56,7 @@ describe("merge", () => {
}], }],
}]; }];
const actual = merge(textParts, styleFragments); const actual = merge(textParts, styleFragments, styleFragments.map((fragment) => fragment.text).join(""));
expect(actual).to.deep.equal(expected); expect(actual).to.deep.equal(expected);
}); });