mirror of
https://github.com/ziex-dev/ziex.git
synced 2026-07-20 02:29:36 -06:00
refactor: camel to snake for generated events
This commit is contained in:
parent
3ead4a7f58
commit
26f8b93475
@ -43,9 +43,9 @@ fn onclick(ctx: *zx.client.Event.Stateful) void {
|
||||
const data = ctx.data(.mousedown, zx.allocator);
|
||||
zx.log.info("event: type={s} at ({d},{d}) on <{s}>", .{
|
||||
data.type,
|
||||
data.clientX,
|
||||
data.clientY,
|
||||
if (data.target) |target| target.tagName else "unknown",
|
||||
data.client_x,
|
||||
data.client_y,
|
||||
if (data.target) |target| target.tag_name else "unknown",
|
||||
});
|
||||
|
||||
tryonclick(ctx) catch |e| {
|
||||
@ -57,7 +57,7 @@ fn onfocus(ctx: *zx.client.Event.Stateful) void {
|
||||
const data = ctx.data(.focusin, zx.allocator);
|
||||
zx.log.info("focus: type={s} relatedTarget?={any}", .{
|
||||
data.type,
|
||||
data.relatedTarget != null,
|
||||
data.related_target != null,
|
||||
});
|
||||
}
|
||||
|
||||
@ -75,8 +75,8 @@ fn onkeydown(ctx: *zx.client.Event.Stateful) void {
|
||||
zx.log.info("keydown: key={s} code={s} ctrl={any} shift={any}", .{
|
||||
data.key,
|
||||
data.code,
|
||||
data.ctrlKey,
|
||||
data.shiftKey,
|
||||
data.ctrl_key,
|
||||
data.shift_key,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const window = @import("client/window.zig");
|
||||
|
||||
pub const Event = @import("client/Event.zig");
|
||||
pub const events = @import("client/events_generated.zig");
|
||||
pub const events = @import("client/events/generated.zig");
|
||||
pub const jsx = @import("client/jsx.zig");
|
||||
|
||||
// Legacy --- may get removed/renamed
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
const std = @import("std");
|
||||
const zx = @import("../../root.zig");
|
||||
const client = @import("window.zig");
|
||||
const generated_events = @import("events_generated.zig");
|
||||
const generated_events = @import("events/generated.zig");
|
||||
const js = zx.client.js;
|
||||
const reactivity = client.reactivity;
|
||||
|
||||
@ -79,7 +79,8 @@ fn readField(comptime F: type, allocator: Allocator, obj: js.Object, comptime na
|
||||
const finfo = @typeInfo(F);
|
||||
const Child = if (finfo == .optional) finfo.optional.child else F;
|
||||
const child_info = @typeInfo(Child);
|
||||
const raw = obj.value.get(name) catch return null;
|
||||
const js_name = comptime generated_events.jsName(name);
|
||||
const raw = obj.value.get(js_name) catch return null;
|
||||
defer raw.deinit();
|
||||
|
||||
const raw_type = raw.typeOf();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -45,14 +45,15 @@ fn eql(a: []const u8, b: []const u8) bool {
|
||||
|
||||
fn isZigKeyword(name: []const u8) bool {
|
||||
const keywords = [_][]const u8{
|
||||
"addrspace", "align", "allowzero", "and", "anyframe", "anytype",
|
||||
"asm", "async", "await", "break", "callconv", "catch", "comptime",
|
||||
"const", "continue", "defer", "else", "enum", "errdefer", "error",
|
||||
"export", "extern", "fn", "for", "if", "inline", "linksection",
|
||||
"noalias", "noinline", "nosuspend", "opaque", "or", "orelse",
|
||||
"packed", "pub", "resume", "return", "struct", "suspend", "switch",
|
||||
"test", "threadlocal", "try", "union", "unreachable", "usingnamespace",
|
||||
"var", "volatile", "while",
|
||||
"addrspace", "align", "allowzero", "and", "anyframe", "anytype",
|
||||
"asm", "async", "await", "break", "callconv", "catch",
|
||||
"comptime", "const", "continue", "defer", "else", "enum",
|
||||
"errdefer", "error", "export", "extern", "fn", "for",
|
||||
"if", "inline", "linksection", "noalias", "noinline", "nosuspend",
|
||||
"opaque", "or", "orelse", "packed", "pub", "resume",
|
||||
"return", "struct", "suspend", "switch", "test", "threadlocal",
|
||||
"try", "union", "unreachable", "usingnamespace", "var", "volatile",
|
||||
"while",
|
||||
};
|
||||
for (keywords) |keyword| {
|
||||
if (eql(name, keyword)) return true;
|
||||
@ -65,6 +66,32 @@ fn zigIdent(allocator: std.mem.Allocator, name: []const u8) ![]const u8 {
|
||||
return try std.fmt.allocPrint(allocator, "@\"{s}\"", .{name});
|
||||
}
|
||||
|
||||
// Converts a camelCase WebIDL identifier to snake_case for Zig field naming.
|
||||
// Runs of uppercase letters are treated as acronyms, so `blockedURI` → `blocked_uri`
|
||||
// and `newURL` → `new_url`. The original camelCase is preserved separately as the
|
||||
// JS property name to read from the underlying DOM event object.
|
||||
fn camelToSnake(allocator: std.mem.Allocator, name: []const u8) ![]const u8 {
|
||||
var out: std.ArrayListUnmanaged(u8) = .empty;
|
||||
for (name, 0..) |c, i| {
|
||||
const is_upper = c >= 'A' and c <= 'Z';
|
||||
if (is_upper and i > 0) {
|
||||
const prev = name[i - 1];
|
||||
const prev_is_lower = prev >= 'a' and prev <= 'z';
|
||||
const next_is_lower = (i + 1 < name.len) and name[i + 1] >= 'a' and name[i + 1] <= 'z';
|
||||
const prev_is_upper = prev >= 'A' and prev <= 'Z';
|
||||
if (prev_is_lower or (prev_is_upper and next_is_lower)) {
|
||||
try out.append(allocator, '_');
|
||||
}
|
||||
}
|
||||
if (is_upper) {
|
||||
try out.append(allocator, c - 'A' + 'a');
|
||||
} else {
|
||||
try out.append(allocator, c);
|
||||
}
|
||||
}
|
||||
return out.toOwnedSlice(allocator);
|
||||
}
|
||||
|
||||
// A parsed interface: flat list of (name, zig_type) after resolving inheritance.
|
||||
const Interface = struct {
|
||||
name: []const u8,
|
||||
@ -73,6 +100,7 @@ const Interface = struct {
|
||||
|
||||
const Field = struct {
|
||||
name: []const u8,
|
||||
js_name: []const u8,
|
||||
zig_type: []const u8,
|
||||
};
|
||||
};
|
||||
@ -83,10 +111,10 @@ pub fn main() !void {
|
||||
const allocator = gpa.allocator();
|
||||
const source = try generate(allocator);
|
||||
defer allocator.free(source);
|
||||
const file = try std.fs.cwd().createFile("src/runtime/client/events_generated.zig", .{});
|
||||
const file = try std.fs.cwd().createFile("src/runtime/client/events/generated.zig", .{});
|
||||
defer file.close();
|
||||
try file.writeAll(source);
|
||||
std.debug.print("Generated src/runtime/client/events_generated.zig\n", .{});
|
||||
std.debug.print("Generated src/runtime/client/events/generated.zig\n", .{});
|
||||
}
|
||||
|
||||
pub fn generate(allocator: std.mem.Allocator) ![]const u8 {
|
||||
@ -204,14 +232,16 @@ pub fn generate(allocator: std.mem.Allocator) ![]const u8 {
|
||||
\\//!
|
||||
\\//! Provides typed Zig structs for all browser DOM events.
|
||||
\\//! Use with `event.as(events.MouseEvent, allocator)`.
|
||||
\\const std = @import("std");
|
||||
);
|
||||
|
||||
// Emit EventTarget helper struct first
|
||||
// Emit EventTarget helper struct first. Field names are snake_case; the
|
||||
// original camelCase DOM property names are resolved via `jsName` below.
|
||||
try file.addRaw(
|
||||
\\/// Minimal representation of EventTarget/Element for use as a nested field.
|
||||
\\/// Contains the most commonly accessed DOM element properties.
|
||||
\\pub const EventTarget = struct {
|
||||
\\ tagName: []const u8 = "",
|
||||
\\ tag_name: []const u8 = "",
|
||||
\\ id: []const u8 = "",
|
||||
\\ name: []const u8 = "",
|
||||
\\ value: []const u8 = "",
|
||||
@ -221,6 +251,12 @@ pub fn generate(allocator: std.mem.Allocator) ![]const u8 {
|
||||
\\};
|
||||
);
|
||||
|
||||
// Track snake_case → camelCase for every field whose names differ, so that
|
||||
// `Event.as(T, …)` can translate Zig field names back to the JS property
|
||||
// name when reading from the native DOM event object.
|
||||
var js_name_pairs = std.StringHashMap([]const u8).init(a);
|
||||
try js_name_pairs.put("tag_name", "tagName");
|
||||
|
||||
// Emit each interface struct
|
||||
var iface_it = interfaces.iterator();
|
||||
while (iface_it.next()) |iface_entry| {
|
||||
@ -237,6 +273,9 @@ pub fn generate(allocator: std.mem.Allocator) ![]const u8 {
|
||||
break :blk "0";
|
||||
};
|
||||
try container.addField(file.arena.allocator(), "", try zigIdent(file.arena.allocator(), field.name), field.zig_type, default);
|
||||
if (!eql(field.name, field.js_name)) {
|
||||
_ = try js_name_pairs.getOrPutValue(field.name, field.js_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,7 +339,34 @@ pub fn generate(allocator: std.mem.Allocator) ![]const u8 {
|
||||
}
|
||||
}
|
||||
try w.writeAll(" };\n");
|
||||
try w.writeAll("}\n\n");
|
||||
|
||||
// Emit the snake_case → camelCase map used by `Event.as` at runtime to
|
||||
// translate Zig field names back to the original DOM property names.
|
||||
try w.writeAll("/// Maps snake_case Zig field names to their camelCase DOM property names.\n");
|
||||
try w.writeAll("/// Fields whose snake_case equals the DOM name are omitted; callers should\n");
|
||||
try w.writeAll("/// fall back to the original identifier when no mapping is present.\n");
|
||||
try w.writeAll("pub const js_field_names = std.StaticStringMap([]const u8).initComptime(.{\n");
|
||||
var pair_it = js_name_pairs.iterator();
|
||||
// Sort entries for deterministic output.
|
||||
var sorted_keys: std.ArrayListUnmanaged([]const u8) = .empty;
|
||||
while (pair_it.next()) |e| try sorted_keys.append(a, e.key_ptr.*);
|
||||
std.mem.sort([]const u8, sorted_keys.items, {}, struct {
|
||||
fn lt(_: void, l: []const u8, r: []const u8) bool {
|
||||
return std.mem.lessThan(u8, l, r);
|
||||
}
|
||||
}.lt);
|
||||
for (sorted_keys.items) |k| {
|
||||
const v = js_name_pairs.get(k).?;
|
||||
try w.print(" .{{ \"{s}\", \"{s}\" }},\n", .{ k, v });
|
||||
}
|
||||
try w.writeAll("});\n\n");
|
||||
try w.writeAll("/// Resolves the DOM property name for a given Zig field name.\n");
|
||||
try w.writeAll("/// Returns the mapped camelCase identifier, or the input unchanged when none exists.\n");
|
||||
try w.writeAll("pub fn jsName(name: []const u8) []const u8 {\n");
|
||||
try w.writeAll(" return js_field_names.get(name) orelse name;\n");
|
||||
try w.writeAll("}");
|
||||
|
||||
try file.addRaw(try aliases.toOwnedSlice(a));
|
||||
|
||||
return try file.finish();
|
||||
@ -351,7 +417,8 @@ fn resolveInterface(
|
||||
const zig_type = idlToZig(raw_type.string, nullable) orelse continue;
|
||||
|
||||
try seen_names.put(field_name, {});
|
||||
try fields.append(a, .{ .name = field_name, .zig_type = zig_type });
|
||||
const snake = try camelToSnake(a, field_name);
|
||||
try fields.append(a, .{ .name = snake, .js_name = field_name, .zig_type = zig_type });
|
||||
}
|
||||
}
|
||||
current = raw_inheritance.get(iname);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user