github.com/jgarto/itcv@v0.0.0-20180826224514-4eea09c1aa0d/cmd/coreGen/elements.go (about)

     1  package main
     2  
     3  import "fmt"
     4  
     5  type Elem struct {
     6  	// The myitcv.io/react Name of the element - not set directly, taken from
     7  	// the key of the elements map.
     8  	Name string
     9  
    10  	// React is an override for the React name of the element if it is otherwise
    11  	// not equal to the lowercase version of .Name
    12  	React string
    13  
    14  	// Dom is the name used by honnef.co/go/js/dom when referring to the underlying
    15  	// HTML element. Default is HTML{{.Name}}Element
    16  	Dom string
    17  
    18  	// HTML is an override for the HTML 5 spec name of the element if it is otherwise
    19  	// not equal to the lowercase version of .Name
    20  	HTML string
    21  
    22  	// Attributes maps the name of an attribute to the definition of an
    23  	// attribute.
    24  	Attributes map[string]*Attr
    25  
    26  	// NonBasic is true if  honnef.co/go/js/dom does not declare a specific
    27  	// Element type.
    28  	NonBasic bool
    29  
    30  	// Templates lists the attribute templates this element should use as a
    31  	// base.
    32  	Templates []string
    33  
    34  	// NonHTML indicates this element should not automatically inherit the html
    35  	// attribute template
    36  	NonHTML bool
    37  
    38  	// Child indicates this element can take a single child of the provided type.
    39  	// Its use is exclusive with Children. No default value.
    40  	Child string
    41  
    42  	// Children indicates this element can take a multiple children of the provided
    43  	// type. Its use is exclusive with Child. Default is Element.
    44  	Children string
    45  
    46  	// EmptyElement indicates the element may not have any children
    47  	EmptyElement bool
    48  
    49  	// Implements is the list of special interface methods this element implements.
    50  	Implements []string
    51  
    52  	// SkipTests is an override on whether to not generate the boilerplate tests.
    53  	SkipTests bool
    54  }
    55  
    56  func (e *Elem) ChildParam() string {
    57  	if e.Child != "" {
    58  		return "child " + e.Child
    59  	} else if e.Children != "" {
    60  		return "children ..." + e.Children
    61  	}
    62  
    63  	return ""
    64  }
    65  
    66  func (e *Elem) ChildConvert() string {
    67  	if e.Children != "" && e.Children != "Element" {
    68  		return `
    69  var elems []Element
    70  for _, v := range children {
    71  	elems = append(elems, v)
    72  }
    73  		`
    74  	}
    75  
    76  	return ""
    77  }
    78  
    79  func (e *Elem) ChildArg() string {
    80  	if e.Child != "" {
    81  		return "child"
    82  	} else if e.Children != "" {
    83  		if e.Children == "Element" {
    84  			return "children..."
    85  		} else {
    86  			return "elems..."
    87  		}
    88  	}
    89  
    90  	return ""
    91  }
    92  
    93  func (e *Elem) ChildrenReactType() string {
    94  	if e.Children[0] == '*' {
    95  		return "*react." + e.Children[1:]
    96  	}
    97  
    98  	return "react." + e.Children
    99  }
   100  
   101  func (e *Elem) HTMLAttributes() map[string]*Attr {
   102  	res := make(map[string]*Attr)
   103  
   104  	for n, a := range e.Attributes {
   105  		if a.NoHTML || a.NoReact || a.IsEvent || a.Name == "Ref" {
   106  			continue
   107  		}
   108  
   109  		res[n] = a
   110  	}
   111  
   112  	return res
   113  }
   114  
   115  type Attr struct {
   116  	// The myitcv.io/react Name of the attribute - not set directly, taken from
   117  	// the key of the elements map.
   118  	Name string
   119  
   120  	// React is an override for the React name of the attribute if it is otherwise
   121  	// not equal to the lower-initial version of .Name
   122  	React string
   123  
   124  	// HTML is an override for the HTML attribute name if it is otherwise not equal
   125  	// to the lowercase version of .Name
   126  	HTML string
   127  
   128  	// HTMLConvert is a function that must be called on a JSX-parsed value before
   129  	// assignment. Default is nothing.
   130  	HTMLConvert string
   131  
   132  	// Type is an override for the type of the attribute. The zero value implies
   133  	// string
   134  	Type string
   135  
   136  	// OmitEmpty indicates that no attribute should be set on the underlying React
   137  	// element if the zero value of the attribute is set.
   138  	OmitEmpty bool
   139  
   140  	// NoReact indicates that this attribute should not attempt to be mapped directly
   141  	// to an underlying React attribute.
   142  	NoReact bool
   143  
   144  	// NoHTML indicates this attribute does not have an HTML equivalent, and hence
   145  	// should not appear during parsing.
   146  	NoHTML bool
   147  
   148  	// IsEvent indicates that the attribute is an event.
   149  	IsEvent bool
   150  }
   151  
   152  func (a *Attr) Tag() string {
   153  	omitEmpty := ""
   154  	if a.OmitEmpty {
   155  		omitEmpty = ` react:"omitempty"`
   156  	}
   157  	return fmt.Sprintf("`js:\"%v\"%v`", a.React, omitEmpty)
   158  }
   159  
   160  func (a *Attr) HTMLConvertor(s string) string {
   161  	if a.HTMLConvert == "" {
   162  		return s
   163  	}
   164  
   165  	return fmt.Sprintf("%v(%v)", a.HTMLConvert, s)
   166  }
   167  
   168  // templates are the attribute templates to which elements can refer
   169  var templates = map[string]map[string]*Attr{
   170  	"html": {
   171  		"AriaHasPopup":            &Attr{React: "aria-haspopup", Type: "bool", HTML: "aria-haspopup"},
   172  		"AriaExpanded":            &Attr{React: "aria-expanded", Type: "bool", HTML: "aria-expanded"},
   173  		"AriaLabelledBy":          &Attr{React: "aria-labelledby", HTML: "aria-labelledby"},
   174  		"ClassName":               &Attr{HTML: "class"},
   175  		"DangerouslySetInnerHTML": &Attr{Type: "*DangerousInnerHTML", NoHTML: true},
   176  		"DataSet":                 &Attr{Type: "DataSet", NoReact: true},
   177  		"ID":                      &Attr{OmitEmpty: true, React: "id"},
   178  		"Key":                     &Attr{OmitEmpty: true},
   179  		"Ref":                     &Attr{Type: "Ref"},
   180  		"Role":                    &Attr{},
   181  		"Style":                   &Attr{Type: "*CSS", HTMLConvert: "parseCSS"},
   182  
   183  		// Events
   184  		"OnChange": &Attr{Type: "OnChange", IsEvent: true},
   185  		"OnClick":  &Attr{Type: "OnClick", IsEvent: true},
   186  	},
   187  }
   188  
   189  // elements is a map from the Go element name to the definition
   190  var elements = map[string]*Elem{
   191  	"A": &Elem{
   192  		Dom: "HTMLAnchorElement",
   193  		Attributes: map[string]*Attr{
   194  			"Href":   &Attr{},
   195  			"Target": &Attr{},
   196  			"Title":  &Attr{},
   197  		},
   198  	},
   199  	"Abbr": &Elem{
   200  		Dom: "BasicHTMLElement",
   201  	},
   202  	"Article": &Elem{
   203  		Dom: "BasicHTMLElement",
   204  	},
   205  	"Aside": &Elem{
   206  		Dom: "BasicHTMLElement",
   207  	},
   208  	"B": &Elem{
   209  		Dom: "BasicHTMLElement",
   210  	},
   211  	"Br": &Elem{
   212  		Dom: "HTMLBRElement",
   213  	},
   214  	"Button": &Elem{
   215  		Attributes: map[string]*Attr{
   216  			"Type": &Attr{},
   217  		},
   218  	},
   219  	"Caption": &Elem{
   220  		SkipTests: true,
   221  		Dom:       "BasicHTMLElement",
   222  	},
   223  	"Code": &Elem{
   224  		Dom: "BasicHTMLElement",
   225  	},
   226  	"Div": &Elem{},
   227  	"Em": &Elem{
   228  		Dom: "BasicHTMLElement",
   229  	},
   230  	"Footer": &Elem{
   231  		Dom: "BasicHTMLElement",
   232  	},
   233  	"Form": &Elem{},
   234  	"H1": &Elem{
   235  		Dom: "HTMLHeadingElement",
   236  	},
   237  	"H2": &Elem{
   238  		Dom: "HTMLHeadingElement",
   239  	},
   240  	"H3": &Elem{
   241  		Dom: "HTMLHeadingElement",
   242  	},
   243  	"H4": &Elem{
   244  		Dom: "HTMLHeadingElement",
   245  	},
   246  	"H5": &Elem{
   247  		Dom: "HTMLHeadingElement",
   248  	},
   249  	"H6": &Elem{
   250  		Dom: "HTMLHeadingElement",
   251  	},
   252  	"Header": &Elem{
   253  		Dom: "BasicHTMLElement",
   254  	},
   255  	"Hr": &Elem{
   256  		Dom:          "HTMLHRElement",
   257  		EmptyElement: true,
   258  	},
   259  	"I": &Elem{
   260  		Dom: "BasicHTMLElement",
   261  	},
   262  	"IFrame": &Elem{
   263  		Attributes: map[string]*Attr{
   264  			"SrcDoc": &Attr{},
   265  		},
   266  	},
   267  	"Img": &Elem{
   268  		Dom: "HTMLImageElement",
   269  		Attributes: map[string]*Attr{
   270  			"Src": &Attr{},
   271  			"Alt": &Attr{},
   272  		},
   273  	},
   274  	"Input": &Elem{
   275  		Attributes: map[string]*Attr{
   276  			"Placeholder": &Attr{},
   277  			"Type":        &Attr{},
   278  			"Value":       &Attr{},
   279  		},
   280  	},
   281  	"Label": &Elem{
   282  		Attributes: map[string]*Attr{
   283  			"For": &Attr{
   284  				React: "htmlFor",
   285  			},
   286  		},
   287  	},
   288  	"Li": &Elem{
   289  		Dom:        "HTMLLIElement",
   290  		Implements: []string{"RendersLi(*LiElem)"},
   291  	},
   292  	"Main": &Elem{
   293  		Dom: "BasicHTMLElement",
   294  	},
   295  	"Nav": &Elem{
   296  		Dom: "BasicHTMLElement",
   297  	},
   298  	"Option": &Elem{
   299  		Attributes: map[string]*Attr{
   300  			"Value": &Attr{},
   301  		},
   302  	},
   303  	"P": &Elem{
   304  		Dom: "HTMLParagraphElement",
   305  	},
   306  	"Pre": &Elem{},
   307  	"Select": &Elem{
   308  		Attributes: map[string]*Attr{
   309  			"Value": &Attr{},
   310  		},
   311  		Children: "*OptionElem",
   312  	},
   313  	"Span": &Elem{},
   314  	"Strike": &Elem{
   315  		Dom:   "BasicHTMLElement",
   316  		React: "s",
   317  		HTML:  "s",
   318  	},
   319  	"Sup": &Elem{
   320  		Dom: "BasicHTMLElement",
   321  	},
   322  	"Table": &Elem{},
   323  	"Tbody": &Elem{
   324  		SkipTests: true,
   325  		Dom:       "BasicHTMLElement",
   326  	},
   327  	"Td": &Elem{
   328  		SkipTests: true,
   329  		Dom:       "BasicHTMLElement",
   330  	},
   331  	"TextArea": &Elem{
   332  		Attributes: map[string]*Attr{
   333  			"Placeholder": &Attr{},
   334  			"Value":       &Attr{},
   335  		},
   336  	},
   337  	"Th": &Elem{
   338  		SkipTests: true,
   339  		Dom:       "BasicHTMLElement",
   340  	},
   341  	"Thead": &Elem{
   342  		SkipTests: true,
   343  		Dom:       "BasicHTMLElement",
   344  	},
   345  	"Tr": &Elem{
   346  		SkipTests: true,
   347  		Dom:       "BasicHTMLElement",
   348  	},
   349  	"Ul": &Elem{
   350  		Dom:      "HTMLUListElement",
   351  		Children: "RendersLi",
   352  	},
   353  }