Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 8 additions & 10 deletions src/autolink.zig
Original file line number Diff line number Diff line change
Expand Up @@ -148,27 +148,21 @@ pub const AutolinkProcessor = struct {
const size = self.text.len;

var rewind: usize = 0;
var ns: usize = 0;
while (rewind < i) {
const c = self.text.*[i - rewind - 1];
if (ascii.isAlphanumeric(c) or EMAIL_OK_SET[c]) {
rewind += 1;
continue;
}

if (c == '/') {
ns += 1;
}

break;
}

if (rewind == 0 or ns > 0) {
if (rewind == 0) {
return null;
}

var link_end: usize = 0;
var nb: usize = 0;
var link_end: usize = 1;
var np: usize = 0;

while (link_end < size - i) {
Expand All @@ -177,7 +171,7 @@ pub const AutolinkProcessor = struct {
if (ascii.isAlphanumeric(c)) {
// empty
} else if (c == '@') {
nb += 1;
return null;
} else if (c == '.' and link_end < size - i - 1 and ascii.isAlphanumeric(self.text.*[i + link_end + 1])) {
np += 1;
} else if (c != '-' and c != '_') {
Expand All @@ -187,12 +181,16 @@ pub const AutolinkProcessor = struct {
link_end += 1;
}

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] != '.')) {
if (link_end < 2 or np == 0 or (!ascii.isAlphabetic(self.text.*[i + link_end - 1]) and self.text.*[i + link_end - 1] != '.')) {
return null;
}

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

if (link_end == 0) {
return null;
}

var url = try ArrayList(u8).initCapacity(self.allocator, 7 + link_end - rewind);
try url.appendSlice("mailto:");
try url.appendSlice(self.text.*[i - rewind .. link_end + i]);
Expand Down
62 changes: 24 additions & 38 deletions src/inlines.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ const nodes = @import("nodes.zig");
const strings = @import("strings.zig");
const Options = @import("options.zig").Options;
const scanners = @import("scanners.zig");
const Reference = @import("parser.zig").Reference;
const parser_mod = @import("parser.zig");
const Reference = parser_mod.Reference;
const RefMap = parser_mod.RefMap;

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

pub const Subject = struct {
allocator: mem.Allocator,
refmap: *std.StringHashMap(Reference),
refmap: *RefMap,
options: *const Options,
input: []const u8,
pos: usize = 0,
last_delimiter: ?*Delimiter = null,
brackets: ArrayList(Bracket),
backticks: [MAX_BACKTICKS + 1]usize = [_]usize{0} ** (MAX_BACKTICKS + 1),
scanned_for_backticks: bool = false,
no_link_openers: bool = true,
special_chars: *const [256]bool,
skip_chars: *const [256]bool,

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 {
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 {
const s = Subject{
.allocator = allocator,
.refmap = refmap,
Expand Down Expand Up @@ -136,20 +139,12 @@ pub const Subject = struct {
return inl;
}

pub fn processEmphasis(self: *Subject, stack_bottom: ?*Delimiter) !void {
pub fn processEmphasis(self: *Subject, stack_bottom: usize) !void {
var closer = self.last_delimiter;

var openers_bottom: [3][128]?*Delimiter = [_][128]?*Delimiter{[_]?*Delimiter{null} ** 128} ** 3;
for (&openers_bottom) |*i| {
i['*'] = stack_bottom;
i['_'] = stack_bottom;
i['\''] = stack_bottom;
i['"'] = stack_bottom;
if (self.options.extensions.strikethrough)
i['~'] = stack_bottom;
}
var openers_bottom: [3][128]usize = [_][128]usize{[_]usize{stack_bottom} ** 128} ** 3;

while (closer != null and closer.?.prev != stack_bottom) {
while (closer != null and closer.?.prev != null and closer.?.prev.?.position > stack_bottom) {
closer = closer.?.prev;
}

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

while (opener != null and opener != openers_bottom[closer.?.length % 3][closer.?.delim_char]) {
while (opener != null and opener.?.position > openers_bottom[closer.?.length % 3][closer.?.delim_char]) {
if (opener.?.can_open and opener.?.delim_char == closer.?.delim_char) {
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);
if (!odd_match) {
Expand Down Expand Up @@ -204,7 +199,7 @@ pub const Subject = struct {
if (!opener_found) {
const ix = old_closer.?.length % 3;
openers_bottom[ix][old_closer.?.delim_char] =
old_closer.?.prev;
if (old_closer.?.prev) |p| p.position else stack_bottom;

if (!old_closer.?.can_open) {
self.removeDelimiter(old_closer.?);
Expand All @@ -215,7 +210,7 @@ pub const Subject = struct {
}
}

while (self.last_delimiter != null and self.last_delimiter != stack_bottom) {
while (self.last_delimiter != null and self.last_delimiter.?.position > stack_bottom) {
self.removeDelimiter(self.last_delimiter.?);
}
}
Expand Down Expand Up @@ -541,6 +536,7 @@ pub const Subject = struct {
.can_close = can_close,
.prev = self.last_delimiter,
.next = null,
.position = self.pos,
};
if (delimiter.prev) |prev| {
prev.next = delimiter;
Expand Down Expand Up @@ -612,12 +608,13 @@ pub const Subject = struct {
const len = self.brackets.items.len;
if (len > 0)
self.brackets.items[len - 1].bracket_after = true;
if (kind == .Link)
self.no_link_openers = false;
try self.brackets.append(.{
.previous_delimiter = self.last_delimiter,
.delimiter_position = if (self.last_delimiter) |d| d.position else 0,
.inl_text = inl_text,
.position = self.pos,
.kind = kind,
.active = true,
.bracket_after = false,
});
}
Expand All @@ -631,12 +628,12 @@ pub const Subject = struct {
return try self.makeInline(.{ .Text = try self.allocator.dupe(u8, "]") });
}

if (!self.brackets.items[brackets_len - 1].active) {
const kind = self.brackets.items[brackets_len - 1].kind;

if (kind != .Image and self.no_link_openers) {
_ = self.brackets.pop();
return try self.makeInline(.{ .Text = try self.allocator.dupe(u8, "]") });
}

const kind = self.brackets.items[brackets_len - 1].kind;
const after_link_text_pos = self.pos;

var sps: usize = 0;
Expand Down Expand Up @@ -678,7 +675,7 @@ pub const Subject = struct {

const normalized = try strings.normalizeLabel(self.allocator, label orelse "");
defer self.allocator.free(normalized);
const maybe_ref = if (label != null) self.refmap.get(normalized) else null;
const maybe_ref = if (label != null) self.refmap.lookup(normalized) else null;

if (maybe_ref) |ref| {
try self.closeBracketMatch(kind, try self.allocator.dupe(u8, ref.url), try self.allocator.dupe(u8, ref.title));
Expand Down Expand Up @@ -748,23 +745,12 @@ pub const Subject = struct {
inl.append(tmp);
}
self.brackets.items[brackets_len - 1].inl_text.detachDeinit();
const previous_delimiter = self.brackets.items[brackets_len - 1].previous_delimiter;
try self.processEmphasis(previous_delimiter);
try self.processEmphasis(self.brackets.items[brackets_len - 1].delimiter_position);
_ = self.brackets.pop();
brackets_len -= 1;

if (kind == .Link) {
var i: i32 = @intCast(brackets_len);
i -= 1;
while (i >= 0) : (i -= 1) {
if (self.brackets.items[@intCast(i)].kind == .Link) {
if (!self.brackets.items[@intCast(i)].active) {
break;
} else {
self.brackets.items[@intCast(i)].active = false;
}
}
}
self.no_link_openers = true;
}
}

Expand Down Expand Up @@ -849,14 +835,14 @@ const Delimiter = struct {
can_close: bool,
prev: ?*Delimiter,
next: ?*Delimiter,
position: usize,
};

const Bracket = struct {
previous_delimiter: ?*Delimiter,
delimiter_position: usize,
inl_text: *nodes.AstNode,
position: usize,
kind: BracketKind,
active: bool,
bracket_after: bool,
};

Expand Down
1 change: 1 addition & 0 deletions src/nodes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub const Node = struct {
content: ArrayList(u8),
open: bool = true,
last_line_blank: bool = false,
table_visited: bool = false,

pub fn deinit(self: *Node, allocator: mem.Allocator) void {
self.content.deinit();
Expand Down
Loading