github.com/MontFerret/ferret@v0.18.0/pkg/drivers/common/setter.go (about)

     1  package common
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/MontFerret/ferret/pkg/drivers"
     7  	"github.com/MontFerret/ferret/pkg/runtime/core"
     8  	"github.com/MontFerret/ferret/pkg/runtime/values"
     9  	"github.com/MontFerret/ferret/pkg/runtime/values/types"
    10  )
    11  
    12  func SetInPage(ctx context.Context, path []core.Value, page drivers.HTMLPage, value core.Value) core.PathError {
    13  	if len(path) == 0 {
    14  		return nil
    15  	}
    16  
    17  	return SetInDocument(ctx, path, page.GetMainFrame(), value)
    18  }
    19  
    20  func SetInDocument(ctx context.Context, path []core.Value, doc drivers.HTMLDocument, value core.Value) core.PathError {
    21  	if len(path) == 0 {
    22  		return nil
    23  	}
    24  
    25  	return SetInNode(ctx, path, doc, value)
    26  }
    27  
    28  func SetInElement(ctx context.Context, path []core.Value, el drivers.HTMLElement, value core.Value) core.PathError {
    29  	if len(path) == 0 {
    30  		return nil
    31  	}
    32  
    33  	segmentIdx := 0
    34  	segment := path[segmentIdx]
    35  
    36  	if segment.Type() == types.String {
    37  		segment := segment.(values.String)
    38  
    39  		switch segment {
    40  		case "attributes":
    41  			if len(path) > 1 {
    42  				attrName := path[1]
    43  				err := el.SetAttribute(ctx, values.NewString(attrName.String()), values.NewString(value.String()))
    44  
    45  				if err != nil {
    46  					return core.NewPathError(err, segmentIdx)
    47  				}
    48  
    49  				return nil
    50  			}
    51  
    52  			err := core.ValidateType(value, types.Object)
    53  
    54  			if err != nil {
    55  				return core.NewPathError(err, segmentIdx)
    56  			}
    57  
    58  			curr, err := el.GetAttributes(ctx)
    59  
    60  			if err != nil {
    61  				return core.NewPathError(err, segmentIdx)
    62  			}
    63  
    64  			// remove all previous attributes
    65  			err = el.RemoveAttribute(ctx, curr.Keys()...)
    66  
    67  			if err != nil {
    68  				return core.NewPathError(err, segmentIdx)
    69  			}
    70  
    71  			obj := value.(*values.Object)
    72  			obj.ForEach(func(value core.Value, key string) bool {
    73  				err = el.SetAttribute(ctx, values.NewString(key), values.NewString(value.String()))
    74  
    75  				return err == nil
    76  			})
    77  
    78  			if err != nil {
    79  				return core.NewPathError(err, segmentIdx)
    80  			}
    81  
    82  			return nil
    83  		case "style":
    84  			if len(path) > 1 {
    85  				attrName := path[1]
    86  
    87  				err := el.SetStyle(ctx, values.NewString(attrName.String()), values.NewString(value.String()))
    88  
    89  				if err != nil {
    90  					return core.NewPathError(err, segmentIdx)
    91  				}
    92  
    93  				return nil
    94  			}
    95  
    96  			err := core.ValidateType(value, types.Object)
    97  
    98  			if err != nil {
    99  				return core.NewPathError(err, segmentIdx)
   100  			}
   101  
   102  			styles, err := el.GetStyles(ctx)
   103  
   104  			if err != nil {
   105  				return core.NewPathError(err, segmentIdx)
   106  			}
   107  
   108  			err = el.RemoveStyle(ctx, styles.Keys()...)
   109  
   110  			obj := value.(*values.Object)
   111  			obj.ForEach(func(value core.Value, key string) bool {
   112  				err = el.SetStyle(ctx, values.NewString(key), values.NewString(value.String()))
   113  
   114  				return err == nil
   115  			})
   116  
   117  			if err != nil {
   118  				return core.NewPathError(err, segmentIdx)
   119  			}
   120  
   121  			return nil
   122  		case "value":
   123  			if len(path) > 1 {
   124  				return core.NewPathError(ErrInvalidPath, segmentIdx+1)
   125  			}
   126  
   127  			err := el.SetValue(ctx, value)
   128  
   129  			if err != nil {
   130  				return core.NewPathError(err, segmentIdx)
   131  			}
   132  
   133  			return nil
   134  		}
   135  	}
   136  
   137  	return SetInNode(ctx, path, el, value)
   138  }
   139  
   140  func SetInNode(_ context.Context, path []core.Value, _ drivers.HTMLNode, _ core.Value) core.PathError {
   141  	if len(path) == 0 {
   142  		return nil
   143  	}
   144  
   145  	return core.NewPathError(ErrReadOnly, 0)
   146  }