diff --git a/src/browser/cssom/css_rule.zig b/src/browser/cssom/css_rule.zig new file mode 100644 index 00000000..857c0a8a --- /dev/null +++ b/src/browser/cssom/css_rule.zig @@ -0,0 +1,42 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); + +const CSSStyleSheet = @import("css_stylesheet.zig").CSSStyleSheet; + +pub const Interfaces = .{ + CSSRule, + CSSImportRule, +}; + +// https://developer.mozilla.org/en-US/docs/Web/API/CSSRule +pub const CSSRule = struct { + css_text: []const u8, + parent_rule: ?*CSSRule = null, + parent_stylesheet: ?*CSSStyleSheet = null, +}; + +pub const CSSImportRule = struct { + pub const prototype = *CSSRule; + href: []const u8, + layer_name: ?[]const u8, + media: void, + style_sheet: CSSStyleSheet, + supports_text: ?[]const u8, +}; diff --git a/src/browser/cssom/css_rule_list.zig b/src/browser/cssom/css_rule_list.zig new file mode 100644 index 00000000..bf5222f2 --- /dev/null +++ b/src/browser/cssom/css_rule_list.zig @@ -0,0 +1,60 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); + +const StyleSheet = @import("stylesheet.zig").StyleSheet; +const CSSRule = @import("css_rule.zig").CSSRule; +const CSSImportRule = @import("css_rule.zig").CSSImportRule; + +pub const CSSRuleList = struct { + list: std.ArrayListUnmanaged([]const u8), + + pub fn constructor() CSSRuleList { + return .{ .list = .empty }; + } + + pub fn _item(self: *CSSRuleList, _index: u32) ?CSSRule { + const index: usize = @intCast(_index); + + if (index > self.list.items.len) { + return null; + } + + // todo: for now, just return null. + // this depends on properly parsing CSSRule + return null; + } + + pub fn get_length(self: *CSSRuleList) u32 { + return @intCast(self.list.items.len); + } +}; + +const testing = @import("../../testing.zig"); +test "Browser.CSS.CSSRuleList" { + var runner = try testing.jsRunner(testing.tracking_allocator, .{}); + defer runner.deinit(); + + try runner.testCases(&.{ + .{ "let list = new CSSRuleList()", "undefined" }, + .{ "list instanceof CSSRuleList", "true" }, + .{ "list.length", "0" }, + .{ "list.item(0)", "null" }, + }, .{}); +} diff --git a/src/browser/cssom/css_style_declaration.zig b/src/browser/cssom/css_style_declaration.zig index 98a9015d..6ec1d880 100644 --- a/src/browser/cssom/css_style_declaration.zig +++ b/src/browser/cssom/css_style_declaration.zig @@ -20,15 +20,9 @@ const std = @import("std"); const CSSParser = @import("./css_parser.zig").CSSParser; const CSSValueAnalyzer = @import("./css_value_analyzer.zig").CSSValueAnalyzer; +const CSSRule = @import("css_rule.zig").CSSRule; const Page = @import("../page.zig").Page; -pub const Interfaces = .{ - CSSStyleDeclaration, - CSSRule, -}; - -const CSSRule = struct {}; - pub const CSSStyleDeclaration = struct { store: std.StringHashMapUnmanaged(Property), order: std.ArrayListUnmanaged([]const u8), diff --git a/src/browser/cssom/css_stylesheet.zig b/src/browser/cssom/css_stylesheet.zig new file mode 100644 index 00000000..bb03d79c --- /dev/null +++ b/src/browser/cssom/css_stylesheet.zig @@ -0,0 +1,91 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const std = @import("std"); + +const Page = @import("../page.zig").Page; +const StyleSheet = @import("stylesheet.zig").StyleSheet; + +const CSSRuleList = @import("css_rule_list.zig").CSSRuleList; +const CSSImportRule = @import("css_rule.zig").CSSImportRule; + +pub const CSSStyleSheet = struct { + pub const prototype = *StyleSheet; + + proto: StyleSheet, + css_rules: CSSRuleList, + owner_rule: ?*CSSImportRule, + + const CSSStyleSheetOpts = struct { + base_url: ?[]const u8 = null, + // TODO: Suupport media + disabled: bool = false, + }; + + pub fn constructor(_opts: ?CSSStyleSheetOpts) !CSSStyleSheet { + const opts = _opts orelse CSSStyleSheetOpts{}; + return .{ + .proto = StyleSheet{ .disabled = opts.disabled }, + .css_rules = .constructor(), + .owner_rule = null, + }; + } + + pub fn get_ownerRule(_: *CSSStyleSheet) ?*CSSImportRule { + return null; + } + + pub fn get_cssRules(self: *CSSStyleSheet) *CSSRuleList { + return &self.css_rules; + } + + pub fn _insertRule(self: *CSSStyleSheet, rule: []const u8, _index: ?usize, page: *Page) !usize { + const index = _index orelse 0; + if (index > self.css_rules.list.items.len) { + return error.IndexSize; + } + + const arena = page.arena; + try self.css_rules.list.insert(arena, index, try arena.dupe(u8, rule)); + return index; + } + + pub fn _deleteRule(self: *CSSStyleSheet, index: usize) !void { + if (index > self.css_rules.list.items.len) { + return error.IndexSize; + } + + _ = self.css_rules.list.orderedRemove(index); + } +}; + +const testing = @import("../../testing.zig"); +test "Browser.CSS.StyleSheet" { + var runner = try testing.jsRunner(testing.tracking_allocator, .{}); + defer runner.deinit(); + + try runner.testCases(&.{ + .{ "let css = new CSSStyleSheet()", "undefined" }, + .{ "css instanceof CSSStyleSheet", "true" }, + .{ "css.cssRules.length", "0" }, + .{ "css.ownerRule", "null" }, + .{ "let index1 = css.insertRule('body { color: red; }', 0)", "undefined" }, + .{ "index1", "0" }, + .{ "css.cssRules.length", "1" }, + }, .{}); +} diff --git a/src/browser/cssom/cssom.zig b/src/browser/cssom/cssom.zig new file mode 100644 index 00000000..ffd2eabb --- /dev/null +++ b/src/browser/cssom/cssom.zig @@ -0,0 +1,30 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +pub const Stylesheet = @import("stylesheet.zig").StyleSheet; +pub const CSSStylesheet = @import("css_stylesheet.zig").CSSStyleSheet; +pub const CSSStyleDeclaration = @import("css_style_declaration.zig").CSSStyleDeclaration; +pub const CSSRuleList = @import("css_rule_list.zig").CSSRuleList; + +pub const Interfaces = .{ + Stylesheet, + CSSStylesheet, + CSSStyleDeclaration, + CSSRuleList, + @import("css_rule.zig").Interfaces, +}; diff --git a/src/browser/cssom/stylesheet.zig b/src/browser/cssom/stylesheet.zig new file mode 100644 index 00000000..7086063c --- /dev/null +++ b/src/browser/cssom/stylesheet.zig @@ -0,0 +1,55 @@ +// Copyright (C) 2023-2024 Lightpanda (Selecy SAS) +// +// Francis Bouvier +// Pierre Tachoire +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +const parser = @import("../netsurf.zig"); + +// https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet#specifications +pub const StyleSheet = struct { + disabled: bool = false, + href: []const u8 = "", + owner_node: ?*parser.Node = null, + parent_stylesheet: ?*StyleSheet = null, + title: []const u8 = "", + type: []const u8 = "text/css", + + pub fn get_disabled(self: *const StyleSheet) bool { + return self.disabled; + } + + pub fn get_href(self: *const StyleSheet) []const u8 { + return self.href; + } + + // TODO: media + + pub fn get_ownerNode(self: *const StyleSheet) ?*parser.Node { + return self.owner_node; + } + + pub fn get_parentStyleSheet(self: *const StyleSheet) ?*StyleSheet { + return self.parent_stylesheet; + } + + pub fn get_title(self: *const StyleSheet) []const u8 { + return self.title; + } + + pub fn get_type(self: *const StyleSheet) []const u8 { + return self.type; + } +}; diff --git a/src/browser/env.zig b/src/browser/env.zig index 806391e5..aa03c9be 100644 --- a/src/browser/env.zig +++ b/src/browser/env.zig @@ -22,7 +22,7 @@ const WebApis = struct { pub const Interfaces = generate.Tuple(.{ @import("crypto/crypto.zig").Crypto, @import("console/console.zig").Console, - @import("cssom/css_style_declaration.zig").Interfaces, + @import("cssom/cssom.zig").Interfaces, @import("dom/dom.zig").Interfaces, @import("encoding/text_encoder.zig").Interfaces, @import("events/event.zig").Interfaces,