Skip to content

Commit

Permalink
Add matchIndex parameter to addMatch.
Browse files Browse the repository at this point in the history
This allows us to splice things like `-emph` into the appropriate place
in the match list, avoiding the need to sort the whole list in
getMatches.

This yields ~ 20% speed increase in inline-heavy text.

See #13.
  • Loading branch information
jgm committed Jan 8, 2023
1 parent f80d65b commit 28b330a
Showing 1 changed file with 48 additions and 20 deletions.
68 changes: 48 additions & 20 deletions src/inline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Opener = {
startpos: number,
endpos: number,
annot: null | string,
subMatchIndex: number,
substartpos: null | number,
subendpos: null | number
}
Expand Down Expand Up @@ -150,7 +151,8 @@ const betweenMatched = function(
const opener = openers[openers.length - 1];
if (opener.endpos !== pos - 1) { // exclude empty emph
self.clearOpeners(opener.startpos, pos);
self.addMatch(opener.startpos, opener.endpos, "+" + annotation);
self.addMatch(opener.startpos, opener.endpos, "+" + annotation,
opener.matchIndex);
self.addMatch(pos, endcloser, "-" + annotation);
return endcloser + 1;
}
Expand Down Expand Up @@ -358,45 +360,55 @@ const matchers = {
subject.codePointAt(opener.startpos - 2) !== C_BACKSLASH;
if (isImage) {
self.addMatch(opener.startpos - 1, opener.startpos - 1,
"image_marker");
self.addMatch(opener.startpos, opener.endpos, "+imagetext");
"image_marker", opener.matchIndex);
self.addMatch(opener.startpos, opener.endpos, "+imagetext",
opener.matchIndex);
self.addMatch(opener.substartpos || opener.startpos,
opener.substartpos || opener.startpos, "-imagetext");
opener.substartpos || opener.startpos, "-imagetext",
opener.subMatchIndex);
} else {
self.addMatch(opener.startpos, opener.endpos, "+linktext");
self.addMatch(opener.startpos, opener.endpos, "+linktext",
opener.matchIndex);
self.addMatch(opener.substartpos || opener.startpos,
opener.substartpos || opener.startpos, "-linktext");
opener.substartpos || opener.startpos, "-linktext",
opener.subMatchIndex);
}
self.addMatch(opener.subendpos || opener.endpos,
opener.subendpos || opener.endpos, "+reference");
opener.subendpos || opener.endpos, "+reference",
opener.subMatchIndex + 1);
self.addMatch(pos, pos, "-reference");
// remove from openers
self.clearOpeners(opener.startpos, pos);
return pos + 1;
} else if (pos + 1 <= endpos &&
subject.codePointAt(pos + 1) === C_LEFT_BRACKET) {
opener.annot = "reference_link";
self.addMatch(pos, pos, "str");
opener.subMatchIndex = self.matches.length - 1;
self.addMatch(pos + 1, pos + 1, "str");
opener.substartpos = pos; // intermediate ]
opener.subendpos = pos + 1; // intermediate [
self.addMatch(pos, pos + 1, "str");
// remove any openers between [ and ]
self.clearOpeners(opener.startpos + 1, pos - 1);
return pos + 2;
} else if (pos + 1 <= endpos &&
subject.codePointAt(pos + 1) === C_LEFT_PAREN) {
self.openers["("] = []; // clear ( openers
opener.annot = "explicit_link";
self.addMatch(pos, pos, "str"); // ]
opener.subMatchIndex = self.matches.length - 1;
self.addMatch(pos + 1, pos + 1, "str"); // (
opener.substartpos = pos; // intermediate ]
opener.subendpos = pos + 1; // intermediate (
self.destination = true;
self.addMatch(pos, pos + 1, "str");
// remove any openers between [ and ]
self.clearOpeners(opener.startpos + 1, pos - 1);
return pos + 2;
} else if (pos + 1 <= endpos &&
subject.codePointAt(pos + 1) === C_LEFT_BRACE) {
// assume this is attributes, bracketed span
self.addMatch(opener.startpos, opener.endpos, "+span");
self.addMatch(opener.startpos, opener.endpos, "+span",
opener.matchIndex);
self.addMatch(pos, pos, "-span");
// remove any openers between [ and ]
self.clearOpeners(opener.startpos, pos);
Expand Down Expand Up @@ -435,17 +447,23 @@ const matchers = {
subject.codePointAt(opener.startpos - 1) === C_BANG &&
subject.codePointAt(opener.startpos - 2) !== C_BACKSLASH;
if (isImage) {
self.addMatch(opener.startpos - 1, opener.startpos - 1, "image_marker");
self.addMatch(opener.startpos, opener.endpos, "+imagetext");
self.addMatch(opener.startpos - 1, opener.startpos - 1,
"image_marker", opener.matchIndex);
self.addMatch(opener.startpos, opener.endpos, "+imagetext",
opener.matchIndex);
self.addMatch(opener.substartpos || opener.startpos,
opener.substartpos || opener.startpos, "-imagetext");
opener.substartpos || opener.startpos, "-imagetext",
opener.subMatchIndex);
} else {
self.addMatch(opener.startpos, opener.endpos, "+linktext");
self.addMatch(opener.startpos, opener.endpos, "+linktext",
opener.matchIndex);
self.addMatch(opener.substartpos || opener.startpos,
opener.substartpos || opener.startpos, "-linktext");
opener.substartpos || opener.startpos, "-linktext",
opener.subMatchIndex);
}
self.addMatch(opener.subendpos || opener.endpos,
opener.subendpos || opener.endpos, "+destination");
opener.subendpos || opener.endpos, "+destination",
opener.subMatchIndex + 1);
self.addMatch(pos, pos, "-destination");
self.destination = false;
// remove from openers
Expand Down Expand Up @@ -546,8 +564,18 @@ class InlineParser {
this.matchers = matchers;
}

