Skip to content

Commit 0f10363

Browse files
authored
Merge pull request #65 from kivikakk/push-swtsmsuxkqzo
port comrak quadratic fixes
2 parents 115c666 + fc2df9b commit 0f10363

File tree

6 files changed

+107
-79
lines changed

6 files changed

+107
-79
lines changed

flake.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/autolink.zig

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -148,27 +148,21 @@ pub const AutolinkProcessor = struct {
148148
const size = self.text.len;
149149

150150
var rewind: usize = 0;
151-
var ns: usize = 0;
152151
while (rewind < i) {
153152
const c = self.text.*[i - rewind - 1];
154153
if (ascii.isAlphanumeric(c) or EMAIL_OK_SET[c]) {
155154
rewind += 1;
156155
continue;
157156
}
158157

159-
if (c == '/') {
160-
ns += 1;
161-
}
162-
163158
break;
164159
}
165160

166-
if (rewind == 0 or ns > 0) {
161+
if (rewind == 0) {
167162
return null;
168163
}
169164

170-
var link_end: usize = 0;
171-
var nb: usize = 0;
165+
var link_end: usize = 1;
172166
var np: usize = 0;
173167

174168
while (link_end < size - i) {
@@ -177,7 +171,7 @@ pub const AutolinkProcessor = struct {
177171
if (ascii.isAlphanumeric(c)) {
178172
// empty
179173
} else if (c == '@') {
180-
nb += 1;
174+
return null;
181175
} else if (c == '.' and link_end < size - i - 1 and ascii.isAlphanumeric(self.text.*[i + link_end + 1])) {
182176
np += 1;
183177
} else if (c != '-' and c != '_') {
@@ -187,12 +181,16 @@ pub const AutolinkProcessor = struct {
187181
link_end += 1;
188182
}
189183

190-
if (link_end < 2 or nb != 1 or np == 0 or (!ascii.isAlphabetic(self.text.*[i + link_end - 1]) and self.text.*[i + link_end - 1] != '.')) {
184+
if (link_end < 2 or np == 0 or (!ascii.isAlphabetic(self.text.*[i + link_end - 1]) and self.text.*[i + link_end - 1] != '.')) {
191185
return null;
192186
}
193187

194188
link_end = autolinkDelim(self.text.*[i..], link_end);
195189

190+
if (link_end == 0) {
191+
return null;
192+
}
193+
196194
var url = try ArrayList(u8).initCapacity(self.allocator, 7 + link_end - rewind);
197195
try url.appendSlice("mailto:");
198196
try url.appendSlice(self.text.*[i - rewind .. link_end + i]);

src/inlines.zig

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ const nodes = @import("nodes.zig");
88
const strings = @import("strings.zig");
99
const Options = @import("options.zig").Options;
1010
const scanners = @import("scanners.zig");
11-
const Reference = @import("parser.zig").Reference;
11+
const parser_mod = @import("parser.zig");
12+
const Reference = parser_mod.Reference;
13+
const RefMap = parser_mod.RefMap;
1214

1315
const MAX_BACKTICKS = 80;
1416
const MAX_LINK_LABEL_LENGTH = 1000;
@@ -17,18 +19,19 @@ pub const ParseError = error{ OutOfMemory, InvalidUtf8 };
1719

1820
pub const Subject = struct {
1921
allocator: mem.Allocator,
20-
refmap: *std.StringHashMap(Reference),
22+
refmap: *RefMap,
2123
options: *const Options,
2224
input: []const u8,
2325
pos: usize = 0,
2426
last_delimiter: ?*Delimiter = null,
2527
brackets: ArrayList(Bracket),
2628
backticks: [MAX_BACKTICKS + 1]usize = [_]usize{0} ** (MAX_BACKTICKS + 1),
2729
scanned_for_backticks: bool = false,
30+
no_link_openers: bool = true,
2831
special_chars: *const [256]bool,
2932
skip_chars: *const [256]bool,
3033

31-
pub fn init(allocator: mem.Allocator, refmap: *std.StringHashMap(Reference), options: *const Options, special_chars: *const [256]bool, skip_chars: *const [256]bool, input: []const u8) Subject {
34+
pub fn init(allocator: mem.Allocator, refmap: *RefMap, options: *const Options, special_chars: *const [256]bool, skip_chars: *const [256]bool, input: []const u8) Subject {
3235
const s = Subject{
3336
.allocator = allocator,
3437
.refmap = refmap,
@@ -136,20 +139,12 @@ pub const Subject = struct {
136139
return inl;
137140
}
138141

139-
pub fn processEmphasis(self: *Subject, stack_bottom: ?*Delimiter) !void {
142+
pub fn processEmphasis(self: *Subject, stack_bottom: usize) !void {
140143
var closer = self.last_delimiter;
141144

142-
var openers_bottom: [3][128]?*Delimiter = [_][128]?*Delimiter{[_]?*Delimiter{null} ** 128} ** 3;
143-
for (&openers_bottom) |*i| {
144-
i['*'] = stack_bottom;
145-
i['_'] = stack_bottom;
146-
i['\''] = stack_bottom;
147-
i['"'] = stack_bottom;
148-
if (self.options.extensions.strikethrough)
149-
i['~'] = stack_bottom;
150-
}
145+
var openers_bottom: [3][128]usize = [_][128]usize{[_]usize{stack_bottom} ** 128} ** 3;
151146

152-
while (closer != null and closer.?.prev != stack_bottom) {
147+
while (closer != null and closer.?.prev != null and closer.?.prev.?.position > stack_bottom) {
153148
closer = closer.?.prev;
154149
}
155150

@@ -158,7 +153,7 @@ pub const Subject = struct {
158153
var opener = closer.?.prev;
159154
var opener_found = false;
160155

161-
while (opener != null and opener != openers_bottom[closer.?.length % 3][closer.?.delim_char]) {
156+
while (opener != null and opener.?.position > openers_bottom[closer.?.length % 3][closer.?.delim_char]) {
162157
if (opener.?.can_open and opener.?.delim_char == closer.?.delim_char) {
163158
const odd_match = (closer.?.can_open or opener.?.can_close) and ((opener.?.length + closer.?.length) % 3 == 0) and !(opener.?.length % 3 == 0 and closer.?.length % 3 == 0);
164159
if (!odd_match) {
@@ -204,7 +199,7 @@ pub const Subject = struct {
204199
if (!opener_found) {
205200
const ix = old_closer.?.length % 3;
206201
openers_bottom[ix][old_closer.?.delim_char] =
207-
old_closer.?.prev;
202+
if (old_closer.?.prev) |p| p.position else stack_bottom;
208203

209204
if (!old_closer.?.can_open) {
210205
self.removeDelimiter(old_closer.?);
@@ -215,7 +210,7 @@ pub const Subject = struct {
215210
}
216211
}
217212

218-
while (self.last_delimiter != null and self.last_delimiter != stack_bottom) {
213+
while (self.last_delimiter != null and self.last_delimiter.?.position > stack_bottom) {
219214
self.removeDelimiter(self.last_delimiter.?);
220215
}
221216
}
@@ -541,6 +536,7 @@ pub const Subject = struct {
541536
.can_close = can_close,
542537
.prev = self.last_delimiter,
543538
.next = null,
539+
.position = self.pos,
544540
};
545541
if (delimiter.prev) |prev| {
546542
prev.next = delimiter;
@@ -612,12 +608,13 @@ pub const Subject = struct {
612608
const len = self.brackets.items.len;
613609
if (len > 0)
614610
self.brackets.items[len - 1].bracket_after = true;
611+
if (kind == .Link)
612+
self.no_link_openers = false;
615613
try self.brackets.append(.{
616-
.previous_delimiter = self.last_delimiter,
614+
.delimiter_position = if (self.last_delimiter) |d| d.position else 0,
617615
.inl_text = inl_text,
618616
.position = self.pos,
619617
.kind = kind,
620-
.active = true,
621618
.bracket_after = false,
622619
});
623620
}
@@ -631,12 +628,12 @@ pub const Subject = struct {
631628
return try self.makeInline(.{ .Text = try self.allocator.dupe(u8, "]") });
632629
}
633630

634-
if (!self.brackets.items[brackets_len - 1].active) {
631+
const kind = self.brackets.items[brackets_len - 1].kind;
632+
633+
if (kind != .Image and self.no_link_openers) {
635634
_ = self.brackets.pop();
636635
return try self.makeInline(.{ .Text = try self.allocator.dupe(u8, "]") });
637636
}
638-
639-
const kind = self.brackets.items[brackets_len - 1].kind;
640637
const after_link_text_pos = self.pos;
641638

642639
var sps: usize = 0;
@@ -678,7 +675,7 @@ pub const Subject = struct {
678675

679676
const normalized = try strings.normalizeLabel(self.allocator, label orelse "");
680677
defer self.allocator.free(normalized);
681-
const maybe_ref = if (label != null) self.refmap.get(normalized) else null;
678+
const maybe_ref = if (label != null) self.refmap.lookup(normalized) else null;
682679

683680
if (maybe_ref) |ref| {
684681
try self.closeBracketMatch(kind, try self.allocator.dupe(u8, ref.url), try self.allocator.dupe(u8, ref.title));
@@ -748,23 +745,12 @@ pub const Subject = struct {
748745
inl.append(tmp);
749746
}
750747
self.brackets.items[brackets_len - 1].inl_text.detachDeinit();
751-
const previous_delimiter = self.brackets.items[brackets_len - 1].previous_delimiter;
752-
try self.processEmphasis(previous_delimiter);
748+
try self.processEmphasis(self.brackets.items[brackets_len - 1].delimiter_position);
753749
_ = self.brackets.pop();
754750
brackets_len -= 1;
755751

756752
if (kind == .Link) {
757-
var i: i32 = @intCast(brackets_len);
758-
i -= 1;
759-
while (i >= 0) : (i -= 1) {
760-
if (self.brackets.items[@intCast(i)].kind == .Link) {
761-
if (!self.brackets.items[@intCast(i)].active) {
762-
break;
763-
} else {
764-
self.brackets.items[@intCast(i)].active = false;
765-
}
766-
}
767-
}
753+
self.no_link_openers = true;
768754
}
769755
}
770756

@@ -849,14 +835,14 @@ const Delimiter = struct {
849835
can_close: bool,
850836
prev: ?*Delimiter,
851837
next: ?*Delimiter,
838+
position: usize,
852839
};
853840

854841
const Bracket = struct {
855-
previous_delimiter: ?*Delimiter,
842+
delimiter_position: usize,
856843
inl_text: *nodes.AstNode,
857844
position: usize,
858845
kind: BracketKind,
859-
active: bool,
860846
bracket_after: bool,
861847
};
862848

src/nodes.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub const Node = struct {
1010
content: ArrayList(u8),
1111
open: bool = true,
1212
last_line_blank: bool = false,
13+
table_visited: bool = false,
1314

1415
pub fn deinit(self: *Node, allocator: mem.Allocator) void {
1516
self.content.deinit();

0 commit comments

Comments
 (0)