tiny.zen.html
Defined in tiny.zen.
API (9)
Actions
Public operations.
appendAttributeEscapedappendEscapedappendEscapedByteescapedAllocescapedLengthslugslugLengthwriteEscapedwriteSlug
Source
Source: lib/zen/src/html.zig
zig
const std = @import("std");const Allocator = std.mem.Allocator;pub fn appendEscaped(out: *std.ArrayList(u8), allocator: Allocator, value: []const u8) Allocator.Error!void { for (value) |byte| try appendEscapedByte(out, allocator, byte);}pub fn appendAttributeEscaped(out: *std.ArrayList(u8), allocator: Allocator, value: []const u8) Allocator.Error!void { try appendEscaped(out, allocator, value);}pub fn appendEscapedByte(out: *std.ArrayList(u8), allocator: Allocator, byte: u8) Allocator.Error!void { switch (byte) { '&' => try out.appendSlice(allocator, "&"), '<' => try out.appendSlice(allocator, "<"), '>' => try out.appendSlice(allocator, ">"), '"' => try out.appendSlice(allocator, """), '\'' => try out.appendSlice(allocator, "'"), else => try out.append(allocator, byte), }}pub fn escapedLength(value: []const u8) error{CapacityOverflow}!usize { var length: usize = 0; for (value) |byte| { length = std.math.add(usize, length, escapedByteLength(byte)) catch return error.CapacityOverflow; } return length;}pub fn writeEscaped(out: []u8, value: []const u8) []u8 { const length = escapedLength(value) catch unreachable; std.debug.assert(out.len >= length); var index: usize = 0; for (value) |byte| switch (byte) { '&' => copy(out, &index, "&"), '<' => copy(out, &index, "<"), '>' => copy(out, &index, ">"), '"' => copy(out, &index, """), '\'' => copy(out, &index, "'"), else => { out[index] = byte; index += 1; }, }; std.debug.assert(index == length); return out[0..index];}pub fn escapedAlloc(allocator: Allocator, value: []const u8) Allocator.Error![]u8 { var out: std.ArrayList(u8) = .empty; errdefer out.deinit(allocator); try appendEscaped(&out, allocator, value); return try out.toOwnedSlice(allocator);}pub fn slug(allocator: Allocator, value: []const u8) Allocator.Error![]u8 { const out = try allocator.alloc(u8, slugLength(value)); _ = writeSlug(out, value); return out;}pub fn slugLength(value: []const u8) usize { var length: usize = 0; var previous_dash = false; for (value) |byte| { if (isAsciiAlnum(byte)) { length += 1; previous_dash = false; } else if (byte == ' ' or byte == '\t' or byte == '-' or byte == '_') { if (!previous_dash and length != 0) { length += 1; previous_dash = true; } } } if (length != 0 and previous_dash) length -= 1; return if (length == 0) "section".len else length;}pub fn writeSlug(out: []u8, value: []const u8) []u8 { std.debug.assert(out.len >= slugLength(value)); var index: usize = 0; var pending_dash = false; for (value) |byte| { if (isAsciiAlnum(byte)) { if (pending_dash) { out[index] = '-'; index += 1; } out[index] = std.ascii.toLower(byte); index += 1; pending_dash = false; } else if (byte == ' ' or byte == '\t' or byte == '-' or byte == '_') { if (index != 0) pending_dash = true; } } if (index == 0) { @memcpy(out[0.."section".len], "section"); index = "section".len; } std.debug.assert(index == slugLength(value)); return out[0..index];}fn isAsciiAlnum(byte: u8) bool { return (byte >= 'a' and byte <= 'z') or (byte >= 'A' and byte <= 'Z') or (byte >= '0' and byte <= '9');}fn escapedByteLength(byte: u8) usize { return switch (byte) { '&' => "&".len, '<' => "<".len, '>' => ">".len, '"' => """.len, '\'' => "'".len, else => 1, };}fn copy(out: []u8, index: *usize, value: []const u8) void { @memcpy(out[index.*..][0..value.len], value); index.* += value.len;}test "html escaping covers text and attributes" { const escaped = try escapedAlloc(std.testing.allocator, "<a href=\"x&y\">'"); defer std.testing.allocator.free(escaped); try std.testing.expectEqualStrings("<a href="x&y">'", escaped); var exact: [44]u8 = undefined; const written = writeEscaped(&exact, "<a href=\"x&y\">'"); try std.testing.expectEqual(try escapedLength("<a href=\"x&y\">'"), written.len); try std.testing.expectEqualStrings(escaped, written);}test "slug normalizes ascii heading text" { const value = try slug(std.testing.allocator, "Fast, Robust Sites!"); defer std.testing.allocator.free(value); try std.testing.expectEqualStrings("fast-robust-sites", value);}test "slug length and caller storage cover fallback and trailing separators" { var normal: [17]u8 = undefined; try std.testing.expectEqualStrings( "fast-robust-sites", writeSlug(&normal, "Fast, Robust Sites!--"), ); var fallback: [7]u8 = undefined; try std.testing.expectEqualStrings("section", writeSlug(&fallback, "!?")); try std.testing.expectEqual(@as(usize, 7), slugLength("!?"));}Source: lib/zen/src/root.zig:25
zig
/// HTML text and attribute escaping helpers.pub const html = @import("html.zig");Complete caller list for html.appendAttributeEscaped
7 direct callers.
lib.zen.src.code.AnchorCursor.appendForLine[method] — private source atlib/zen/src/code.zig:150in nearest public ownertiny.zen.codetiny.zen.code.render[function] atlib/zen/src/code.zig:31lib.zen.src.markdown.appendContentsItem[function] — private source atlib/zen/src/markdown.zig:857in nearest public ownertiny.zen.markdownlib.zen.src.markdown.appendFootnoteReference[function] — private source atlib/zen/src/markdown.zig:1709in nearest public ownertiny.zen.markdownlib.zen.src.markdown.appendFootnotes[function] — private source atlib/zen/src/markdown.zig:1676in nearest public ownertiny.zen.markdownlib.zen.src.markdown.appendImageAttributes[function] — private source atlib/zen/src/markdown.zig:2622in nearest public ownertiny.zen.markdowntiny.zen.markdown.render[function] atlib/zen/src/markdown.zig:340
Complete caller list for html.appendEscaped
12 direct callers.
tiny.zen.code.render[function] atlib/zen/src/code.zig:31tiny.zen.html.appendAttributeEscaped[function] atlib/zen/src/html.zig:9tiny.zen.html.escapedAlloc[function] atlib/zen/src/html.zig:52lib.zen.src.markdown.appendContents[function] — private source atlib/zen/src/markdown.zig:827in nearest public ownertiny.zen.markdownlib.zen.src.markdown.appendInlineIndexed[function] — private source atlib/zen/src/markdown.zig:1762in nearest public ownertiny.zen.markdownlib.zen.src.markdown.flushFence[function] — private source atlib/zen/src/markdown.zig:672in nearest public ownertiny.zen.markdowntiny.zen.math.mathml.append[function] atlib/zen/src/math/mathml.zig:8lib.zen.src.math.mathml.appendFence[function] — private source atlib/zen/src/math/mathml.zig:116in nearest public ownertiny.zen.math.mathmllib.zen.src.syntax.Highlighter.appendC[method] — private source atlib/zen/src/syntax.zig:84in nearest public ownerlib.zen.src.syntaxlib.zen.src.syntax.Highlighter.appendLine[method] — private source atlib/zen/src/syntax.zig:24in nearest public ownerlib.zen.src.syntaxlib.zen.src.syntax.Highlighter.appendZig[method] — private source atlib/zen/src/syntax.zig:36in nearest public ownerlib.zen.src.syntaxlib.zen.src.syntax.appendToken[function] — private source atlib/zen/src/syntax.zig:178in nearest public ownerlib.zen.src.syntax
Audit
| Definitions | 10 |
|---|---|
| Public names | 10 |
| Members | 0 |
| Version | 26.7.0 |
| Revision | daab053ee433 |