diff --git a/src/browser/cssom/css_rule.zig b/src/browser/cssom/css_rule.zig new file mode 100644 index 00000000..686f5b00 --- /dev/null +++ b/src/browser/cssom/css_rule.zig @@ -0,0 +1,80 @@ +// 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 CSSStyleDeclaration = @import("css_style_declaration.zig").CSSStyleDeclaration; +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, +}; + +// pub const CSSGroupingRule = struct { +// pub const prototype = *CSSRule; +// list: std.ArrayListUnmanaged(CSSRule), + +// pub fn _insertRule(self: *CSSGroupingRule, rule: []const u8, _index: ?usize, page: *Page) !usize { +// const index = _index orelse 0; +// if (index > self.list.items.len) return error.IndexSizeError; + +// const css_rule: CSSRule = .{ .css_text = rule, .parent_rule = null, .parent_stylesheet = null }; +// try self.list.insert(page.arena, index, css_rule); +// return self.list.items.len; +// } + +// pub fn _deleteRule(self: *CSSGroupingRule, index: usize) !void { +// if (index > self.list.items.len) return error.IndexSizeError; +// _ = self.list.orderedRemove(index); +// } +// }; + +// pub const CSSStyleRule = struct { +// pub const prototype = *CSSGroupingRule; +// selector_text: []const u8, +// style: CSSStyleDeclaration, +// }; + +// pub const CSSFontFaceRule = struct { +// pub const prototype = *CSSRule; +// }; + +// pub const CSSPageRule = struct { +// pub const prototype = *CSSGroupingRule; +// selector_text: []const u8, +// style: CSSStyleDeclaration, +// }; 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..910110db --- /dev/null +++ b/src/browser/cssom/css_stylesheet.zig @@ -0,0 +1,84 @@ +// 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 CSSRule = @import("css_rule.zig").CSSRule; +const CSSImportRule = @import("css_rule.zig").CSSImportRule; + +pub const CSSStyleSheet = struct { + pub const prototype = *StyleSheet; + + // TODO: For now, we won't parse any rules. + css_rules: std.ArrayListUnmanaged([]const u8), + + // TODO: Support owner_rule here. + + const CSSStyleSheetOpts = struct { + base_url: ?[]const u8, + // TODO: Suupport media + disabled: bool = false, + }; + + pub fn constructor(_opts: ?CSSStyleSheetOpts) CSSStyleSheet { + const opts = _opts orelse CSSStyleSheetOpts{}; + _ = opts; + + return .{ .css_rules = .empty, .owner_rule = null }; + } + + pub fn get_ownerRule(_: *CSSStyleSheet) ?*CSSImportRule { + return null; + } + + pub fn get_cssRules(self: *CSSStyleSheet) *std.ArrayListUnmanaged([]const u8) { + 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.items.len) { + return error.IndexSize; + } + + const arena = page.arena; + try self.css_rules.insert(arena, index, arena.dupe(u8, rule)); + return index; + } + + pub fn _deleteRule(self: *CSSStyleSheet, index: usize) !void { + if (index > self.css_rules.items.len) { + return error.IndexSize; + } + + _ = self.css_rules.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()", "" }, + }, .{}); +} diff --git a/src/browser/cssom/cssom.zig b/src/browser/cssom/cssom.zig new file mode 100644 index 00000000..6635430e --- /dev/null +++ b/src/browser/cssom/cssom.zig @@ -0,0 +1,28 @@ +// 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 Interfaces = .{ + Stylesheet, + CSSStylesheet, + CSSStyleDeclaration, + @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..61fc4d40 --- /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, + href: []const u8, + owner_node: *parser.Node, + parent_stylesheet: ?*StyleSheet, + title: []const u8, + type: []const u8, + + pub fn get_disabled(self: *StyleSheet) bool { + return self.disabled; + } + + pub fn get_href(self: *StyleSheet) []const u8 { + return self.href; + } + + // TODO: media + + pub fn get_ownerNode(self: *StyleSheet) *parser.Node { + return self.owner_node; + } + + pub fn get_parentStyleSheet(self: *StyleSheet) ?*StyleSheet { + return self.parent_stylesheet; + } + + pub fn get_title(self: *StyleSheet) []const u8 { + return self.title; + } + + pub fn get_type(self: *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,