diff --git a/README.md b/README.md index 3e82d53..132def8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## REQUIREMENTS: -- zig 0.13.0 +- zig 0.14.0 ## HOW TO EDIT WITH LIVE-PREVIEW & COMMIT DOCS diff --git a/assets/main.wasm b/assets/main.wasm deleted file mode 100644 index c97f31c..0000000 Binary files a/assets/main.wasm and /dev/null differ diff --git a/assets/zml_api.js b/assets/zml_api.js index 7c5cabb..64e56f0 100644 --- a/assets/zml_api.js +++ b/assets/zml_api.js @@ -983,3 +983,4 @@ wasmArray.set(jsArray); } })(); + diff --git a/build.zig b/build.zig index f01cc38..458835b 100644 --- a/build.zig +++ b/build.zig @@ -7,6 +7,11 @@ pub fn build(b: *std.Build) !void { // the zine dev server needs this option!!! const opt_debug = b.option(bool, "debug", "zine debug, unused") orelse true; + const include_drafts = b.option( + bool, + "include-drafts", + "Include drafts in zine output", + ) orelse false; const pcre2_dep = b.dependency("pcre2", .{ .target = target, @@ -15,7 +20,7 @@ pub fn build(b: *std.Build) !void { }); const docs_wasm = try buildDocsWasm(b, optimize); - const website_step, const serve_step = try buildWebSite(b, docs_wasm, opt_debug); + const website_step, const serve_step = try buildWebSite(b, docs_wasm, opt_debug, include_drafts); // has to be run with zig build website _ = website_step; // has to be run with zig build serve @@ -54,7 +59,7 @@ fn buildDocsWasm(b: *std.Build, optimize: std.builtin.OptimizeMode) !*std.Build. return docs_wasm; } -fn buildWebSite(b: *std.Build, docs_wasm: *std.Build.Step.Compile, debug: bool) !struct { +fn buildWebSite(b: *std.Build, docs_wasm: *std.Build.Step.Compile, debug: bool, include_drafts: bool) !struct { *std.Build.Step, *std.Build.Step, } { @@ -107,7 +112,7 @@ fn buildWebSite(b: *std.Build, docs_wasm: *std.Build.Step.Compile, debug: bool) "website", "Builds the website", ); - zine.addWebsite(b, opts, website_step, site); + zine.addWebsite(b, opts, website_step, site, include_drafts); const serve_step = b.step( "serve", diff --git a/build.zig.zon b/build.zig.zon index 57541de..43d978f 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,15 +8,12 @@ // .hash = "1220a59c2cf0e42a6f42cf1bf9b6a6c2691abfd91fcafa0e81a6282c4a197d05c41a", // modified zine - .url = "git+https://github.com/renerocksai/zine#170567737efc5333b38886cfe83211e011267b24", - .hash = "1220ec97928f9e1f1a95ff8c39a943cf6ebab2ff2e6acb1900aeb7844f906b1ce3aa", - - // rene local dev - // .path = "../../renerocksai/zine", + .url = "https://github.com/renerocksai/zine/archive/refs/tags/zig-0.14.0.tar.gz", + .hash = "1220dfe5a9352fc7c9c16b07c5c6d7417fc96ee92dbab5f27b8d4d02400ba5a9f88c", }, .pcre2 = .{ - .url = "https://github.com/renerocksai/pcre2/archive/refs/tags/pcre2-10.45.tar.gz", - .hash = "12207d56c8b27a141c793fc596af11e6eca919efbbcf49b04f7803c603e2f6081b1b", + .url = "https://github.com/renerocksai/pcre2/archive/refs/tags/zig-0.14.tar.gz", + .hash = "12202a2e5043bd8641208b0eb597bc0346fd94fdec5b1ae92ee0096e83d6ff33fc45", }, }, .paths = .{"."}, diff --git a/zig_docs/Decl.zig b/zig_docs/Decl.zig index 4f0d2c3..2546355 100644 --- a/zig_docs/Decl.zig +++ b/zig_docs/Decl.zig @@ -12,9 +12,6 @@ file: Walk.File.Index, /// The decl whose namespace this is in. parent: Index, -/// Delete this to find out where URL escaping needs to be added. -const missing_feature_url_escape = true; - pub const ExtraInfo = struct { is_pub: bool, name: []const u8, @@ -160,16 +157,6 @@ pub fn fqn(decl: *const Decl, out: *std.ArrayListUnmanaged(u8)) Oom!void { } } -threadlocal var _fqn_buf: [1024]u8 = undefined; - -pub fn fqnAsHref(decl: *const Decl, allocator: std.mem.Allocator, out: *std.ArrayListUnmanaged(u8)) Oom!void { - var _fqn = std.ArrayListUnmanaged(u8).fromOwnedSlice(&_fqn_buf); - _fqn.items.len = 0; - try decl.fqn(&_fqn); - - try renderHref(out.writer(allocator), _fqn.items); -} - pub fn reset_with_path(decl: *const Decl, list: *std.ArrayListUnmanaged(u8)) Oom!void { list.clearRetainingCapacity(); try append_path(decl, list); @@ -237,26 +224,3 @@ pub fn find(search_string: []const u8) Decl.Index { } return current_decl_index; } - -/// Replace a fully qualified name from Zig std symbol by an external link. -/// fqn is not allowed to alias to out. -pub fn renderHref(writer: anytype, noalias name: []const u8) !void { - std.log.debug("checking fqn: \"{s}\"", .{name}); - - const std_module = std.mem.indexOf(u8, name, ".std."); - const std_root = if (std.mem.endsWith(u8, name, ".std")) name.len - 4 else null; - - if (std_module orelse std_root) |std_dot_start| { - const std_href = " href=\"https://ziglang.org/documentation/0.13.0/std/#"; - try writer.writeAll(std_href); - _ = missing_feature_url_escape; - try writer.writeAll(name[std_dot_start + 1 ..]); - try writer.writeByte('"'); - std.log.debug("replaced name: \"{s}\" -> {s}{s}", .{ name, std_href, name }); - } else { - try writer.writeAll(" href=\"#"); - _ = missing_feature_url_escape; - try writer.writeAll(name); - try writer.writeByte('"'); - } -} diff --git a/zig_docs/Walk.zig b/zig_docs/Walk.zig index ae924b8..49a5e73 100644 --- a/zig_docs/Walk.zig +++ b/zig_docs/Walk.zig @@ -10,9 +10,9 @@ const Oom = error{OutOfMemory}; pub const Decl = @import("Decl.zig"); -pub var files: std.StringArrayHashMapUnmanaged(File) = .{}; -pub var decls: std.ArrayListUnmanaged(Decl) = .{}; -pub var modules: std.StringArrayHashMapUnmanaged(File.Index) = .{}; +pub var files: std.StringArrayHashMapUnmanaged(File) = .empty; +pub var decls: std.ArrayListUnmanaged(Decl) = .empty; +pub var modules: std.StringArrayHashMapUnmanaged(File.Index) = .empty; file: File.Index, @@ -36,23 +36,23 @@ pub const Category = union(enum(u8)) { /// A function that returns a type. type_function: Ast.Node.Index, - pub const Tag = @typeInfo(Category).Union.tag_type.?; + pub const Tag = @typeInfo(Category).@"union".tag_type.?; }; pub const File = struct { ast: Ast, /// Maps identifiers to the declarations they point to. - ident_decls: std.AutoArrayHashMapUnmanaged(Ast.TokenIndex, Ast.Node.Index) = .{}, + ident_decls: std.AutoArrayHashMapUnmanaged(Ast.TokenIndex, Ast.Node.Index) = .empty, /// Maps field access identifiers to the containing field access node. - token_parents: std.AutoArrayHashMapUnmanaged(Ast.TokenIndex, Ast.Node.Index) = .{}, + token_parents: std.AutoArrayHashMapUnmanaged(Ast.TokenIndex, Ast.Node.Index) = .empty, /// Maps declarations to their global index. - node_decls: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, Decl.Index) = .{}, + node_decls: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, Decl.Index) = .empty, /// Maps function declarations to doctests. - doctests: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, Ast.Node.Index) = .{}, + doctests: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, Ast.Node.Index) = .empty, /// root node => its namespace scope /// struct/union/enum/opaque decl node => its namespace scope /// local var decl node => its local variable scope - scopes: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, *Scope) = .{}, + scopes: std.AutoArrayHashMapUnmanaged(Ast.Node.Index, *Scope) = .empty, pub fn lookup_token(file: *File, token: Ast.TokenIndex) Decl.Index { const decl_node = file.ident_decls.get(token) orelse return .none; @@ -464,8 +464,8 @@ pub const Scope = struct { const Namespace = struct { base: Scope = .{ .tag = .namespace }, parent: *Scope, - names: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .{}, - doctests: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .{}, + names: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .empty, + doctests: std.StringArrayHashMapUnmanaged(Ast.Node.Index) = .empty, decl_index: Decl.Index, }; diff --git a/zig_docs/html_render.zig b/zig_docs/html_render.zig index 684452e..d9cb74f 100644 --- a/zig_docs/html_render.zig +++ b/zig_docs/html_render.zig @@ -8,11 +8,24 @@ const Decl = Walk.Decl; const gpa = std.heap.wasm_allocator; const Oom = error{OutOfMemory}; +/// Delete this to find out where URL escaping needs to be added. +pub const missing_feature_url_escape = true; + pub const RenderSourceOptions = struct { skip_doc_comments: bool = false, skip_comments: bool = false, collapse_whitespace: bool = false, fn_link: Decl.Index = .none, + /// Assumed to be sorted ascending. + source_location_annotations: []const Annotation = &.{}, + /// Concatenated with dom_id. + annotation_prefix: []const u8 = "l", +}; + +pub const Annotation = struct { + file_byte_offset: u32, + /// Concatenated with annotation_prefix. + dom_id: u32, }; pub fn fileSourceHtml( @@ -25,7 +38,7 @@ pub fn fileSourceHtml( const file = file_index.get(); const g = struct { - var field_access_buffer: std.ArrayListUnmanaged(u8) = .{}; + var field_access_buffer: std.ArrayListUnmanaged(u8) = .empty; }; const token_tags = ast.tokens.items(.tag); @@ -48,6 +61,8 @@ pub fn fileSourceHtml( } } + var next_annotate_index: usize = 0; + for ( token_tags[start_token..end_token], token_starts[start_token..end_token], @@ -71,6 +86,18 @@ pub fn fileSourceHtml( if (tag == .eof) break; const slice = ast.tokenSlice(token_index); cursor = start + slice.len; + + // Insert annotations. + while (true) { + if (next_annotate_index >= options.source_location_annotations.len) break; + const next_annotation = options.source_location_annotations[next_annotate_index]; + if (cursor <= next_annotation.file_byte_offset) break; + try out.writer(gpa).print("", .{ + options.annotation_prefix, next_annotation.dom_id, + }); + next_annotate_index += 1; + } + switch (tag) { .eof => unreachable, @@ -159,8 +186,9 @@ pub fn fileSourceHtml( const fn_link = options.fn_link.get(); const fn_token = main_tokens[fn_link.ast_node]; if (token_index == fn_token + 1) { - try out.appendSlice(gpa, ""); try appendEscaped(out, slice); try out.appendSlice(gpa, ""); @@ -193,9 +221,10 @@ pub fn fileSourceHtml( g.field_access_buffer.clearRetainingCapacity(); try walkFieldAccesses(file_index, &g.field_access_buffer, field_access_node); if (g.field_access_buffer.items.len > 0) { - try out.appendSlice(gpa, ""); + try out.appendSlice(gpa, ""); try appendEscaped(out, slice); try out.appendSlice(gpa, ""); } else { @@ -208,9 +237,10 @@ pub fn fileSourceHtml( g.field_access_buffer.clearRetainingCapacity(); try resolveIdentLink(file_index, &g.field_access_buffer, token_index); if (g.field_access_buffer.items.len > 0) { - try out.appendSlice(gpa, ""); + try out.appendSlice(gpa, ""); try appendEscaped(out, slice); try out.appendSlice(gpa, ""); break :i; diff --git a/zig_docs/main.zig b/zig_docs/main.zig index 3e0d19b..0ec2227 100644 --- a/zig_docs/main.zig +++ b/zig_docs/main.zig @@ -9,7 +9,7 @@ const Decl = Walk.Decl; const fileSourceHtml = @import("html_render.zig").fileSourceHtml; const appendEscaped = @import("html_render.zig").appendEscaped; const resolveDeclLink = @import("html_render.zig").resolveDeclLink; -const renderHref = Decl.renderHref; +const missing_feature_url_escape = @import("html_render.zig").missing_feature_url_escape; const gpa = std.heap.wasm_allocator; @@ -60,8 +60,8 @@ export fn unpack(tar_ptr: [*]u8, tar_len: usize) void { }; } -var query_string: std.ArrayListUnmanaged(u8) = .{}; -var query_results: std.ArrayListUnmanaged(Decl.Index) = .{}; +var query_string: std.ArrayListUnmanaged(u8) = .empty; +var query_results: std.ArrayListUnmanaged(Decl.Index) = .empty; /// Resizes the query string to be the correct length; returns the pointer to /// the query string. @@ -93,11 +93,11 @@ fn query_exec_fallible(query: []const u8, ignore_case: bool) !void { segments: u16, }; const g = struct { - var full_path_search_text: std.ArrayListUnmanaged(u8) = .{}; - var full_path_search_text_lower: std.ArrayListUnmanaged(u8) = .{}; - var doc_search_text: std.ArrayListUnmanaged(u8) = .{}; + var full_path_search_text: std.ArrayListUnmanaged(u8) = .empty; + var full_path_search_text_lower: std.ArrayListUnmanaged(u8) = .empty; + var doc_search_text: std.ArrayListUnmanaged(u8) = .empty; /// Each element matches a corresponding query_results element. - var scores: std.ArrayListUnmanaged(Score) = .{}; + var scores: std.ArrayListUnmanaged(Score) = .empty; }; // First element stores the size of the list. @@ -238,8 +238,9 @@ const ErrorIdentifier = packed struct(u64) { try out.appendSlice(gpa, "
"); try out.appendSlice(gpa, name); if (has_link) { - try out.appendSlice(gpa, " "); try out.appendSlice(gpa, decl_index.get().extra_info().name); try out.appendSlice(gpa, ""); @@ -254,8 +255,8 @@ const ErrorIdentifier = packed struct(u64) { } }; -var string_result: std.ArrayListUnmanaged(u8) = .{}; -var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .{}; +var string_result: std.ArrayListUnmanaged(u8) = .empty; +var error_set_result: std.StringArrayHashMapUnmanaged(ErrorIdentifier) = .empty; export fn decl_error_set(decl_index: Decl.Index) Slice(ErrorIdentifier) { return Slice(ErrorIdentifier).init(decl_error_set_fallible(decl_index) catch @panic("OOM")); @@ -380,7 +381,7 @@ export fn decl_params(decl_index: Decl.Index) Slice(Ast.Node.Index) { fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { const g = struct { - var result: std.ArrayListUnmanaged(Ast.Node.Index) = .{}; + var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; }; g.result.clearRetainingCapacity(); const decl = decl_index.get(); @@ -402,7 +403,7 @@ fn decl_fields_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { fn decl_params_fallible(decl_index: Decl.Index) ![]Ast.Node.Index { const g = struct { - var result: std.ArrayListUnmanaged(Ast.Node.Index) = .{}; + var result: std.ArrayListUnmanaged(Ast.Node.Index) = .empty; }; g.result.clearRetainingCapacity(); const decl = decl_index.get(); @@ -671,7 +672,7 @@ fn render_docs( defer parsed_doc.deinit(gpa); const g = struct { - var link_buffer: std.ArrayListUnmanaged(u8) = .{}; + var link_buffer: std.ArrayListUnmanaged(u8) = .empty; }; const Writer = std.ArrayListUnmanaged(u8).Writer; @@ -694,8 +695,9 @@ fn render_docs( g.link_buffer.clearRetainingCapacity(); try resolveDeclLink(resolved_decl_index, &g.link_buffer); - try writer.writeAll("{}", .{markdown.fmtHtml(content)}); } else { try writer.print("{}", .{markdown.fmtHtml(content)}); @@ -815,7 +817,7 @@ export fn find_module_root(pkg: Walk.ModuleIndex) Decl.Index { } /// Set by `set_input_string`. -var input_string: std.ArrayListUnmanaged(u8) = .{}; +var input_string: std.ArrayListUnmanaged(u8) = .empty; export fn set_input_string(len: usize) [*]u8 { input_string.resize(gpa, len) catch @panic("OOM"); @@ -837,7 +839,7 @@ export fn find_decl() Decl.Index { if (result != .none) return result; const g = struct { - var match_fqn: std.ArrayListUnmanaged(u8) = .{}; + var match_fqn: std.ArrayListUnmanaged(u8) = .empty; }; for (Walk.decls.items, 0..) |*decl, decl_index| { g.match_fqn.clearRetainingCapacity(); @@ -886,7 +888,7 @@ export fn type_fn_members(parent: Decl.Index, include_private: bool) Slice(Decl. export fn namespace_members(parent: Decl.Index, include_private: bool) Slice(Decl.Index) { const g = struct { - var members: std.ArrayListUnmanaged(Decl.Index) = .{}; + var members: std.ArrayListUnmanaged(Decl.Index) = .empty; }; g.members.clearRetainingCapacity(); diff --git a/zig_docs/markdown/Document.zig b/zig_docs/markdown/Document.zig index 8eec974..59a4013 100644 --- a/zig_docs/markdown/Document.zig +++ b/zig_docs/markdown/Document.zig @@ -170,7 +170,7 @@ pub fn ExtraData(comptime T: type) type { } pub fn extraData(doc: Document, comptime T: type, index: ExtraIndex) ExtraData(T) { - const fields = @typeInfo(T).Struct.fields; + const fields = @typeInfo(T).@"struct".fields; var i: usize = @intFromEnum(index); var result: T = undefined; inline for (fields) |field| { diff --git a/zig_docs/markdown/Parser.zig b/zig_docs/markdown/Parser.zig index fe4fc2f..1b5f407 100644 --- a/zig_docs/markdown/Parser.zig +++ b/zig_docs/markdown/Parser.zig @@ -31,11 +31,11 @@ const ExtraData = Document.ExtraData; const StringIndex = Document.StringIndex; nodes: Node.List = .{}, -extra: std.ArrayListUnmanaged(u32) = .{}, -scratch_extra: std.ArrayListUnmanaged(u32) = .{}, -string_bytes: std.ArrayListUnmanaged(u8) = .{}, -scratch_string: std.ArrayListUnmanaged(u8) = .{}, -pending_blocks: std.ArrayListUnmanaged(Block) = .{}, +extra: std.ArrayListUnmanaged(u32) = .empty, +scratch_extra: std.ArrayListUnmanaged(u32) = .empty, +string_bytes: std.ArrayListUnmanaged(u8) = .empty, +scratch_string: std.ArrayListUnmanaged(u8) = .empty, +pending_blocks: std.ArrayListUnmanaged(Block) = .empty, allocator: Allocator, const Parser = @This(); @@ -816,7 +816,7 @@ fn isThematicBreak(line: []const u8) bool { } fn closeLastBlock(p: *Parser) !void { - const b = p.pending_blocks.pop(); + const b = p.pending_blocks.pop().?; const node = switch (b.tag) { .list => list: { assert(b.string_start == p.scratch_string.items.len); @@ -928,8 +928,8 @@ const InlineParser = struct { parent: *Parser, content: []const u8, pos: usize = 0, - pending_inlines: std.ArrayListUnmanaged(PendingInline) = .{}, - completed_inlines: std.ArrayListUnmanaged(CompletedInline) = .{}, + pending_inlines: std.ArrayListUnmanaged(PendingInline) = .empty, + completed_inlines: std.ArrayListUnmanaged(CompletedInline) = .empty, const PendingInline = struct { tag: Tag, @@ -1564,7 +1564,7 @@ fn parseInlines(p: *Parser, content: []const u8) !ExtraIndex { } pub fn extraData(p: Parser, comptime T: type, index: ExtraIndex) ExtraData(T) { - const fields = @typeInfo(T).Struct.fields; + const fields = @typeInfo(T).@"struct".fields; var i: usize = @intFromEnum(index); var result: T = undefined; inline for (fields) |field| {