feat(codegen): reject reserved custom element tags
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
5fc370b691
commit
799317b788
4 changed files with 65 additions and 1 deletions
|
|
@ -7,6 +7,16 @@ import (
|
|||
)
|
||||
|
||||
var canonicalSlotOrder = []string{"H", "L", "C", "R", "F"}
|
||||
var reservedCustomElementTags = map[string]struct{}{
|
||||
"annotation-xml": {},
|
||||
"color-profile": {},
|
||||
"font-face": {},
|
||||
"font-face-src": {},
|
||||
"font-face-uri": {},
|
||||
"font-face-format": {},
|
||||
"font-face-name": {},
|
||||
"missing-glyph": {},
|
||||
}
|
||||
|
||||
// cmd/wasm/components.go: isValidCustomElementTag reports whether tag is a safe
|
||||
// custom element name.
|
||||
|
|
@ -19,6 +29,9 @@ func isValidCustomElementTag(tag string) bool {
|
|||
if tag[0] < 'a' || tag[0] > 'z' {
|
||||
return false
|
||||
}
|
||||
if _, reserved := reservedCustomElementTags[tag]; reserved {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range len(tag) {
|
||||
ch := tag[i]
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ func TestIsValidCustomElementTag(t *testing.T) {
|
|||
{tag: "NavBar", want: false},
|
||||
{tag: "nav", want: false},
|
||||
{tag: "nav_bar", want: false},
|
||||
{tag: "annotation-xml", want: false},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,22 @@ import (
|
|||
|
||||
// isValidCustomElementTag reports whether tag is a safe custom element name.
|
||||
// The generator rejects values that would fail at customElements.define() time.
|
||||
var reservedCustomElementTags = map[string]struct{}{
|
||||
"annotation-xml": {},
|
||||
"color-profile": {},
|
||||
"font-face": {},
|
||||
"font-face-src": {},
|
||||
"font-face-uri": {},
|
||||
"font-face-format": {},
|
||||
"font-face-name": {},
|
||||
"missing-glyph": {},
|
||||
}
|
||||
|
||||
func isReservedCustomElementTag(tag string) bool {
|
||||
_, reserved := reservedCustomElementTags[tag]
|
||||
return reserved
|
||||
}
|
||||
|
||||
func isValidCustomElementTag(tag string) bool {
|
||||
if tag == "" || !strings.Contains(tag, "-") {
|
||||
return false
|
||||
|
|
@ -18,6 +34,9 @@ func isValidCustomElementTag(tag string) bool {
|
|||
if tag[0] < 'a' || tag[0] > 'z' {
|
||||
return false
|
||||
}
|
||||
if isReservedCustomElementTag(tag) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range len(tag) {
|
||||
ch := tag[i]
|
||||
|
|
@ -60,7 +79,11 @@ var wcTemplate = template.Must(template.New("wc").Parse(`class {{.ClassName}} ex
|
|||
// Example: cls, err := GenerateClass("nav-bar", "H")
|
||||
func GenerateClass(tag, slot string) (string, error) {
|
||||
if !isValidCustomElementTag(tag) {
|
||||
return "", log.E("codegen.GenerateClass", "custom element tag must be a lowercase hyphenated name: "+tag, nil)
|
||||
message := "custom element tag must be a lowercase hyphenated name: " + tag
|
||||
if isReservedCustomElementTag(tag) {
|
||||
message = "custom element tag is reserved by the Web Components spec: " + tag
|
||||
}
|
||||
return "", log.E("codegen.GenerateClass", message, nil)
|
||||
}
|
||||
var b strings.Builder
|
||||
err := wcTemplate.Execute(&b, struct {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ func TestGenerateClass_Bad_InvalidTag(t *testing.T) {
|
|||
|
||||
_, err = GenerateClass("nav bar", "C")
|
||||
assert.Error(t, err, "custom element names must reject spaces")
|
||||
|
||||
_, err = GenerateClass("annotation-xml", "C")
|
||||
assert.Error(t, err, "reserved custom element names must be rejected")
|
||||
}
|
||||
|
||||
func TestGenerateRegistration_Good(t *testing.T) {
|
||||
|
|
@ -96,6 +99,16 @@ func TestGenerateBundle_Bad_InvalidSlotKey(t *testing.T) {
|
|||
assert.Contains(t, err.Error(), `"X"`)
|
||||
}
|
||||
|
||||
func TestGenerateBundle_Bad_ReservedTag(t *testing.T) {
|
||||
slots := map[string]string{
|
||||
"H": "annotation-xml",
|
||||
}
|
||||
|
||||
_, err := GenerateBundle(slots)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "reserved")
|
||||
}
|
||||
|
||||
func TestGenerateTypeDefinitions_Good(t *testing.T) {
|
||||
slots := map[string]string{
|
||||
"H": "nav-bar",
|
||||
|
|
@ -145,3 +158,17 @@ func TestGenerateTypeDefinitions_SkipsInvalidTags(t *testing.T) {
|
|||
assert.NotContains(t, dts, "nav bar")
|
||||
assert.Equal(t, 1, strings.Count(dts, "extends HTMLElement"))
|
||||
}
|
||||
|
||||
func TestGenerateTypeDefinitions_SkipsReservedTags(t *testing.T) {
|
||||
slots := map[string]string{
|
||||
"H": "annotation-xml",
|
||||
"C": "nav-bar",
|
||||
}
|
||||
|
||||
dts, err := GenerateTypeDefinitions(slots)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Contains(t, dts, `"nav-bar": NavBar;`)
|
||||
assert.NotContains(t, dts, "annotation-xml")
|
||||
assert.Equal(t, 1, strings.Count(dts, "extends HTMLElement"))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue