Skip to content

Commit dffa219

Browse files
committed
fmt: don't vertically align tags in text
1 parent 2008408 commit dffa219

File tree

1 file changed

+61
-22
lines changed

1 file changed

+61
-22
lines changed

src/html/Ast.zig

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const kinds = Element.elements;
1515
const Attribute = @import("Attribute.zig");
1616

1717
const log = std.log.scoped(.@"html/ast");
18+
const fmtlog = std.log.scoped(.@"html/ast/fmt");
1819

1920
has_syntax_errors: bool,
2021
language: Language,
@@ -949,34 +950,40 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
949950
var current = ast.nodes[1];
950951
var direction: enum { enter, exit } = .enter;
951952
var last_rbracket: u32 = 0;
953+
var last_was_text = false;
952954
var pre: u32 = 0;
953955
while (true) {
954956
const zone_outer = tracy.trace(@src());
955957
defer zone_outer.end();
956-
log.debug("looping, ind: {}, dir: {s}", .{
958+
fmtlog.debug("looping, ind: {}, dir: {s}", .{
957959
indentation,
958960
@tagName(direction),
959961
});
962+
963+
const crt = current;
964+
defer last_was_text = crt.kind == .text;
960965
switch (direction) {
961966
.enter => {
962967
const zone = tracy.trace(@src());
963968
defer zone.end();
964-
log.debug("rendering enter ({}): {s} {any}", .{
969+
fmtlog.debug("rendering enter ({}): {t} lwt: {}", .{
965970
indentation,
966-
"",
967-
// current.open.slice(src),
968-
current,
971+
current.kind,
972+
last_was_text,
969973
});
970974

971975
const maybe_ws = src[last_rbracket..current.open.start];
972-
log.debug("maybe_ws = '{s}'", .{maybe_ws});
976+
fmtlog.debug("maybe_ws = '{s}'", .{maybe_ws});
973977
if (pre > 0) {
974978
try w.writeAll(maybe_ws);
975979
} else {
976-
const vertical = maybe_ws.len > 0;
980+
const vertical = if (last_was_text and current.kind != .text)
981+
std.mem.indexOfScalar(u8, maybe_ws, '\n') != null
982+
else
983+
maybe_ws.len > 0;
977984

978985
if (vertical) {
979-
log.debug("adding a newline", .{});
986+
fmtlog.debug("adding a newline", .{});
980987
const lines = std.mem.count(u8, maybe_ws, "\n");
981988
if (last_rbracket > 0) {
982989
if (lines >= 2) {
@@ -989,6 +996,8 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
989996
for (0..indentation) |_| {
990997
try w.writeAll("\t");
991998
}
999+
} else if ((last_was_text or current.kind == .text) and maybe_ws.len > 0) {
1000+
try w.writeAll(" ");
9921001
}
9931002
}
9941003

@@ -1016,7 +1025,7 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
10161025
return;
10171026
}
10181027

1019-
log.debug("rendering exit ({}): {s} {any}", .{
1028+
fmtlog.debug("rendering exit ({}): {s} {any}", .{
10201029
indentation,
10211030
current.open.slice(src),
10221031
current,
@@ -1034,12 +1043,24 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
10341043
indentation -= 1;
10351044
}
10361045

1037-
const open_was_vertical = std.ascii.isWhitespace(src[current.open.end]);
1038-
10391046
if (pre > 0) {
10401047
const maybe_ws = src[last_rbracket..current.close.start];
10411048
try w.writeAll(maybe_ws);
10421049
} else {
1050+
// const first_child_is_text = if (ast.child(current)) |ch|
1051+
// ch.kind == .text
1052+
// else
1053+
// false;
1054+
// const open_was_vertical = if (first_child_is_text)
1055+
// std.mem.indexOfScalar(
1056+
// u8,
1057+
// src[current.open.end..ast.nodes[current.first_child_idx].open.start],
1058+
// '\n',
1059+
// ) != null
1060+
// else
1061+
// std.ascii.isWhitespace(src[current.open.end]);
1062+
1063+
const open_was_vertical = std.ascii.isWhitespace(src[current.open.end]);
10431064
if (open_was_vertical) {
10441065
try w.writeAll("\n");
10451066
for (0..indentation) |_| {
@@ -1069,7 +1090,29 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
10691090
const txt = current.open.slice(src);
10701091
const parent_kind = ast.nodes[current.parent_idx].kind;
10711092
switch (parent_kind) {
1072-
else => try w.writeAll(txt),
1093+
else => {
1094+
var it = std.mem.splitScalar(u8, txt, '\n');
1095+
var first = true;
1096+
var empty_line = false;
1097+
while (it.next()) |raw_line| {
1098+
const line = std.mem.trim(
1099+
u8,
1100+
raw_line,
1101+
&std.ascii.whitespace,
1102+
);
1103+
if (line.len == 0) {
1104+
if (empty_line) continue;
1105+
empty_line = true;
1106+
if (!first) for (0..indentation) |_| try w.print("\t", .{});
1107+
try w.print("\n", .{});
1108+
continue;
1109+
} else empty_line = false;
1110+
if (!first) for (0..indentation) |_| try w.print("\t", .{});
1111+
try w.print("{s}", .{line});
1112+
if (it.peek() != null) try w.print("\n", .{});
1113+
first = false;
1114+
}
1115+
},
10731116
.style, .script => {
10741117
var css_indent = indentation;
10751118
var it = std.mem.splitScalar(u8, txt, '\n');
@@ -1110,7 +1153,7 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
11101153
last_rbracket = current.open.end;
11111154

11121155
if (current.next_idx != 0) {
1113-
log.debug("text next: {}", .{current.next_idx});
1156+
fmtlog.debug("text next: {}", .{current.next_idx});
11141157
current = ast.nodes[current.next_idx];
11151158
} else {
11161159
current = ast.nodes[current.parent_idx];
@@ -1141,7 +1184,7 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
11411184
const maybe_name, const maybe_extra = blk: {
11421185
var tt: Tokenizer = .{ .language = ast.language };
11431186
const tag = current.open.slice(src);
1144-
log.debug("doctype tag: {s} {any}", .{ tag, current });
1187+
fmtlog.debug("doctype tag: {s} {any}", .{ tag, current });
11451188
const dt = tt.next(tag).?.doctype;
11461189
const maybe_name: ?[]const u8 = if (dt.name) |name|
11471190
name.slice(tag)
@@ -1203,7 +1246,7 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
12031246
break :blk true;
12041247
};
12051248

1206-
log.debug("element <{s}> vertical = {}", .{ name, vertical });
1249+
fmtlog.debug("element <{s}> vertical = {}", .{ name, vertical });
12071250

12081251
// if (std.mem.eql(u8, name, "path")) @breakpoint();
12091252

@@ -1294,7 +1337,7 @@ pub fn render(ast: Ast, src: []const u8, w: *Writer) !void {
12941337
.return_attrs = true,
12951338
};
12961339
const tag = current.open.slice(src);
1297-
log.debug("retokenize {s}\n", .{tag});
1340+
fmtlog.debug("retokenize {s}\n", .{tag});
12981341
break :blk tt.getName(tag).?.slice(tag);
12991342
};
13001343

@@ -1870,17 +1913,13 @@ test "spans" {
18701913
test "arrow span" {
18711914
const case =
18721915
\\<a href="$if.permalink()">← <span var="$if.title"></span></a>
1873-
;
1874-
const expected = comptime std.fmt.comptimePrint(
1875-
\\<a href="$if.permalink()">←
1876-
\\{c}<span var="$if.title"></span></a>
18771916
\\
1878-
, .{'\t'});
1917+
;
18791918

18801919
const ast = try Ast.init(std.testing.allocator, case, .html, true);
18811920
defer ast.deinit(std.testing.allocator);
18821921

1883-
try std.testing.expectFmt(expected, "{f}", .{ast.formatter(case)});
1922+
try std.testing.expectFmt(case, "{f}", .{ast.formatter(case)});
18841923
}
18851924

18861925
test "self-closing tag complex example" {

0 commit comments

Comments
 (0)