/* localize.c (c) 1998-2001 (W3C) MIT, INRIA, Keio University See tidy.c for the copyright notice. You should only need to edit this file and tidy.c to localize HTML tidy. CVS Info : $Author: terry_teague $ $Date: 2001/12/04 09:54:36 $ $Revision: 1.49 $ */ #include "platform.h" #include "html.h" /* used to point to Web Accessibility Guidelines */ #define ACCESS_URL "http://www.w3.org/WAI/GL" char *release_date = "1st December 2001"; static char *currentFile; /* sasdjb 01May00 for GNU Emacs error parsing */ extern uint optionerrors; /* not used for anything yet */ /* This routine is the single point via which all output is written and as such is a good way to interface Tidy to other code when embedding Tidy in a GUI application. */ void tidy_out(FILE *fp, const char* msg, ...) { va_list args; va_start(args, msg); vfprintf(fp, msg, args); va_end(args); } void ShowVersion(FILE *fp) { /* tidy_out(fp, "HTML Tidy release date: %s\n" "See http://www.w3.org/People/Raggett for details\n", release_date); */ #ifdef PLATFORM_NAME tidy_out(fp, "\nHTML Tidy for %s (release date: %s; built on %s, at %s)\n" "See http://www.w3.org/People/Raggett for details\n", PLATFORM_NAME, release_date, __DATE__, __TIME__); #else tidy_out(fp, "\nHTML Tidy (release date: %s; built on %s, at %s)\n" "See http://www.w3.org/People/Raggett for details\n", release_date, __DATE__, __TIME__); #endif } void FileError(FILE *fp, const char *file) { tidy_out(fp, "Can't open \"%s\"\n", file); } static void ReportTag(Lexer *lexer, Node *tag) { if (tag) { if (tag->type == StartTag || tag->type == StartEndTag) tidy_out(lexer->errout, "<%s>", tag->element); else if (tag->type == EndTag) tidy_out(lexer->errout, "", tag->element); else if (tag->type == DocTypeTag) tidy_out(lexer->errout, ""); else if (tag->type == TextNode) tidy_out(lexer->errout, "plain text"); else tidy_out(lexer->errout, "%s", tag->element); } } /* lexer is not defined when this is called */ void ReportUnknownOption(char *option) { optionerrors++; fprintf(stderr, "Warning - unknown option: %s\n", option); } /* lexer is not defined when this is called */ void ReportBadArgument(char *option) { optionerrors++; fprintf(stderr, "Warning - missing or malformed argument for option: %s\n", option); } static void NtoS(int n, char *str) { char buf[40]; int i; for (i = 0;; ++i) { buf[i] = (n % 10) + '0'; n = n / 10; if (n == 0) break; } n = i; while (i >= 0) { str[n-i] = buf[i]; --i; } str[n+1] = '\0'; } static void ReportPosition(Lexer *lexer) { /* Change formatting to be parsable by GNU Emacs */ if (Emacs) { tidy_out(lexer->errout, "%s", currentFile); tidy_out(lexer->errout, ":%d:", lexer->lines); tidy_out(lexer->errout, "%d: ", lexer->columns); } #ifdef Plan9 else /* plan9 format */ { tidy_out(lexer->errout, "%s", currentFile); tidy_out(lexer->errout, ":%d ", lexer->lines); } #else else /* traditional format */ { tidy_out(lexer->errout, "line %d", lexer->lines); tidy_out(lexer->errout, " column %d - ", lexer->columns); } #endif } void ReportEncodingError(Lexer *lexer, uint code, uint c) { char buf[256]; /* An encoding mismatch is currently treated as a fatal error */ if ((code & ~DISCARDED_CHAR) == ENCODING_MISMATCH) { /* actual encoding passed in "c" */ sprintf(buf, "specified input encoding (%s) does not match actual input encoding (%s)", CharEncodingName(lexer->in->encoding), CharEncodingName(c)); FatalError(buf); } lexer->warnings++; /* keep quiet after errors */ if (lexer->errors > ShowErrors) return; if (ShowWarnings) { ReportPosition(lexer); if ((code & ~DISCARDED_CHAR) == VENDOR_SPECIFIC_CHARS) { NtoS(c, buf); lexer->badChars |= VENDOR_SPECIFIC_CHARS; tidy_out(lexer->errout, "Warning: %s invalid character code %s", code & DISCARDED_CHAR?"discarding":"replacing", buf); } else if ((code & ~DISCARDED_CHAR) == INVALID_SGML_CHARS) { NtoS(c, buf); lexer->badChars |= INVALID_SGML_CHARS; tidy_out(lexer->errout, "Warning: %s invalid character code %s", code & DISCARDED_CHAR?"discarding":"replacing", buf); } else if ((code & ~DISCARDED_CHAR) == INVALID_UTF8) { sprintf(buf, "U+%04lX", c); lexer->badChars |= INVALID_UTF8; tidy_out(lexer->errout, "Warning: %s invalid UTF-8 bytes (char. code %s)", code & DISCARDED_CHAR?"discarding":"replacing", buf); } #if SUPPORT_UTF16_ENCODINGS else if ((code & ~DISCARDED_CHAR) == INVALID_UTF16) { sprintf(buf, "U+%04lX", c); lexer->badChars |= INVALID_UTF16; tidy_out(lexer->errout, "Warning: %s invalid UTF-16 surrogate pair (char. code %s)", code & DISCARDED_CHAR?"discarding":"replacing", buf); } #endif else if ((code & ~DISCARDED_CHAR) == INVALID_NCR) { NtoS(c, buf); lexer->badChars |= INVALID_NCR; tidy_out(lexer->errout, "Warning: %s invalid numeric character reference %s", code & DISCARDED_CHAR?"discarding":"replacing", buf); } tidy_out(lexer->errout, "\n"); } } void ReportEntityError(Lexer *lexer, uint code, char *entity, int c) { /* replacement for #427818 - fix by Tony Goodwin 11 Oct 00 */ char *entityname = "NULL"; if (entity) entityname = entity; lexer->warnings++; /* keep quiet after errors */ if (lexer->errors > ShowErrors) return; if (ShowWarnings) { ReportPosition(lexer); if (code == MISSING_SEMICOLON) { tidy_out(lexer->errout, "Warning: entity \"%s\" doesn't end in ';'", entityname); } if (code == MISSING_SEMICOLON_NCR) { tidy_out(lexer->errout, "Warning: numeric character reference \"%s\" doesn't end in ';'", entityname); } else if (code == UNKNOWN_ENTITY) { tidy_out(lexer->errout, "Warning: unescaped & or unknown entity \"%s\"", entityname); } else if (code == UNESCAPED_AMPERSAND) { tidy_out(lexer->errout, "Warning: unescaped & which should be written as &"); } else if (code == APOS_UNDEFINED) { tidy_out(lexer->errout, "Warning: named entity ' only defined in XML/XHTML"); } tidy_out(lexer->errout, "\n"); } } void ReportAttrError(Lexer *lexer, Node *node, AttVal *av, uint code) { /* replacement for #427676 - fix by Tony Goodwin 11 Oct 00 */ char *name = "NULL", *value = "NULL"; if (av) { if (av->attribute) name = av->attribute; if (av->value) value = av->value; } if (code == UNEXPECTED_GT) lexer->errors++; else lexer->warnings++; /* keep quiet after errors */ if (lexer->errors > ShowErrors) return; if (ShowWarnings) { /* on end of file adjust reported position to end of input */ if (code == UNEXPECTED_END_OF_FILE) { lexer->lines = lexer->in->curline; lexer->columns = lexer->in->curcol; } ReportPosition(lexer); if (code == UNKNOWN_ATTRIBUTE) tidy_out(lexer->errout, "Warning: unknown attribute \"%s\"", name); else if (code == MISSING_ATTRIBUTE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " lacks \"%s\" attribute", name); } else if (code == MISSING_ATTR_VALUE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " attribute \"%s\" lacks value", name); } else if (code == MISSING_IMAGEMAP) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " should use client-side image map"); lexer->badAccess |= MISSING_IMAGE_MAP; } else if (code == BAD_ATTRIBUTE_VALUE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " attribute \"%s\" has invalid value \"%s\"", name, value); } else if (code == XML_ATTRIBUTE_VALUE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " has XML attribute \"%s\"", name); } else if (code == UNEXPECTED_QUOTEMARK) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " unexpected or duplicate quote mark"); } else if (code == MISSING_QUOTEMARK) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " attribute with missing trailing quote mark"); } else if (code == REPEATED_ATTRIBUTE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " dropping value \"%s\" for repeated attribute \"%s\"", value, name); } else if (code == PROPRIETARY_ATTR_VALUE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " proprietary attribute value \"%s\"", value); } else if (code == PROPRIETARY_ATTRIBUTE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " proprietary attribute \"%s\"", name); } else if (code == UNEXPECTED_END_OF_FILE) { tidy_out(lexer->errout, "Warning: end of file while parsing attributes"); } else if (code == ID_NAME_MISMATCH) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " id and name attribute value mismatch"); } else if (code == BACKSLASH_IN_URI) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " URI reference contains backslash. Typo?"); } else if (code == FIXED_BACKSLASH) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " converting backslash in URI to slash"); } else if (code == ILLEGAL_URI_REFERENCE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " improperly escaped URI reference"); } else if (code == ESCAPED_ILLEGAL_URI) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " escaping malformed URI reference"); } else if (code == NEWLINE_IN_URI) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " discarding newline in URI reference"); } else if (code == ANCHOR_NOT_UNIQUE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " Anchor \"%s\" already defined", value); } else if (code == ENTITY_IN_ID) { tidy_out(lexer->errout, "Warning: No entities allowed in id attribute, discarding \"&\""); } else if (code == JOINING_ATTRIBUTE) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " joining values of repeated attribute \"%s\"", name); } else if (code == UNEXPECTED_EQUALSIGN) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " unexpected '=', expected attribute name"); } if ((code != UNEXPECTED_GT)) tidy_out(lexer->errout, "\n"); } if (code == UNEXPECTED_GT) { if (!ShowWarnings) ReportPosition(lexer); tidy_out(lexer->errout, "Error: "); ReportTag(lexer, node); tidy_out(lexer->errout, " missing '>' for end of tag\n"); } } void ReportMissingAttr(Lexer* lexer, Node* node, char* name) { AttVal *dummy = NewAttributeEx(name, null); ReportAttrError(lexer, node, dummy, MISSING_ATTRIBUTE); FreeAttribute(dummy); } void ReportWarning(Lexer *lexer, Node *element, Node *node, uint code) { if ((code == DISCARDING_UNEXPECTED) && lexer->badForm) /* lexer->errors++ */; /* already done in BadForm() */ else lexer->warnings++; /* keep quiet after errors */ if (lexer->errors > ShowErrors) return; if (ShowWarnings) { /* on end of file adjust reported position to end of input */ if (code == UNEXPECTED_END_OF_FILE) { lexer->lines = lexer->in->curline; lexer->columns = lexer->in->curcol; } ReportPosition(lexer); if (code == MISSING_ENDTAG_FOR) tidy_out(lexer->errout, "Warning: missing ", element->element); else if (code == MISSING_ENDTAG_BEFORE) { tidy_out(lexer->errout, "Warning: missing before ", element->element); ReportTag(lexer, node); } else if ((code == DISCARDING_UNEXPECTED) && (lexer->badForm == no)) { /* the case for when this is an error not a warning, is handled later */ tidy_out(lexer->errout, "Warning: discarding unexpected "); ReportTag(lexer, node); } else if (code == NESTED_EMPHASIS) { tidy_out(lexer->errout, "Warning: nested emphasis "); ReportTag(lexer, node); } else if (code == COERCE_TO_ENDTAG) { tidy_out(lexer->errout, "Warning: <%s> is probably intended as ", node->element, node->element); } else if (code == NON_MATCHING_ENDTAG) { tidy_out(lexer->errout, "Warning: replacing unexpected "); ReportTag(lexer, node); tidy_out(lexer->errout, " by ", element->element); } else if (code == TAG_NOT_ALLOWED_IN) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " isn't allowed in <%s> elements", element->element); } else if (code == DOCTYPE_AFTER_TAGS) { tidy_out(lexer->errout, "Warning: isn't allowed after elements"); } else if (code == MISSING_STARTTAG) tidy_out(lexer->errout, "Warning: missing <%s>", node->element); else if (code == UNEXPECTED_ENDTAG) { tidy_out(lexer->errout, "Warning: unexpected ", node->element); if (element) tidy_out(lexer->errout, " in <%s>", element->element); } else if (code == TOO_MANY_ELEMENTS) { tidy_out(lexer->errout, "Warning: too many %s elements", node->element); if (element) tidy_out(lexer->errout, " in <%s>", element->element); } else if (code == USING_BR_INPLACE_OF) { tidy_out(lexer->errout, "Warning: using
in place of "); ReportTag(lexer, node); } else if (code == INSERTING_TAG) tidy_out(lexer->errout, "Warning: inserting implicit <%s>", node->element); else if (code == CANT_BE_NESTED) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " can't be nested"); } else if (code == PROPRIETARY_ELEMENT) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " is not approved by W3C"); if (node->tag == tag_layer) lexer->badLayout |= USING_LAYER; else if (node->tag == tag_spacer) lexer->badLayout |= USING_SPACER; else if (node->tag == tag_nobr) lexer->badLayout |= USING_NOBR; } else if (code == OBSOLETE_ELEMENT) { if (element->tag && (element->tag->model & CM_OBSOLETE)) tidy_out(lexer->errout, "Warning: replacing obsolete element "); else tidy_out(lexer->errout, "Warning: replacing element "); ReportTag(lexer, element); tidy_out(lexer->errout, " by "); ReportTag(lexer, node); } else if (code == UNESCAPED_ELEMENT) { tidy_out(lexer->errout, "Warning: unescaped "); ReportTag(lexer, node); tidy_out(lexer->errout, " in pre content"); } else if (code == TRIM_EMPTY_ELEMENT) { tidy_out(lexer->errout, "Warning: trimming empty "); ReportTag(lexer, element); } else if (code == MISSING_TITLE_ELEMENT) tidy_out(lexer->errout, "Warning: inserting missing 'title' element"); else if (code == ILLEGAL_NESTING) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, element); tidy_out(lexer->errout, " shouldn't be nested"); } else if (code == NOFRAMES_CONTENT) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, node); tidy_out(lexer->errout, " not inside 'noframes' element"); } else if (code == INCONSISTENT_VERSION) { tidy_out(lexer->errout, "Warning: HTML DOCTYPE doesn't match content"); } else if (code == MALFORMED_DOCTYPE) { tidy_out(lexer->errout, "Warning: expected \"html PUBLIC\" or \"html SYSTEM\""); } else if (code == CONTENT_AFTER_BODY) { tidy_out(lexer->errout, "Warning: content occurs after end of body"); } else if (code == MALFORMED_COMMENT) { tidy_out(lexer->errout, "Warning: adjacent hyphens within comment"); } else if (code == BAD_COMMENT_CHARS) { tidy_out(lexer->errout, "Warning: expecting -- or >"); } else if (code == BAD_XML_COMMENT) { tidy_out(lexer->errout, "Warning: XML comments can't contain --"); } else if (code == BAD_CDATA_CONTENT) { tidy_out(lexer->errout, "Warning: '<' + '/' + letter not allowed here"); } else if (code == INCONSISTENT_NAMESPACE) { tidy_out(lexer->errout, "Warning: HTML namespace doesn't match content"); } else if (code == DTYPE_NOT_UPPER_CASE) { tidy_out(lexer->errout, "Warning: SYSTEM, PUBLIC, W3C, DTD, EN must be upper case"); } else if (code == UNEXPECTED_END_OF_FILE) { tidy_out(lexer->errout, "Warning: unexpected end of file"); ReportTag(lexer, element); } else if (code == NESTED_QUOTATION) { tidy_out(lexer->errout, "Warning: nested q elements, possible typo."); } else if (code == ELEMENT_NOT_EMPTY) { tidy_out(lexer->errout, "Warning: "); ReportTag(lexer, element); tidy_out(lexer->errout, " element not empty or not closed"); } if ((code != DISCARDING_UNEXPECTED) || (lexer->badForm == no)) tidy_out(lexer->errout, "\n"); } if ((code == DISCARDING_UNEXPECTED) && lexer->badForm) { /* the case for when this is a warning not an error, is handled earlier */ if (!ShowWarnings) ReportPosition(lexer); tidy_out(lexer->errout, "Error: discarding unexpected "); ReportTag(lexer, node); tidy_out(lexer->errout, "\n"); } } void ReportError(Lexer *lexer, Node *element, Node *node, uint code) { /* lexer->warnings++; */ lexer->errors++; /* keep quiet after errors */ if (lexer->errors > ShowErrors) return; ReportPosition(lexer); if (code == SUSPECTED_MISSING_QUOTE) { tidy_out(lexer->errout, "Error: missing quote mark for attribute value"); } else if (code == DUPLICATE_FRAMESET) { tidy_out(lexer->errout, "Error: repeated FRAMESET element"); } else if (code == UNKNOWN_ELEMENT) { tidy_out(lexer->errout, "Error: "); ReportTag(lexer, node); tidy_out(lexer->errout, " is not recognized!"); } else if (code == UNEXPECTED_ENDTAG) /* generated by XML docs */ { tidy_out(lexer->errout, "Error: unexpected ", node->element); /* #434100 - fix by various */ if (element) tidy_out(lexer->errout, " in <%s>", element->element); } tidy_out(lexer->errout, "\n"); } void ErrorSummary(Lexer *lexer) { /* adjust badAccess to that its null if frames are ok */ if (lexer->badAccess & (USING_FRAMES | USING_NOFRAMES)) { if (!((lexer->badAccess & USING_FRAMES) && !(lexer->badAccess & USING_NOFRAMES))) lexer->badAccess &= ~(USING_FRAMES | USING_NOFRAMES); } if (lexer->badChars) { #if 0 if (lexer->badChars & WINDOWS_CHARS) { tidy_out(lexer->errout, "Characters codes for the Microsoft Windows fonts in the range\n"); tidy_out(lexer->errout, "128 - 159 may not be recognized on other platforms. You are\n"); tidy_out(lexer->errout, "instead recommended to use named entities, e.g. ™ rather\n"); tidy_out(lexer->errout, "than Windows character code 153 (0x2122 in Unicode). Note that\n"); tidy_out(lexer->errout, "as of February 1998 few browsers support the new entities.\n\n"); } #endif if (lexer->badChars & VENDOR_SPECIFIC_CHARS) { tidy_out(lexer->errout, "It is unlikely that vendor-specific, system-dependent encodings\n"); tidy_out(lexer->errout, "work widely enough on the World Wide Web; you should avoid using the \n"); tidy_out(lexer->errout, "%s character encoding, instead you are recommended to\n", (lexer->in->encoding == WIN1252)?"Windows-1252": (lexer->in->encoding == MACROMAN)?"MacRoman":"specified"); tidy_out(lexer->errout, "use named entities, e.g. ™.\n\n"); } if ((lexer->badChars & INVALID_SGML_CHARS) || (lexer->badChars & INVALID_NCR)) { tidy_out(lexer->errout, "Character codes 128 to 159 (U+0080 to U+009F) are not allowed in HTML;\n"); tidy_out(lexer->errout, "even if they were, they would likely be unprintable control characters.\n"); tidy_out(lexer->errout, "Tidy assumed you wanted to refer to a character with the same byte value in the \n"); tidy_out(lexer->errout, "%s encoding and replaced that reference with the Unicode equivalent.\n\n", (ReplacementCharEncoding == WIN1252)?"Windows-1252": (ReplacementCharEncoding == MACROMAN)?"MacRoman":"default"); } if (lexer->badChars & INVALID_UTF8) { tidy_out(lexer->errout, "Character codes for UTF-8 must be in the range: U+0000 to U+10FFFF.\n"); tidy_out(lexer->errout, "The definition of UTF-8 in Annex D of ISO/IEC 10646-1:2000 also\n"); tidy_out(lexer->errout, "allows for the use of five- and six-byte sequences to encode\n"); tidy_out(lexer->errout, "characters that are outside the range of the Unicode character set;\n"); tidy_out(lexer->errout, "those five- and six-byte sequences are illegal for the use of\n"); tidy_out(lexer->errout, "UTF-8 as a transformation of Unicode characters. ISO/IEC 10646\n"); tidy_out(lexer->errout, "does not allow mapping of unpaired surrogates, nor U+FFFE and U+FFFF\n"); tidy_out(lexer->errout, "(but it does allow other noncharacters). For more information please refer to\n"); tidy_out(lexer->errout, "http://www.unicode.org/unicode and http://www.cl.cam.ac.uk/~mgk25/unicode.html\n\n"); } #if SUPPORT_UTF16_ENCODINGS if (lexer->badChars & INVALID_UTF16) { tidy_out(lexer->errout, "Character codes for UTF-16 must be in the range: U+0000 to U+10FFFF.\n"); tidy_out(lexer->errout, "The definition of UTF-16 in Annex C of ISO/IEC 10646-1:2000 does not allow the\n"); tidy_out(lexer->errout, "mapping of unpaired surrogates. For more information please refer to\n"); tidy_out(lexer->errout, "http://www.unicode.org/unicode and http://www.cl.cam.ac.uk/~mgk25/unicode.html\n\n"); } #endif if (lexer->badChars & INVALID_URI) { tidy_out(lexer->errout, "URIs must be properly escaped, they must not contain unescaped\n"); tidy_out(lexer->errout, "characters below U+0021 including the space character and not\n"); tidy_out(lexer->errout, "above U+007E. Tidy escapes the URI for you as recommended by\n"); tidy_out(lexer->errout, "HTML 4.01 section B.2.1 and XML 1.0 section 4.2.2. Some user agents\n"); tidy_out(lexer->errout, "use another algorithm to escape such URIs and some server-sided\n"); tidy_out(lexer->errout, "scripts depend on that. If you want to depend on that, you must\n"); tidy_out(lexer->errout, "escape the URI by your own. For more information please refer to\n"); tidy_out(lexer->errout, "http://www.w3.org/International/O-URL-and-ident.html\n\n"); } } if (lexer->badForm) { tidy_out(lexer->errout, "You may need to move one or both of the
and
\n"); tidy_out(lexer->errout, "tags. HTML elements should be properly nested and form elements\n"); tidy_out(lexer->errout, "are no exception. For instance you should not place the
\n"); tidy_out(lexer->errout, "in one table cell and the
in another. If the
is\n"); tidy_out(lexer->errout, "placed before a table, the
cannot be placed inside the\n"); tidy_out(lexer->errout, "table! Note that one form can't be nested inside another!\n\n"); } if (lexer->badAccess) { if (lexer->badAccess & MISSING_SUMMARY) { tidy_out(lexer->errout, "The table summary attribute should be used to describe\n"); tidy_out(lexer->errout, "the table structure. It is very helpful for people using\n"); tidy_out(lexer->errout, "non-visual browsers. The scope and headers attributes for\n"); tidy_out(lexer->errout, "table cells are useful for specifying which headers apply\n"); tidy_out(lexer->errout, "to each table cell, enabling non-visual browsers to provide\n"); tidy_out(lexer->errout, "a meaningful context for each cell.\n\n"); } if (lexer->badAccess & MISSING_IMAGE_ALT) { tidy_out(lexer->errout, "The alt attribute should be used to give a short description\n"); tidy_out(lexer->errout, "of an image; longer descriptions should be given with the\n"); tidy_out(lexer->errout, "longdesc attribute which takes a URL linked to the description.\n"); tidy_out(lexer->errout, "These measures are needed for people using non-graphical browsers.\n\n"); } if (lexer->badAccess & MISSING_IMAGE_MAP) { tidy_out(lexer->errout, "Use client-side image maps in preference to server-side image\n"); tidy_out(lexer->errout, "maps as the latter are inaccessible to people using non-\n"); tidy_out(lexer->errout, "graphical browsers. In addition, client-side maps are easier\n"); tidy_out(lexer->errout, "to set up and provide immediate feedback to users.\n\n"); } if (lexer->badAccess & MISSING_LINK_ALT) { tidy_out(lexer->errout, "For hypertext links defined using a client-side image map, you\n"); tidy_out(lexer->errout, "need to use the alt attribute to provide a textual description\n"); tidy_out(lexer->errout, "of the link for people using non-graphical browsers.\n\n"); } if ((lexer->badAccess & USING_FRAMES) && !(lexer->badAccess & USING_NOFRAMES)) { tidy_out(lexer->errout, "Pages designed using frames presents problems for\n"); tidy_out(lexer->errout, "people who are either blind or using a browser that\n"); tidy_out(lexer->errout, "doesn't support frames. A frames-based page should always\n"); tidy_out(lexer->errout, "include an alternative layout inside a NOFRAMES element.\n\n"); } tidy_out(lexer->errout, "For further advice on how to make your pages accessible\n"); tidy_out(lexer->errout, "see \"%s\". You may also want to try\n", ACCESS_URL); tidy_out(lexer->errout, "\"http://www.cast.org/bobby/\" which is a free Web-based\n"); tidy_out(lexer->errout, "service for checking URLs for accessibility.\n\n"); } if (lexer->badLayout) { if (lexer->badLayout & USING_LAYER) { tidy_out(lexer->errout, "The Cascading Style Sheets (CSS) Positioning mechanism\n"); tidy_out(lexer->errout, "is recommended in preference to the proprietary \n"); tidy_out(lexer->errout, "element due to limited vendor support for LAYER.\n\n"); } if (lexer->badLayout & USING_SPACER) { tidy_out(lexer->errout, "You are recommended to use CSS for controlling white\n"); tidy_out(lexer->errout, "space (e.g. for indentation, margins and line spacing).\n"); tidy_out(lexer->errout, "The proprietary element has limited vendor support.\n\n"); } if (lexer->badLayout & USING_FONT) { tidy_out(lexer->errout, "You are recommended to use CSS to specify the font and\n"); tidy_out(lexer->errout, "properties such as its size and color. This will reduce\n"); tidy_out(lexer->errout, "the size of HTML files and make them easier to maintain\n"); /* #427674 - fix by Andrew Billington 22 Aug 00 */ tidy_out(lexer->errout, "compared with using elements.\n\n"); } if (lexer->badLayout & USING_NOBR) { tidy_out(lexer->errout, "You are recommended to use CSS to control line wrapping.\n"); tidy_out(lexer->errout, "Use \"white-space: nowrap\" to inhibit wrapping in place\n"); tidy_out(lexer->errout, "of inserting ... into the markup.\n\n"); } if (lexer->badLayout & USING_BODY) { tidy_out(lexer->errout, "You are recommended to use CSS to specify page and link colors\n"); } } } void UnknownOption(FILE *errout, char c) { tidy_out(errout, "unrecognized option -%c use -help to list options\n", c); } void UnknownFile(FILE *errout, char *program, char *file) { tidy_out(errout, "%s: can't open file \"%s\"\n", program, file); } void NeedsAuthorIntervention(FILE *errout) { tidy_out(errout, "Too many errors, no output generated\n"); } void MissingBody(FILE *errout) { tidy_out(errout, "Can't create slides - document is missing a body element.\n"); } void ReportNumberOfSlides(FILE *errout, int count) { tidy_out(errout, "%d Slides found\n", count); } void GeneralInfo(FILE *errout) { tidy_out(errout, "HTML and CSS specifications are available from http://www.w3.org/\n"); tidy_out(errout, "To learn more about HTML Tidy see http://www.w3.org/People/Raggett/tidy/\n"); tidy_out(errout, "Please send bug reports to Dave Raggett care of \n"); tidy_out(errout, "Lobby your company to join W3C, see http://www.w3.org/Consortium\n"); } /* #431895 - fix by Dave Bryan 04 Jan 01 */ void SetFilename (char *filename) { currentFile = filename; /* for use with Gnu Emacs */ } void HelloMessage(FILE *errout, char *date, char *filename) { /* if (wstrcmp(filename, "stdin") == 0) tidy_out(errout, "\nTidy (vers %s) Parsing console input (stdin)\n", date); else tidy_out(errout, "\nTidy (vers %s) Parsing \"%s\"\n", date, filename); */ #ifdef PLATFORM_NAME if (wstrcmp(filename, "stdin") == 0) tidy_out(errout, "\nHTML Tidy for %s (vers %s; built on %s, at %s)\nParsing console input (stdin)\n", PLATFORM_NAME, date, __DATE__, __TIME__); else tidy_out(errout, "\nHTML Tidy for %s (vers %s; built on %s, at %s)\nParsing \"%s\"\n", PLATFORM_NAME, date, __DATE__, __TIME__, filename); #else if (wstrcmp(filename, "stdin") == 0) tidy_out(errout, "\nHTML Tidy (vers %s; built on %s, at %s)\nParsing console input (stdin)\n", date, __DATE__, __TIME__); else tidy_out(errout, "\nHTML Tidy (vers %s; built on %s, at %s)\nParsing \"%s\"\n", date, __DATE__, __TIME__, filename); #endif } void ReportVersion(FILE *errout, Lexer *lexer, char *filename, Node *doctype) { uint i, c; int state = 0; char *vers = HTMLVersionName(lexer); if (doctype) { tidy_out(errout, "\n%s: Doctype given is \"", filename); for (i = doctype->start; i < doctype->end; ++i) { c = (unsigned char)lexer->lexbuf[i]; /* look for UTF-8 multibyte character */ if (c > 0x7F) i += GetUTF8((unsigned char *)lexer->lexbuf + i, &c); if (c == '"') ++state; else if (state == 1) putc(c, errout); } putc('"', errout); } tidy_out(errout, "\n%s: Document content looks like %s\n", filename, (vers ? vers : "HTML proprietary")); } void ReportNumWarnings(FILE *errout, Lexer *lexer) { /* if (lexer->warnings > 0) tidy_out(errout, "%d warnings/errors were found!\n\n", lexer->warnings); */ if ((lexer->warnings > 0) || (lexer->errors > 0)) { tidy_out(errout, "%d %s, %d %s were found!", lexer->warnings, lexer->warnings == 1?"warning":"warnings", lexer->errors, lexer->errors == 1?"error":"errors"); if ((lexer->errors > ShowErrors) || !ShowWarnings) tidy_out(errout, " Not all warnings/errors were shown.\n\n"); else tidy_out(errout, "\n\n"); } else tidy_out(errout, "No warnings or errors were found.\n\n"); } void HelpText(FILE *out, char *prog) { #if 0 /* old style help text */ tidy_out(out, "%s: file1 file2 ...\n", prog); tidy_out(out, "Utility to clean up & pretty print html files\n"); tidy_out(out, "see http://www.w3.org/People/Raggett/tidy/\n"); tidy_out(out, "options for tidy released on %s\n", release_date); tidy_out(out, " -config set options from config file\n"); tidy_out(out, " -indent or -i indent element content\n"); tidy_out(out, " -omit or -o omit optional endtags\n"); tidy_out(out, " -wrap 72 wrap text at column 72 (default is 68)\n"); tidy_out(out, " -upper or -u force tags to upper case (default is lower)\n"); tidy_out(out, " -clean or -c replace font, nobr & center tags by CSS\n"); tidy_out(out, " -raw leave chars > 128 unchanged upon output\n"); tidy_out(out, " -ascii use ASCII for output, Latin-1 for input\n"); tidy_out(out, " -latin1 use Latin-1 for both input and output\n"); tidy_out(out, " -iso2022 use ISO2022 for both input and output\n"); tidy_out(out, " -utf8 use UTF-8 for both input and output\n"); tidy_out(out, " -mac use the Apple MacRoman character set\n"); tidy_out(out, " -numeric or -n output numeric rather than named entities\n"); tidy_out(out, " -modify or -m to modify original files\n"); tidy_out(out, " -errors or -e only show errors\n"); tidy_out(out, " -quiet or -q suppress nonessential output\n"); tidy_out(out, " -f write errors to named \n"); tidy_out(out, " -xml use this when input is wellformed xml\n"); tidy_out(out, " -asxml to convert html to wellformed xml\n"); tidy_out(out, " -slides to burst into slides on h2 elements\n"); tidy_out(out, " -version or -v show version\n"); tidy_out(out, " -help or -h list command line options (this message)\n"); tidy_out(out, " -help-config list all configuration file options\n"); tidy_out(out, "Input/Output default to stdin/stdout respectively\n"); tidy_out(out, "Single letter options apart from -f may be combined\n"); tidy_out(out, "as in: tidy -f errs.txt -imu foo.html\n"); tidy_out(out, "You can also use --blah for any config file option blah\n"); tidy_out(out, "For further info on HTML see http://www.w3.org/MarkUp\n"); #else tidy_out(out, "%s [option...] [file...]\n", prog); tidy_out(out, "Utility to clean up and pretty print HTML/XHTML/XML\n"); tidy_out(out, "see http://www.w3.org/People/Raggett/tidy/\n"); tidy_out(out, "\n"); #ifdef PLATFORM_NAME tidy_out(out, "Options for HTML Tidy for %s released on %s:\n", PLATFORM_NAME, release_date); #else tidy_out(out, "Options for HTML Tidy released on %s:\n", release_date); #endif tidy_out(out, "\n"); tidy_out(out, "Processing directives\n"); tidy_out(out, "---------------------\n"); tidy_out(out, " -indent or -i to indent element content\n"); tidy_out(out, " -omit or -o to omit optional end tags\n"); tidy_out(out, " -wrap to wrap text at the specified (default is 68)\n"); tidy_out(out, " -upper or -u to force tags to upper case (default is lower case)\n"); tidy_out(out, " -clean or -c to replace FONT, NOBR and CENTER tags by CSS\n"); tidy_out(out, " -bare or -b to strip out smart quotes and em dashes, etc.\n"); tidy_out(out, " -numeric or -n to output numeric rather than named entities\n"); tidy_out(out, " -errors or -e to only show errors\n"); tidy_out(out, " -quiet or -q to suppress nonessential output\n"); tidy_out(out, " -xml to specify the input is well formed XML\n"); tidy_out(out, " -asxml to convert HTML to well formed XHTML\n"); tidy_out(out, " -asxhtml to convert HTML to well formed XHTML\n"); tidy_out(out, " -ashtml to force XHTML to well formed HTML\n"); tidy_out(out, " -slides to burst into slides on H2 elements\n"); tidy_out(out, "\n"); tidy_out(out, "Character encodings\n"); tidy_out(out, "-------------------\n"); tidy_out(out, " -raw to output values above 127 without conversion to entities\n"); tidy_out(out, " -ascii to use US-ASCII for output, ISO-8859-1 for input\n"); tidy_out(out, " -latin1 to use ISO-8859-1 for both input and output\n"); tidy_out(out, " -iso2022 to use ISO-2022 for both input and output\n"); tidy_out(out, " -utf8 to use UTF-8 for both input and output\n"); tidy_out(out, " -mac to use MacRoman for input, US-ASCII for output\n"); #if SUPPORT_UTF16_ENCODINGS tidy_out(out, " -utf16le to use UTF-16LE for both input and output\n"); tidy_out(out, " -utf16be to use UTF-16BE for both input and output\n"); tidy_out(out, " -utf16 to use UTF-16 for both input and output\n"); #endif tidy_out(out, " -win1252 to use Windows-1252 for input, US-ASCII for output\n"); #if SUPPORT_ASIAN_ENCODINGS tidy_out(out, " -big5 to use Big5 for both input and output\n"); /* #431953 - RJ */ tidy_out(out, " -shiftjis to use Shift_JIS for both input and output\n"); /* #431953 - RJ */ tidy_out(out, " -language to set the two-letter language code (for future use)\n"); /* #431953 - RJ */ #endif tidy_out(out, "\n"); tidy_out(out, "File manipulation\n"); tidy_out(out, "-----------------\n"); tidy_out(out, " -config to set configuration options from the specified \n"); tidy_out(out, " -f to write errors to the specified \n"); tidy_out(out, " -modify or -m to modify the original input files\n"); tidy_out(out, "\n"); tidy_out(out, "Miscellaneous\n"); tidy_out(out, "-------------\n"); tidy_out(out, " -version or -v to show the version of Tidy\n"); tidy_out(out, " -help, -h or -? to list the command line options\n"); tidy_out(out, " -help-config to list all configuration options\n"); tidy_out(out, " -show-config to list the current configuration settings\n"); tidy_out(out, "\n"); tidy_out(out, "You can also use --blah for any configuration option blah\n"); tidy_out(out, "\n"); tidy_out(out, "Input/Output default to stdin/stdout respectively\n"); tidy_out(out, "Single letter options apart from -f may be combined\n"); tidy_out(out, "as in: tidy -f errs.txt -imu foo.html\n"); tidy_out(out, "For further info on HTML see http://www.w3.org/MarkUp\n"); tidy_out(out, "\n"); #endif }