fd81dd0a7889fb72292a9e74cccede7f5255faef galt Sat Feb 25 17:49:20 2017 -0800 adding SVG self-closing tag capability to htmlCheck. diff --git src/lib/htmlPage.c src/lib/htmlPage.c index a4a300a..e496736 100644 --- src/lib/htmlPage.c +++ src/lib/htmlPage.c @@ -478,30 +478,43 @@ } char *htmlTagAttributeNeeded(struct htmlPage *page, struct htmlTag *tag, char *name) /* Return named tag attribute. Complain and return "n/a" if it * doesn't exist. */ { char *val = htmlTagAttributeVal(page, tag, name, NULL); if (val == NULL) { tagWarn(page, tag, "Missing %s attribute", name); val = "n/a"; } return val; } +boolean isSelfClosingTag(struct htmlTag *tag) +/* Return strue if last attributes' name is "/" + * Self-closing tags are used with html5 and SGV */ +{ +struct htmlAttribute *att = tag->attributes; +if (!att) + return FALSE; +while (att->next) att = att->next; +if (sameString(att->name,"/")) + return TRUE; +return FALSE; +} + static struct htmlTag *htmlTagScan(char *html, char *dupe) /* Scan HTML for tags and return a list of them. * Html is the text to scan, and dupe is a copy of it * which this routine will insert 0's in in the course of * parsing.*/ { char *s = dupe, c, *e, *tagName; struct htmlTag *tagList = NULL, *tag; struct htmlAttribute *att; int pos; for (;;) { c = *s++; if (c == 0) @@ -1677,30 +1690,42 @@ "BASE", "BR", "COL", "COMMAND", "EMBED", "FRAME", // not in html5 "HR", "IMG", "INPUT", "LINK", "META", "PARAM", "SOURCE" }; +static char *selfClosers[] = +/* Tags which can be optionally self-closing in html5 or SVG. */ +{ +"CIRCLE", // SVG +"ELLIPSE", // SVG +"LINE", // SVG +"PATH", // SVG +"POLYGON", // SVG +"POLYLINE", // SVG +"RECT" // SVG +}; + static struct htmlTag *validateBody(struct htmlPage *page, struct htmlTag *startTag) /* Go through tags from current position (just past ) * up to and including and check some things. */ { struct htmlTag *tag, *endTag = NULL; /* First search for end tag. */ for (tag = startTag; tag != NULL; tag = tag->next) { if (sameWord(tag->name, "/BODY")) { endTag = tag; break; } } @@ -1884,57 +1909,66 @@ if (tag == NULL || !sameWord(tag->name, "/HTML")) errAbort("Missing "); validateCgiUrls(page); } } void htmlPageStrictTagNestCheck(struct htmlPage *page) /* Do strict tag nesting check. Aborts if there is a problem. */ { struct htmlTag *tag; /* To simplify things upper case all tag names. */ for (tag = page->tags; tag != NULL; tag = tag->next) touppers(tag->name); /* Add singleton tags to hash. */ -struct hash *hash = hashNew(8); +struct hash *singleTonHash = hashNew(8); int i; -int nesterCount=ArraySize(singleTons); -for (i=0; itags; tag != NULL; tag = tag->next) { if (startsWith("/", tag->name)) { - if (hashLookup(hash, tag->name+1)) + if (hashLookup(singleTonHash, tag->name+1)) tagAbort(page, tag, "Tag %s closing tag not allowed for singleton tags.", tag->name); if (!sameString("P", tag->name+1)) { if (!tagStack) tagAbort(page, tag, "No tags still left on stack. Closing tag %s has no corresponding open tag.", tag->name); struct slName *top = slPopHead(&tagStack); // flush LI tags still on stack when /UL or /OL encountered // since the missing /LI tags are usually tolerated. while ((sameString(tag->name, "/UL") || sameString(tag->name, "/OL")) && sameString(top->name,"LI")) { tagWarn(page, tag, "Closing tag %s found. LI tag on stack. Missing /LI tag. Please fix. Continuing.", tag->name); top = slPopHead(&tagStack); } if (!sameString(top->name,tag->name+1)) { tagAbort(page, tag, "Closing tag %s found, tag %s at top of stack.", tag->name, top->name); } } } else { - if (!hashLookup(hash, tag->name) && !sameString("P", tag->name)) + if ( + ! hashLookup(singleTonHash, tag->name) + && !(hashLookup(selfCloserHash, tag->name) && isSelfClosingTag(tag)) + && ! sameString("P", tag->name)) { slAddHead(&tagStack, slNameNew(tag->name)); } } } if (tagStack) errAbort("Some tags still left on stack. Open tag %s missing its closing tag.", tagStack->name); }