addMatch(startpos: number, endpos: number, annot: string): void {
this.matches.push({ startpos: startpos, endpos: endpos, annot: annot });
addMatch(startpos: number, endpos: number,
annot: string, matchIndex?: number): void {
let match = { startpos: startpos, endpos: endpos, annot: annot };
if (matchIndex !== undefined) {
// insert into the proper place, replacing placeholder
while (this.matches[matchIndex].startpos > startpos && matchIndex > 0) {
matchIndex--;
}
this.matches.splice(matchIndex, 1, match);
} else {
this.matches.push(match);
}
}

inVerbatim(): boolean {
Expand Down Expand Up @@ -583,7 +611,6 @@ class InlineParser {
// we're still in an attribute parse
this.reparseAttributes();
}
this.matches.sort((a,b) => a.startpos - b.startpos);
let i = this.matches.length - 1;
// remove trailing softbreak and any spaces
if (this.matches[i] && this.matches[i].annot === "soft_break") {
Expand Down Expand Up @@ -644,6 +671,7 @@ class InlineParser {
startpos: startpos,
endpos: endpos,
annot: null,
subMatchIndex: this.matches.length,
substartpos: null,
subendpos: null });
// add default match (to be used if we don't match the opener)
Expand Down Expand Up @@ -720,13 +748,13 @@ class InlineParser {
// add attribute matches
if (attributeStart !== null) {
this.addMatch(attributeStart, attributeStart, "+attributes");
this.addMatch(ep, ep, "-attributes");
}
const attrMatches = this.attributeParser.matches;
// add attribute matches
for (const match of attrMatches) {
this.addMatch(match.startpos, match.endpos, match.annot);
}
this.addMatch(ep, ep, "-attributes");
// restore state to prior to adding attribute parser
this.attributeParser = null;
this.attributeStart = null;
Expand Down

0 comments on commit 28b330a

Please sign in to comment.