1- use oxvg_ast:: {
2- arena:: Allocator ,
3- node:: Ref ,
4- serialize:: { Node , PrinterOptions , ToValue } ,
5- } ;
6- use oxvg_collections:: {
7- atom:: Atom ,
8- attribute:: {
9- core_attrs:: Integer ,
10- list_of:: { ListOf , SpaceOrComma } ,
11- } ,
12- } ;
1+ use oxvg_ast:: { arena:: Allocator , node:: Ref , serialize:: Node } ;
2+ use oxvg_collections:: atom:: Atom ;
133
14- use oxvg_parse:: Parse ;
154#[ cfg( feature = "wasm" ) ]
165use tsify:: Tsify ;
176
7+ mod state;
8+
189use crate :: {
1910 error:: Error ,
20- state:: { DerivedState , State , StateElement } ,
21- utils:: create_oxvg_attr,
11+ state:: { DerivedState , State } ,
2212} ;
2313
2414/// An actor holds a reference to a document to act upon.
@@ -38,16 +28,28 @@ pub struct Actor<'input, 'arena> {
3828#[ derive( Debug , Clone ) ]
3929/// An action is a method that an actor can execute upon a document
4030pub enum Action < ' input > {
31+ /// See [`Actor::forget`]
32+ Forget ,
4133 /// See [`Actor::select`]
4234 Select ( Atom < ' input > ) ,
35+ /// See [`Actor::select_more`]
36+ SelectMore ( Atom < ' input > ) ,
37+ /// See [`Actor::deselect`]
38+ Deselect ,
4339}
4440
4541#[ cfg( feature = "napi" ) ]
4642#[ napi]
4743/// An action is a method that an actor can execute upon a document
4844pub enum ActionNapi {
45+ /// See [`Actor::forget`]
46+ Forget ,
4947 /// See [`Actor::select`]
5048 Select ( String ) ,
49+ /// See [`Actor::select_more`]
50+ SelectMore ( String ) ,
51+ /// See [`Actor::deselect`]
52+ Deselect ,
5153}
5254
5355impl < ' input , ' arena > Actor < ' input , ' arena > {
@@ -96,97 +98,11 @@ impl<'input, 'arena> Actor<'input, 'arena> {
9698 /// When the associated action fails
9799 pub fn dispatch ( & mut self , action : Action < ' input > ) -> Result < ( ) , Error < ' input > > {
98100 match action {
99- Action :: Select ( query) => self . select ( query. as_str ( ) ) ,
101+ Action :: Forget => self . forget ( ) ,
102+ Action :: Select ( query) => return self . select ( query. as_str ( ) ) ,
103+ Action :: SelectMore ( query) => return self . select_more ( query. as_str ( ) ) ,
104+ Action :: Deselect => self . deselect ( ) ,
100105 }
101- }
102-
103- /// Updates the state of the actor to point to the elements matching the given selector.
104- /// Elements can also be selected by a space/comma separated list of allocation-id
105- /// integers.
106- ///
107- /// # Errors
108- ///
109- /// When root element is missing or the query cannot be parsed.
110- ///
111- /// # Spec
112- ///
113- #[ doc = include_str ! ( "./spec/select.md" ) ]
114- pub fn select ( & mut self , query : & str ) -> Result < ( ) , Error < ' input > > {
115- let Some ( root) = self . root . element ( ) else {
116- return Err ( Error :: NoRootElement ) ;
117- } ;
118- self . state
119- . record ( & Action :: Select ( query. to_string ( ) . into ( ) ) , & self . allocator ) ;
120-
121- let selections: ListOf < Integer , SpaceOrComma > =
122- if query. chars ( ) . next ( ) . is_some_and ( |c| c. is_ascii_digit ( ) ) {
123- ListOf :: parse_string ( query) . map_err ( |err| Error :: ParseError ( err. to_string ( ) ) ) ?
124- } else {
125- let elements = root
126- . select ( query)
127- . map_err ( |_| Error :: InvalidSelector ( query. to_string ( ) ) ) ?;
128-
129- #[ allow( clippy:: cast_possible_wrap) ]
130- let selections: Vec < _ > = elements. map ( |e| e. id ( ) as Integer ) . collect ( ) ;
131-
132- ListOf {
133- list : selections,
134- separator : SpaceOrComma ,
135- }
136- } ;
137- self . state
138- . get_selections ( & self . allocator )
139- . set_attribute ( create_oxvg_attr (
140- StateElement :: SELECTION_IDS ,
141- selections
142- . to_value_string ( PrinterOptions :: default ( ) )
143- . map_err ( |err| Error :: SerializeError ( err. to_string ( ) ) ) ?
144- . into ( ) ,
145- ) ) ;
146- self . state . embed ( self . root ) ?;
147106 Ok ( ( ) )
148107 }
149108}
150-
151- #[ test]
152- fn select_empty ( ) {
153- oxvg_ast:: parse:: roxmltree:: parse (
154- r#"<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100"/>"# ,
155- |root, allocator| {
156- let mut actor = Actor :: new ( root, allocator) . unwrap ( ) ;
157-
158- actor. select ( "svg" ) . unwrap ( ) ;
159- insta:: assert_snapshot!( actor. root. serialize( ) . unwrap( ) ) ;
160-
161- actor. select ( "1" ) . unwrap ( ) ;
162- insta:: assert_snapshot!( actor. root. serialize( ) . unwrap( ) ) ;
163- } ,
164- )
165- . unwrap ( ) ;
166- }
167-
168- #[ test]
169- fn select ( ) {
170- oxvg_ast:: parse:: roxmltree:: parse (
171- r#"<svg xmlns="http://www.w3.org/2000/svg">
172- <g color="black"/>
173- <g color="BLACK"/>
174- <path fill="rgb(64 64 64)"/>
175- <path fill="rgb(64, 64, 64)"/>
176- <path fill="rgb(86.27451%,86.666667%,87.058824%)"/>
177- <path fill="rgb(-255,100,500)"/>
178- </svg>"# ,
179- |root, allocator| {
180- let mut actor = Actor :: new ( root, allocator) . unwrap ( ) ;
181-
182- actor. select ( "path" ) . unwrap ( ) ;
183- insta:: assert_snapshot!( actor. root. serialize( ) . unwrap( ) ) ;
184- insta:: assert_debug_snapshot!( actor. derive_state( ) . unwrap( ) ) ;
185-
186- actor. select ( "7, 9" ) . unwrap ( ) ;
187- insta:: assert_snapshot!( actor. root. serialize( ) . unwrap( ) ) ;
188- insta:: assert_debug_snapshot!( actor. derive_state( ) . unwrap( ) ) ;
189- } ,
190- )
191- . unwrap ( ) ;
192- }
0 commit comments