Commit de92925897

pfg <pfg@pfg.pw>
2021-10-01 21:43:23
Add line numbers to langref (fixes #9870)
1 parent c4cd592
Changed files (2)
doc/docgen.zig
@@ -864,6 +864,21 @@ fn isType(name: []const u8) bool {
     return false;
 }
 
+const start_line = "<span class=\"line\">";
+const end_line = "</span>";
+
+fn writeEscapedLines(out: anytype, text: []const u8) !void {
+    for (text) |char| {
+        if (char == '\n') {
+            try out.writeAll(end_line);
+            try out.writeAll("\n");
+            try out.writeAll(start_line);
+        } else {
+            try writeEscaped(out, &[_]u8{char});
+        }
+    }
+}
+
 fn tokenizeAndPrintRaw(
     allocator: *Allocator,
     docgen_tokenizer: *Tokenizer,
@@ -873,7 +888,8 @@ fn tokenizeAndPrintRaw(
 ) !void {
     const src_non_terminated = mem.trim(u8, raw_src, " \n");
     const src = try allocator.dupeZ(u8, src_non_terminated);
-    try out.writeAll("<code>");
+
+    try out.writeAll("<code>" ++ start_line);
     var tokenizer = std.zig.Tokenizer.init(src);
     var index: usize = 0;
     var next_tok_is_fn = false;
@@ -888,7 +904,7 @@ fn tokenizeAndPrintRaw(
             const comment_end_off = mem.indexOf(u8, src[comment_start..token.loc.start], "\n");
             const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start;
 
-            try writeEscaped(out, src[index..comment_start]);
+            try writeEscapedLines(out, src[index..comment_start]);
             try out.writeAll("<span class=\"tok-comment\">");
             try writeEscaped(out, src[comment_start..comment_end]);
             try out.writeAll("</span>");
@@ -897,7 +913,7 @@ fn tokenizeAndPrintRaw(
             continue;
         }
 
-        try writeEscaped(out, src[index..token.loc.start]);
+        try writeEscapedLines(out, src[index..token.loc.start]);
         switch (token.tag) {
             .eof => break,
 
@@ -1103,7 +1119,7 @@ fn tokenizeAndPrintRaw(
         }
         index = token.loc.end;
     }
-    try out.writeAll("</code>");
+    try out.writeAll(end_line ++ "</code>");
 }
 
 fn tokenizeAndPrint(
@@ -1126,9 +1142,9 @@ fn printSourceBlock(allocator: *Allocator, docgen_tokenizer: *Tokenizer, out: an
             const raw_source = docgen_tokenizer.buffer[syntax_block.source_token.start..syntax_block.source_token.end];
             const trimmed_raw_source = mem.trim(u8, raw_source, " \n");
 
-            try out.writeAll("<code>");
-            try writeEscaped(out, trimmed_raw_source);
-            try out.writeAll("</code>");
+            try out.writeAll("<code>" ++ start_line);
+            try writeEscapedLines(out, trimmed_raw_source);
+            try out.writeAll(end_line ++ "</code>");
         },
     }
     try out.writeAll("</pre></figure>");
@@ -1142,15 +1158,15 @@ fn printShell(out: anytype, shell_content: []const u8) !void {
     while (iter.next()) |orig_line| {
         const line = mem.trimRight(u8, orig_line, " ");
         if (!cmd_cont and line.len > 1 and mem.eql(u8, line[0..2], "$ ") and line[line.len - 1] != '\\') {
-            try out.print("$ <kbd>{s}</kbd>\n", .{std.mem.trimLeft(u8, line[1..], " ")});
+            try out.print(start_line ++ "$ <kbd>{s}</kbd>" ++ end_line ++ "\n", .{std.mem.trimLeft(u8, line[1..], " ")});
         } else if (!cmd_cont and line.len > 1 and mem.eql(u8, line[0..2], "$ ") and line[line.len - 1] == '\\') {
-            try out.print("$ <kbd>{s}\n", .{std.mem.trimLeft(u8, line[1..], " ")});
+            try out.print(start_line ++ "$ <kbd>{s}" ++ end_line ++ "\n", .{std.mem.trimLeft(u8, line[1..], " ")});
             cmd_cont = true;
         } else if (line.len > 0 and line[line.len - 1] != '\\' and cmd_cont) {
-            try out.print("{s}</kbd>\n", .{line});
+            try out.print(start_line ++ "{s}</kbd>" ++ end_line ++ "\n", .{line});
             cmd_cont = false;
         } else {
-            try out.print("{s}\n", .{line});
+            try out.print(start_line ++ "{s}" ++ end_line ++ "\n", .{line});
         }
     }
 
doc/langref.html.in
@@ -274,6 +274,19 @@
         color: #fff;
       }
     }
+
+    pre {
+      counter-reset: line;
+    }
+    pre span.line:before {
+      counter-increment: line;
+      content: counter(line);
+      display: inline-block;
+      padding-right: 1em;
+      width: 2em;
+      text-align: right;
+      color: #999;
+    }
   </style>
 </head>
 <body>