mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-15 15:58:57 +00:00
add some skeleton implementations for various CSS WebAPIs
This commit is contained in:
@@ -45,7 +45,7 @@ pub fn root(opts: RootOpts, writer: *std.Io.Writer, page: *Page) !void {
|
||||
}
|
||||
}
|
||||
|
||||
return deep(doc.asNode(), .{.strip = opts.strip}, writer);
|
||||
return deep(doc.asNode(), .{ .strip = opts.strip }, writer);
|
||||
}
|
||||
|
||||
pub fn deep(node: *Node, opts: Opts, writer: *std.Io.Writer) error{WriteFailed}!void {
|
||||
|
||||
@@ -488,9 +488,14 @@ pub const JsApis = flattenTypes(&.{
|
||||
@import("../webapi/collections.zig"),
|
||||
@import("../webapi/Console.zig"),
|
||||
@import("../webapi/Crypto.zig"),
|
||||
@import("../webapi/css/CSSRule.zig"),
|
||||
@import("../webapi/css/CSSRuleList.zig"),
|
||||
@import("../webapi/css/CSSStyleDeclaration.zig"),
|
||||
@import("../webapi/css/CSSStyleRule.zig"),
|
||||
@import("../webapi/css/CSSStyleSheet.zig"),
|
||||
@import("../webapi/css/CSSStyleProperties.zig"),
|
||||
@import("../webapi/css/MediaQueryList.zig"),
|
||||
@import("../webapi/css/StyleSheetList.zig"),
|
||||
@import("../webapi/Document.zig"),
|
||||
@import("../webapi/HTMLDocument.zig"),
|
||||
@import("../webapi/History.zig"),
|
||||
|
||||
207
src/browser/tests/css/stylesheet.html
Normal file
207
src/browser/tests/css/stylesheet.html
Normal file
@@ -0,0 +1,207 @@
|
||||
<!DOCTYPE html>
|
||||
<script src="../testing.js"></script>
|
||||
|
||||
<script id="document_styleSheets">
|
||||
{
|
||||
const sheets = document.styleSheets;
|
||||
testing.expectTrue(sheets !== null);
|
||||
testing.expectEqual(0, sheets.length);
|
||||
|
||||
// Should return same instance
|
||||
const sheets2 = document.styleSheets;
|
||||
testing.expectTrue(sheets === sheets2);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleSheet_basic">
|
||||
{
|
||||
const sheets = document.styleSheets;
|
||||
testing.expectEqual('StyleSheetList', sheets.constructor.name);
|
||||
|
||||
// Test indexed access on empty list
|
||||
testing.expectEqual(undefined, sheets[0]);
|
||||
testing.expectEqual(undefined, sheets[99]);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_basic">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Set single property
|
||||
style.cssText = 'color: red';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual(1, style.length);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_multiple">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Set multiple properties
|
||||
style.cssText = 'color: red; background: blue; margin: 10px';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual('blue', style.getPropertyValue('background'));
|
||||
testing.expectEqual('10px', style.getPropertyValue('margin'));
|
||||
testing.expectEqual(3, style.length);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_important">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Set property with !important
|
||||
style.cssText = 'color: red !important';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual('important', style.getPropertyPriority('color'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_important_multiple">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Mix of important and non-important
|
||||
style.cssText = 'color: red !important; background: blue; margin: 10px !important';
|
||||
testing.expectEqual('important', style.getPropertyPriority('color'));
|
||||
testing.expectEqual('', style.getPropertyPriority('background'));
|
||||
testing.expectEqual('important', style.getPropertyPriority('margin'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_whitespace">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Test whitespace handling
|
||||
style.cssText = ' color : red ; background : blue ';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual('blue', style.getPropertyValue('background'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_trailing_semicolon">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Trailing semicolon should be handled
|
||||
style.cssText = 'color: red;';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual(1, style.length);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_no_semicolon">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Single property without semicolon
|
||||
style.cssText = 'color: red';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual(1, style.length);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_empty_declarations">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Multiple semicolons should be ignored
|
||||
style.cssText = 'color: red;;; background: blue';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual('blue', style.getPropertyValue('background'));
|
||||
testing.expectEqual(2, style.length);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_replace">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Set initial properties
|
||||
style.cssText = 'color: red; background: blue';
|
||||
testing.expectEqual(2, style.length);
|
||||
|
||||
// Replace with new properties
|
||||
style.cssText = 'margin: 10px';
|
||||
testing.expectEqual('', style.getPropertyValue('color'));
|
||||
testing.expectEqual('', style.getPropertyValue('background'));
|
||||
testing.expectEqual('10px', style.getPropertyValue('margin'));
|
||||
testing.expectEqual(1, style.length);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_clear">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
style.cssText = 'color: red; background: blue';
|
||||
testing.expectEqual(2, style.length);
|
||||
|
||||
// Clear all properties
|
||||
style.cssText = '';
|
||||
testing.expectEqual(0, style.length);
|
||||
testing.expectEqual('', style.getPropertyValue('color'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_colon_in_value">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// URL value with colon
|
||||
style.cssText = 'background: url(http://example.com/image.png)';
|
||||
testing.expectEqual('url(http://example.com/image.png)', style.getPropertyValue('background'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_important_whitespace">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Various whitespace around !important
|
||||
style.cssText = 'color: red!important';
|
||||
testing.expectEqual('important', style.getPropertyPriority('color'));
|
||||
|
||||
style.cssText = 'color: red ! important';
|
||||
testing.expectEqual('important', style.getPropertyPriority('color'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_case_insensitive_property">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Property names should be normalized to lowercase
|
||||
style.cssText = 'COLOR: red; BACKGROUND: blue';
|
||||
testing.expectEqual('red', style.getPropertyValue('color'));
|
||||
testing.expectEqual('blue', style.getPropertyValue('background'));
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_exclamation_not_important">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
const style = div.style;
|
||||
|
||||
// Exclamation mark without "important" should be kept in value
|
||||
style.cssText = 'content: "hello!"';
|
||||
testing.expectEqual('"hello!"', style.getPropertyValue('content'));
|
||||
testing.expectEqual('', style.getPropertyPriority('content'));
|
||||
}
|
||||
</script>
|
||||
@@ -31,6 +31,7 @@ const NodeFilter = @import("NodeFilter.zig");
|
||||
const DOMTreeWalker = @import("DOMTreeWalker.zig");
|
||||
const DOMNodeIterator = @import("DOMNodeIterator.zig");
|
||||
const DOMImplementation = @import("DOMImplementation.zig");
|
||||
const StyleSheetList = @import("css/StyleSheetList.zig");
|
||||
|
||||
pub const HTMLDocument = @import("HTMLDocument.zig");
|
||||
|
||||
@@ -43,6 +44,7 @@ _ready_state: ReadyState = .loading,
|
||||
_current_script: ?*Element.Html.Script = null,
|
||||
_elements_by_id: std.StringHashMapUnmanaged(*Element) = .empty,
|
||||
_active_element: ?*Element = null,
|
||||
_style_sheets: ?*StyleSheetList = null,
|
||||
|
||||
pub const Type = union(enum) {
|
||||
generic,
|
||||
@@ -225,6 +227,15 @@ pub fn getActiveElement(self: *Document) ?*Element {
|
||||
return self.getDocumentElement();
|
||||
}
|
||||
|
||||
pub fn getStyleSheets(self: *Document, page: *Page) !*StyleSheetList {
|
||||
if (self._style_sheets) |sheets| {
|
||||
return sheets;
|
||||
}
|
||||
const sheets = try StyleSheetList.init(page);
|
||||
self._style_sheets = sheets;
|
||||
return sheets;
|
||||
}
|
||||
|
||||
const ReadyState = enum {
|
||||
loading,
|
||||
interactive,
|
||||
@@ -253,7 +264,7 @@ pub const JsApi = struct {
|
||||
pub const readyState = bridge.accessor(Document.getReadyState, null, .{});
|
||||
pub const implementation = bridge.accessor(Document.getImplementation, null, .{});
|
||||
pub const activeElement = bridge.accessor(Document.getActiveElement, null, .{});
|
||||
|
||||
pub const styleSheets = bridge.accessor(Document.getStyleSheets, null, .{});
|
||||
pub const createElement = bridge.function(Document.createElement, .{});
|
||||
pub const createElementNS = bridge.function(Document.createElementNS, .{});
|
||||
pub const createDocumentFragment = bridge.function(Document.createDocumentFragment, .{});
|
||||
|
||||
@@ -120,4 +120,3 @@ pub const JsApi = struct {
|
||||
// Methods
|
||||
pub const javaEnabled = bridge.function(Navigator.javaEnabled, .{});
|
||||
};
|
||||
|
||||
|
||||
@@ -243,7 +243,6 @@ pub fn atob(_: *const Window, input: []const u8, page: *Page) ![]const u8 {
|
||||
return decoded;
|
||||
}
|
||||
|
||||
|
||||
const ScheduleOpts = struct {
|
||||
repeat: bool,
|
||||
params: []js.Object,
|
||||
|
||||
90
src/browser/webapi/css/CSSRule.zig
Normal file
90
src/browser/webapi/css/CSSRule.zig
Normal file
@@ -0,0 +1,90 @@
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
|
||||
const CSSRule = @This();
|
||||
|
||||
pub const Type = enum(u16) {
|
||||
style = 1,
|
||||
charset = 2,
|
||||
import = 3,
|
||||
media = 4,
|
||||
font_face = 5,
|
||||
page = 6,
|
||||
keyframes = 7,
|
||||
keyframe = 8,
|
||||
margin = 9,
|
||||
namespace = 10,
|
||||
counter_style = 11,
|
||||
supports = 12,
|
||||
document = 13,
|
||||
font_feature_values = 14,
|
||||
viewport = 15,
|
||||
region_style = 16,
|
||||
};
|
||||
|
||||
_type: Type,
|
||||
|
||||
pub fn init(rule_type: Type, page: *Page) !*CSSRule {
|
||||
return page._factory.create(CSSRule{
|
||||
._type = rule_type,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn getType(self: *const CSSRule) u16 {
|
||||
return @intFromEnum(self._type);
|
||||
}
|
||||
|
||||
pub fn getCssText(self: *const CSSRule, page: *Page) []const u8 {
|
||||
_ = self;
|
||||
_ = page;
|
||||
return "";
|
||||
}
|
||||
|
||||
pub fn setCssText(self: *CSSRule, text: []const u8, page: *Page) !void {
|
||||
_ = self;
|
||||
_ = text;
|
||||
_ = page;
|
||||
}
|
||||
|
||||
pub fn getParentRule(self: *const CSSRule) ?*CSSRule {
|
||||
_ = self;
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn getParentStyleSheet(self: *const CSSRule) ?*CSSRule {
|
||||
_ = self;
|
||||
return null;
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(CSSRule);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "CSSRule";
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
};
|
||||
|
||||
pub const STYLE_RULE = 1;
|
||||
pub const CHARSET_RULE = 2;
|
||||
pub const IMPORT_RULE = 3;
|
||||
pub const MEDIA_RULE = 4;
|
||||
pub const FONT_FACE_RULE = 5;
|
||||
pub const PAGE_RULE = 6;
|
||||
pub const KEYFRAMES_RULE = 7;
|
||||
pub const KEYFRAME_RULE = 8;
|
||||
pub const MARGIN_RULE = 9;
|
||||
pub const NAMESPACE_RULE = 10;
|
||||
pub const COUNTER_STYLE_RULE = 11;
|
||||
pub const SUPPORTS_RULE = 12;
|
||||
pub const DOCUMENT_RULE = 13;
|
||||
pub const FONT_FEATURE_VALUES_RULE = 14;
|
||||
pub const VIEWPORT_RULE = 15;
|
||||
pub const REGION_STYLE_RULE = 16;
|
||||
|
||||
pub const @"type" = bridge.accessor(CSSRule.getType, null, .{});
|
||||
pub const cssText = bridge.accessor(CSSRule.getCssText, CSSRule.setCssText, .{});
|
||||
pub const parentRule = bridge.accessor(CSSRule.getParentRule, null, .{});
|
||||
pub const parentStyleSheet = bridge.accessor(CSSRule.getParentStyleSheet, null, .{});
|
||||
};
|
||||
36
src/browser/webapi/css/CSSRuleList.zig
Normal file
36
src/browser/webapi/css/CSSRuleList.zig
Normal file
@@ -0,0 +1,36 @@
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const CSSRule = @import("CSSRule.zig");
|
||||
|
||||
const CSSRuleList = @This();
|
||||
|
||||
_rules: []*CSSRule = &.{},
|
||||
|
||||
pub fn init(page: *Page) !*CSSRuleList {
|
||||
return page._factory.create(CSSRuleList{});
|
||||
}
|
||||
|
||||
pub fn length(self: *const CSSRuleList) u32 {
|
||||
return @intCast(self._rules.len);
|
||||
}
|
||||
|
||||
pub fn item(self: *const CSSRuleList, index: usize) ?*CSSRule {
|
||||
if (index >= self._rules.len) {
|
||||
return null;
|
||||
}
|
||||
return self._rules[index];
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(CSSRuleList);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "CSSRuleList";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(CSSRuleList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(CSSRuleList.item, .{ .null_as_undefined = true });
|
||||
};
|
||||
@@ -29,28 +29,6 @@ const CSSStyleDeclaration = @This();
|
||||
_element: ?*Element = null,
|
||||
_properties: std.DoublyLinkedList = .{},
|
||||
|
||||
pub const Property = struct {
|
||||
_name: String,
|
||||
_value: String,
|
||||
_important: bool = false,
|
||||
_node: std.DoublyLinkedList.Node,
|
||||
|
||||
fn fromNodeLink(n: *std.DoublyLinkedList.Node) *Property {
|
||||
return @alignCast(@fieldParentPtr("_node", n));
|
||||
}
|
||||
|
||||
pub fn format(self: *const Property, writer: *std.Io.Writer) !void {
|
||||
try self._name.format(writer);
|
||||
try writer.writeAll(": ");
|
||||
try self._value.format(writer);
|
||||
|
||||
if (self._important) {
|
||||
try writer.writeAll(" !important");
|
||||
}
|
||||
try writer.writeByte(';');
|
||||
}
|
||||
};
|
||||
|
||||
pub fn init(element: ?*Element, page: *Page) !*CSSStyleDeclaration {
|
||||
return page._factory.create(CSSStyleDeclaration{
|
||||
._element = element,
|
||||
@@ -214,6 +192,28 @@ fn normalizePropertyName(name: []const u8, buf: []u8) []const u8 {
|
||||
return std.ascii.lowerString(buf, name);
|
||||
}
|
||||
|
||||
pub const Property = struct {
|
||||
_name: String,
|
||||
_value: String,
|
||||
_important: bool = false,
|
||||
_node: std.DoublyLinkedList.Node,
|
||||
|
||||
fn fromNodeLink(n: *std.DoublyLinkedList.Node) *Property {
|
||||
return @alignCast(@fieldParentPtr("_node", n));
|
||||
}
|
||||
|
||||
pub fn format(self: *const Property, writer: *std.Io.Writer) !void {
|
||||
try self._name.format(writer);
|
||||
try writer.writeAll(": ");
|
||||
try self._value.format(writer);
|
||||
|
||||
if (self._important) {
|
||||
try writer.writeAll(" !important");
|
||||
}
|
||||
try writer.writeByte(';');
|
||||
}
|
||||
};
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(CSSStyleDeclaration);
|
||||
|
||||
|
||||
@@ -72,7 +72,9 @@ fn isKnownCSSProperty(dash_case: []const u8) bool {
|
||||
}
|
||||
|
||||
fn camelCaseToDashCase(name: []const u8, buf: []u8) []const u8 {
|
||||
if (name.len == 0) return name;
|
||||
if (name.len == 0) {
|
||||
return name;
|
||||
}
|
||||
|
||||
// Special case: cssFloat -> float
|
||||
const lower_name = std.ascii.lowerString(buf, name);
|
||||
|
||||
48
src/browser/webapi/css/CSSStyleRule.zig
Normal file
48
src/browser/webapi/css/CSSStyleRule.zig
Normal file
@@ -0,0 +1,48 @@
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const CSSRule = @import("CSSRule.zig");
|
||||
const CSSStyleDeclaration = @import("CSSStyleDeclaration.zig");
|
||||
|
||||
const CSSStyleRule = @This();
|
||||
|
||||
_proto: *CSSRule,
|
||||
_selector_text: []const u8 = "",
|
||||
_style: ?*CSSStyleDeclaration = null,
|
||||
|
||||
pub fn init(page: *Page) !*CSSStyleRule {
|
||||
const rule = try CSSRule.init(.style, page);
|
||||
return page._factory.create(CSSStyleRule{
|
||||
._proto = rule,
|
||||
});
|
||||
}
|
||||
|
||||
pub fn getSelectorText(self: *const CSSStyleRule) []const u8 {
|
||||
return self._selector_text;
|
||||
}
|
||||
|
||||
pub fn setSelectorText(self: *CSSStyleRule, text: []const u8, page: *Page) !void {
|
||||
self._selector_text = try page.dupeString(text);
|
||||
}
|
||||
|
||||
pub fn getStyle(self: *CSSStyleRule, page: *Page) !*CSSStyleDeclaration {
|
||||
if (self._style) |style| {
|
||||
return style;
|
||||
}
|
||||
const style = try CSSStyleDeclaration.init(null, page);
|
||||
self._style = style;
|
||||
return style;
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(CSSStyleRule);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "CSSStyleRule";
|
||||
pub const prototype_chain = bridge.prototypeChain(CSSRule);
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const selectorText = bridge.accessor(CSSStyleRule.getSelectorText, CSSStyleRule.setSelectorText, .{});
|
||||
pub const style = bridge.accessor(CSSStyleRule.getStyle, null, .{});
|
||||
};
|
||||
87
src/browser/webapi/css/CSSStyleSheet.zig
Normal file
87
src/browser/webapi/css/CSSStyleSheet.zig
Normal file
@@ -0,0 +1,87 @@
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const CSSRuleList = @import("CSSRuleList.zig");
|
||||
const CSSRule = @import("CSSRule.zig");
|
||||
|
||||
const CSSStyleSheet = @This();
|
||||
|
||||
_href: ?[]const u8 = null,
|
||||
_title: []const u8 = "",
|
||||
_disabled: bool = false,
|
||||
_css_rules: ?*CSSRuleList = null,
|
||||
_owner_rule: ?*CSSRule = null,
|
||||
|
||||
pub fn init(page: *Page) !*CSSStyleSheet {
|
||||
return page._factory.create(CSSStyleSheet{});
|
||||
}
|
||||
|
||||
pub fn getOwnerNode(self: *const CSSStyleSheet) ?*CSSStyleSheet {
|
||||
_ = self;
|
||||
return null;
|
||||
}
|
||||
|
||||
pub fn getHref(self: *const CSSStyleSheet) ?[]const u8 {
|
||||
return self._href;
|
||||
}
|
||||
|
||||
pub fn getTitle(self: *const CSSStyleSheet) []const u8 {
|
||||
return self._title;
|
||||
}
|
||||
|
||||
pub fn getDisabled(self: *const CSSStyleSheet) bool {
|
||||
return self._disabled;
|
||||
}
|
||||
|
||||
pub fn setDisabled(self: *CSSStyleSheet, disabled: bool) void {
|
||||
self._disabled = disabled;
|
||||
}
|
||||
|
||||
pub fn getCssRules(self: *CSSStyleSheet, page: *Page) !*CSSRuleList {
|
||||
if (self._css_rules) |rules| return rules;
|
||||
const rules = try CSSRuleList.init(page);
|
||||
self._css_rules = rules;
|
||||
return rules;
|
||||
}
|
||||
|
||||
pub fn getOwnerRule(self: *const CSSStyleSheet) ?*CSSRule {
|
||||
return self._owner_rule;
|
||||
}
|
||||
|
||||
pub fn insertRule(self: *CSSStyleSheet, rule: []const u8, index: u32, page: *Page) !u32 {
|
||||
_ = self;
|
||||
_ = rule;
|
||||
_ = index;
|
||||
_ = page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pub fn deleteRule(self: *CSSStyleSheet, index: u32, page: *Page) !void {
|
||||
_ = self;
|
||||
_ = index;
|
||||
_ = page;
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(CSSStyleSheet);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "CSSStyleSheet";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const ownerNode = bridge.accessor(CSSStyleSheet.getOwnerNode, null, .{ .null_as_undefined = true });
|
||||
pub const href = bridge.accessor(CSSStyleSheet.getHref, null, .{ .null_as_undefined = true });
|
||||
pub const title = bridge.accessor(CSSStyleSheet.getTitle, null, .{});
|
||||
pub const disabled = bridge.accessor(CSSStyleSheet.getDisabled, CSSStyleSheet.setDisabled, .{});
|
||||
pub const cssRules = bridge.accessor(CSSStyleSheet.getCssRules, null, .{});
|
||||
pub const ownerRule = bridge.accessor(CSSStyleSheet.getOwnerRule, null, .{ .null_as_undefined = true });
|
||||
pub const insertRule = bridge.function(CSSStyleSheet.insertRule, .{});
|
||||
pub const deleteRule = bridge.function(CSSStyleSheet.deleteRule, .{});
|
||||
};
|
||||
|
||||
const testing = @import("../../../testing.zig");
|
||||
test "WebApi: CSSStyleSheet" {
|
||||
try testing.htmlRunner("css/stylesheet.html", .{});
|
||||
}
|
||||
34
src/browser/webapi/css/StyleSheetList.zig
Normal file
34
src/browser/webapi/css/StyleSheetList.zig
Normal file
@@ -0,0 +1,34 @@
|
||||
const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Page = @import("../../Page.zig");
|
||||
const CSSStyleSheet = @import("CSSStyleSheet.zig");
|
||||
|
||||
const StyleSheetList = @This();
|
||||
|
||||
_sheets: []*CSSStyleSheet = &.{},
|
||||
|
||||
pub fn init(page: *Page) !*StyleSheetList {
|
||||
return page._factory.create(StyleSheetList{});
|
||||
}
|
||||
|
||||
pub fn length(self: *const StyleSheetList) u32 {
|
||||
return @intCast(self._sheets.len);
|
||||
}
|
||||
|
||||
pub fn item(self: *const StyleSheetList, index: usize) ?*CSSStyleSheet {
|
||||
if (index >= self._sheets.len) return null;
|
||||
return self._sheets[index];
|
||||
}
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(StyleSheetList);
|
||||
|
||||
pub const Meta = struct {
|
||||
pub const name = "StyleSheetList";
|
||||
pub const prototype_chain = bridge.prototypeChain();
|
||||
pub var class_id: bridge.ClassId = undefined;
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(StyleSheetList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(StyleSheetList.item, .{ .null_as_undefined = true });
|
||||
};
|
||||
@@ -1454,4 +1454,3 @@ test "Selector: Parser.parseNthPattern" {
|
||||
try testing.expectEqual(" )", parser.input);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ pub fn LogInterceptor(comptime BC: type) type {
|
||||
self.bc.cdp.sendEvent("Log.entryAdded", .{
|
||||
.entry = .{
|
||||
.source = switch (scope) {
|
||||
.js, .console => "javascript",
|
||||
.js, .console => "javascript",
|
||||
.http => "network",
|
||||
.telemetry, .unknown_prop, .interceptor => unreachable, // filtered out in writer above
|
||||
else => "other",
|
||||
|
||||
@@ -184,6 +184,7 @@ pub extern "C" fn html5ever_get_memory_usage() -> Memory {
|
||||
// Streaming parser API
|
||||
// The Parser type from html5ever implements TendrilSink and supports streaming
|
||||
pub struct StreamingParser {
|
||||
#[allow(dead_code)]
|
||||
arena: Box<typed_arena::Arena<sink::ElementData>>,
|
||||
parser: Box<dyn std::any::Any>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user