Skip to content

Commit ef9f828

Browse files
authored
Merge pull request #790 from lightpanda-io/css-stylesheet
Minimal CSSStyleSheet
2 parents c691764 + 2c940d4 commit ef9f828

File tree

7 files changed

+280
-8
lines changed

7 files changed

+280
-8
lines changed

src/browser/cssom/css_rule.zig

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
const CSSStyleSheet = @import("css_stylesheet.zig").CSSStyleSheet;
22+
23+
pub const Interfaces = .{
24+
CSSRule,
25+
CSSImportRule,
26+
};
27+
28+
// https://developer.mozilla.org/en-US/docs/Web/API/CSSRule
29+
pub const CSSRule = struct {
30+
css_text: []const u8,
31+
parent_rule: ?*CSSRule = null,
32+
parent_stylesheet: ?*CSSStyleSheet = null,
33+
};
34+
35+
pub const CSSImportRule = struct {
36+
pub const prototype = *CSSRule;
37+
href: []const u8,
38+
layer_name: ?[]const u8,
39+
media: void,
40+
style_sheet: CSSStyleSheet,
41+
supports_text: ?[]const u8,
42+
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
const StyleSheet = @import("stylesheet.zig").StyleSheet;
22+
const CSSRule = @import("css_rule.zig").CSSRule;
23+
const CSSImportRule = @import("css_rule.zig").CSSImportRule;
24+
25+
pub const CSSRuleList = struct {
26+
list: std.ArrayListUnmanaged([]const u8),
27+
28+
pub fn constructor() CSSRuleList {
29+
return .{ .list = .empty };
30+
}
31+
32+
pub fn _item(self: *CSSRuleList, _index: u32) ?CSSRule {
33+
const index: usize = @intCast(_index);
34+
35+
if (index > self.list.items.len) {
36+
return null;
37+
}
38+
39+
// todo: for now, just return null.
40+
// this depends on properly parsing CSSRule
41+
return null;
42+
}
43+
44+
pub fn get_length(self: *CSSRuleList) u32 {
45+
return @intCast(self.list.items.len);
46+
}
47+
};
48+
49+
const testing = @import("../../testing.zig");
50+
test "Browser.CSS.CSSRuleList" {
51+
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
52+
defer runner.deinit();
53+
54+
try runner.testCases(&.{
55+
.{ "let list = new CSSRuleList()", "undefined" },
56+
.{ "list instanceof CSSRuleList", "true" },
57+
.{ "list.length", "0" },
58+
.{ "list.item(0)", "null" },
59+
}, .{});
60+
}

src/browser/cssom/css_style_declaration.zig

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,9 @@ const std = @import("std");
2020

2121
const CSSParser = @import("./css_parser.zig").CSSParser;
2222
const CSSValueAnalyzer = @import("./css_value_analyzer.zig").CSSValueAnalyzer;
23+
const CSSRule = @import("css_rule.zig").CSSRule;
2324
const Page = @import("../page.zig").Page;
2425

25-
pub const Interfaces = .{
26-
CSSStyleDeclaration,
27-
CSSRule,
28-
};
29-
30-
const CSSRule = struct {};
31-
3226
pub const CSSStyleDeclaration = struct {
3327
store: std.StringHashMapUnmanaged(Property),
3428
order: std.ArrayListUnmanaged([]const u8),
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const std = @import("std");
20+
21+
const Page = @import("../page.zig").Page;
22+
const StyleSheet = @import("stylesheet.zig").StyleSheet;
23+
24+
const CSSRuleList = @import("css_rule_list.zig").CSSRuleList;
25+
const CSSImportRule = @import("css_rule.zig").CSSImportRule;
26+
27+
pub const CSSStyleSheet = struct {
28+
pub const prototype = *StyleSheet;
29+
30+
proto: StyleSheet,
31+
css_rules: CSSRuleList,
32+
owner_rule: ?*CSSImportRule,
33+
34+
const CSSStyleSheetOpts = struct {
35+
base_url: ?[]const u8 = null,
36+
// TODO: Suupport media
37+
disabled: bool = false,
38+
};
39+
40+
pub fn constructor(_opts: ?CSSStyleSheetOpts) !CSSStyleSheet {
41+
const opts = _opts orelse CSSStyleSheetOpts{};
42+
return .{
43+
.proto = StyleSheet{ .disabled = opts.disabled },
44+
.css_rules = .constructor(),
45+
.owner_rule = null,
46+
};
47+
}
48+
49+
pub fn get_ownerRule(_: *CSSStyleSheet) ?*CSSImportRule {
50+
return null;
51+
}
52+
53+
pub fn get_cssRules(self: *CSSStyleSheet) *CSSRuleList {
54+
return &self.css_rules;
55+
}
56+
57+
pub fn _insertRule(self: *CSSStyleSheet, rule: []const u8, _index: ?usize, page: *Page) !usize {
58+
const index = _index orelse 0;
59+
if (index > self.css_rules.list.items.len) {
60+
return error.IndexSize;
61+
}
62+
63+
const arena = page.arena;
64+
try self.css_rules.list.insert(arena, index, try arena.dupe(u8, rule));
65+
return index;
66+
}
67+
68+
pub fn _deleteRule(self: *CSSStyleSheet, index: usize) !void {
69+
if (index > self.css_rules.list.items.len) {
70+
return error.IndexSize;
71+
}
72+
73+
_ = self.css_rules.list.orderedRemove(index);
74+
}
75+
};
76+
77+
const testing = @import("../../testing.zig");
78+
test "Browser.CSS.StyleSheet" {
79+
var runner = try testing.jsRunner(testing.tracking_allocator, .{});
80+
defer runner.deinit();
81+
82+
try runner.testCases(&.{
83+
.{ "let css = new CSSStyleSheet()", "undefined" },
84+
.{ "css instanceof CSSStyleSheet", "true" },
85+
.{ "css.cssRules.length", "0" },
86+
.{ "css.ownerRule", "null" },
87+
.{ "let index1 = css.insertRule('body { color: red; }', 0)", "undefined" },
88+
.{ "index1", "0" },
89+
.{ "css.cssRules.length", "1" },
90+
}, .{});
91+
}

src/browser/cssom/cssom.zig

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
pub const Stylesheet = @import("stylesheet.zig").StyleSheet;
20+
pub const CSSStylesheet = @import("css_stylesheet.zig").CSSStyleSheet;
21+
pub const CSSStyleDeclaration = @import("css_style_declaration.zig").CSSStyleDeclaration;
22+
pub const CSSRuleList = @import("css_rule_list.zig").CSSRuleList;
23+
24+
pub const Interfaces = .{
25+
Stylesheet,
26+
CSSStylesheet,
27+
CSSStyleDeclaration,
28+
CSSRuleList,
29+
@import("css_rule.zig").Interfaces,
30+
};

src/browser/cssom/stylesheet.zig

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (C) 2023-2024 Lightpanda (Selecy SAS)
2+
//
3+
// Francis Bouvier <francis@lightpanda.io>
4+
// Pierre Tachoire <pierre@lightpanda.io>
5+
//
6+
// This program is free software: you can redistribute it and/or modify
7+
// it under the terms of the GNU Affero General Public License as
8+
// published by the Free Software Foundation, either version 3 of the
9+
// License, or (at your option) any later version.
10+
//
11+
// This program is distributed in the hope that it will be useful,
12+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
// GNU Affero General Public License for more details.
15+
//
16+
// You should have received a copy of the GNU Affero General Public License
17+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
19+
const parser = @import("../netsurf.zig");
20+
21+
// https://developer.mozilla.org/en-US/docs/Web/API/StyleSheet#specifications
22+
pub const StyleSheet = struct {
23+
disabled: bool = false,
24+
href: []const u8 = "",
25+
owner_node: ?*parser.Node = null,
26+
parent_stylesheet: ?*StyleSheet = null,
27+
title: []const u8 = "",
28+
type: []const u8 = "text/css",
29+
30+
pub fn get_disabled(self: *const StyleSheet) bool {
31+
return self.disabled;
32+
}
33+
34+
pub fn get_href(self: *const StyleSheet) []const u8 {
35+
return self.href;
36+
}
37+
38+
// TODO: media
39+
40+
pub fn get_ownerNode(self: *const StyleSheet) ?*parser.Node {
41+
return self.owner_node;
42+
}
43+
44+
pub fn get_parentStyleSheet(self: *const StyleSheet) ?*StyleSheet {
45+
return self.parent_stylesheet;
46+
}
47+
48+
pub fn get_title(self: *const StyleSheet) []const u8 {
49+
return self.title;
50+
}
51+
52+
pub fn get_type(self: *const StyleSheet) []const u8 {
53+
return self.type;
54+
}
55+
};

src/browser/env.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const WebApis = struct {
2222
pub const Interfaces = generate.Tuple(.{
2323
@import("crypto/crypto.zig").Crypto,
2424
@import("console/console.zig").Console,
25-
@import("cssom/css_style_declaration.zig").Interfaces,
25+
@import("cssom/cssom.zig").Interfaces,
2626
@import("dom/dom.zig").Interfaces,
2727
@import("encoding/text_encoder.zig").Interfaces,
2828
@import("events/event.zig").Interfaces,

0 commit comments

Comments
 (0)