diff --git a/console/tidy.c b/console/tidy.c index 0d6179b..d340c86 100755 --- a/console/tidy.c +++ b/console/tidy.c @@ -576,6 +576,12 @@ static void GetOption(TidyDoc tdoc, /**< The tidy document. */ d->vals = "tagX, tagY, ..."; d->def = NULL; break; + + case TidyPriorityAttributes: + d->type = "Attributes Names"; + d->vals = "attributeX, attributeY, ..."; + d->def = NULL; + break; case TidyCharEncoding: case TidyInCharEncoding: diff --git a/include/tidy.h b/include/tidy.h index 29ccc09..3b5762a 100644 --- a/include/tidy.h +++ b/include/tidy.h @@ -925,7 +925,7 @@ TIDY_EXPORT TidyIterator TIDY_CALL tidyOptGetDocLinksList(TidyDoc tdoc, /**< T /** Given a valid TidyIterator initiated with tidyOptGetDocLinksList(), returns ** a TidyOption instance. - ** @result Returns in instane of TidyOption. + ** @result Returns in instance of TidyOption. */ TIDY_EXPORT TidyOption TIDY_CALL tidyOptGetNextDocLinks(TidyDoc tdoc, /**< The tidy document to query. */ TidyIterator* pos /**< The TidyIterator (initiated with tidyOptGetDocLinksList()) token. */ diff --git a/include/tidyenum.h b/include/tidyenum.h old mode 100644 new mode 100755 index 4bbae26..6f4ff19 --- a/include/tidyenum.h +++ b/include/tidyenum.h @@ -220,6 +220,7 @@ extern "C" { FN(MISSING_ENDTAG_FOR) \ FN(MISSING_IMAGEMAP) \ FN(MISSING_QUOTEMARK) \ + FN(MISSING_QUOTEMARK_OPEN) \ FN(MISSING_SEMICOLON_NCR) \ FN(MISSING_SEMICOLON) \ FN(MISSING_STARTTAG) \ @@ -607,6 +608,7 @@ typedef enum TidyPPrintTabs, /**< Indent using tabs istead of spaces */ TidyPreserveEntities, /**< Preserve entities */ TidyPreTags, /**< Declared pre tags */ + TidyPriorityAttributes, /**< Attributes to place first in an element */ #if SUPPORT_ASIAN_ENCODINGS TidyPunctWrap, /**< consider punctuation and breaking spaces for wrapping */ #else diff --git a/localize/translations/tidy.pot b/localize/translations/tidy.pot index 27a3879..3a5c734 100644 --- a/localize/translations/tidy.pot +++ b/localize/translations/tidy.pot @@ -5,7 +5,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: HTML Tidy poconvert.rb\n" "Project-Id-Version: \n" -"POT-Creation-Date: 2017-09-19 14:00:03\n" +"POT-Creation-Date: 2017-09-23 07:53:22\n" "Last-Translator: jderry\n" "Language-Team: \n" @@ -1055,6 +1055,24 @@ msgid "" "This option is ignored in XML mode. " msgstr "" +#. Important notes for translators: +#. - Use only , , , , and +#.
. +#. - Entities, tags, attributes, etc., should be enclosed in . +#. - Option values should be enclosed in . +#. - It's very important that
be self-closing! +#. - The strings "Tidy" and "HTML Tidy" are the program name and must not +#. be translated. +msgctxt "TidyPriorityAttributes" +msgid "" +"This option allows prioritizing the writing of attributes in tidied " +"documents, allowing them to written before the other attributes of an " +"element. For example, you might specify that id and " +"name are written before every other attribute. " +"
" +"This option takes a space or comma separated list of attribute names. " +msgstr "" + #. Important notes for translators: #. - Use only , , , , and #.
. @@ -1226,6 +1244,10 @@ msgid "" "This option specifies that Tidy should sort attributes within an element " "using the specified sort algorithm. If set to alpha, the " "algorithm is an ascending alphabetic sort. " +"
" +"When used while sorting with priority-attributes, any " +"attribute sorting will take place after the priority attributes have " +"been output. " msgstr "" #. Important notes for translators: @@ -2329,6 +2351,11 @@ msgctxt "MISSING_QUOTEMARK" msgid "%s attribute with missing trailing quote mark" msgstr "" +#, c-format +msgctxt "MISSING_QUOTEMARK_OPEN" +msgid "value for attribute \"%s\" missing quote marks" +msgstr "" + #, c-format msgctxt "MISSING_SEMICOLON_NCR" msgid "numeric character reference \"%s\" doesn't end in ';'" diff --git a/src/attrs.c b/src/attrs.c index a4cb379..adb2695 100644 --- a/src/attrs.c +++ b/src/attrs.c @@ -929,6 +929,49 @@ AttVal* TY_(RepairAttrValue)(TidyDocImpl* doc, Node* node, ctmbstr name, ctmbstr return TY_(AddAttribute)(doc, node, name, value); } + +void TY_(FreeAttrPriorityList)( TidyDocImpl* doc ) +{ + PriorityAttribs *priorities = &(doc->attribs.priorityAttribs); + + if ( priorities->list ) + { + uint i = 0; + while ( priorities->list[i] != NULL ) + { + TidyFree( doc->allocator, priorities->list[i] ); + i++; + } + + TidyFree( doc->allocator, priorities->list ); + } +} + +void TY_(DefinePriorityAttribute)(TidyDocImpl* doc, ctmbstr name) +{ + enum { capacity = 10 }; + PriorityAttribs *priorities = &(doc->attribs.priorityAttribs); + + if ( !priorities->list ) + { + priorities->list = TidyAlloc(doc->allocator, sizeof(ctmbstr) * capacity ); + priorities->list[0] = NULL; + priorities->capacity = capacity; + priorities->count = 0; + } + + if ( priorities->count >= priorities->capacity ) + { + priorities->capacity = priorities->capacity * 2; + priorities->list = realloc( priorities->list, sizeof(tmbstr) * priorities->capacity + 1 ); + } + + priorities->list[priorities->count] = TY_(tmbstrdup)( doc->allocator, name); + priorities->count++; + priorities->list[priorities->count] = NULL; +} + + static Bool CheckAttrType( TidyDocImpl* doc, ctmbstr attrname, AttrCheck type ) { @@ -2174,15 +2217,15 @@ void CheckType( TidyDocImpl* doc, Node *node, AttVal *attval) } static -AttVal *SortAttVal( AttVal* list, TidyAttrSortStrategy strat ); +AttVal *SortAttVal( TidyDocImpl* doc, AttVal* list, TidyAttrSortStrategy strat ); -void TY_(SortAttributes)(Node* node, TidyAttrSortStrategy strat) +void TY_(SortAttributes)(TidyDocImpl* doc, Node* node, TidyAttrSortStrategy strat) { while (node) { - node->attributes = SortAttVal( node->attributes, strat ); + node->attributes = SortAttVal( doc, node->attributes, strat ); if (node->content) - TY_(SortAttributes)(node->content, strat); + TY_(SortAttributes)(doc, node->content, strat); node = node->next; } } @@ -2219,25 +2262,88 @@ void TY_(SortAttributes)(Node* node, TidyAttrSortStrategy strat) * SOFTWARE. */ -typedef int(*ptAttValComparator)(AttVal *one, AttVal *two); +typedef int(*ptAttValComparator)(AttVal *one, AttVal *two, ctmbstr *list); -/* Comparison function for TidySortAttrAlpha */ +/* Returns the index of the item in the array, or -1 if not in the array */ static -int AlphaComparator(AttVal *one, AttVal *two) +int indexof( ctmbstr item, ctmbstr *list ) { + if ( list ) + { + uint i = 0; + while ( list[i] != NULL ) { + if ( TY_(tmbstrcasecmp)(item, list[i]) == 0 ) + return i; + i++; + } + } + + return -1; +} + +/* Comparison function for TidySortAttrAlpha. Will also consider items in + the passed in list as higher-priority, and will group them first. + */ +static +int AlphaComparator(AttVal *one, AttVal *two, ctmbstr *list) +{ + int oneIndex = indexof( one->attribute, list ); + int twoIndex = indexof( two->attribute, list ); + + /* If both on the list, the lower index has priority. */ + if ( oneIndex >= 0 && twoIndex >= 0 ) + return oneIndex < twoIndex ? -1 : 1; + + /* If A on the list but B not on the list, then A has priority. */ + if ( oneIndex >= 0 && twoIndex == -1 ) + return -1; + + /* If A not on the list but B is on the list, then B has priority. */ + if ( oneIndex == -1 && twoIndex >= 0 ) + return 1; + + /* Otherwise nothing is on the list, so just compare strings. */ return TY_(tmbstrcmp)(one->attribute, two->attribute); } +/* Comparison function for prioritizing list items. It doesn't otherwise + sort. + */ +static +int PriorityComparator(AttVal *one, AttVal *two, ctmbstr *list) +{ + int oneIndex = indexof( one->attribute, list ); + int twoIndex = indexof( two->attribute, list ); + + /* If both on the list, the lower index has priority. */ + if ( oneIndex >= 0 && twoIndex >= 0 ) + return oneIndex < twoIndex ? -1 : 1; + + /* If A on the list but B not on the list, then A has priority. */ + if ( oneIndex >= 0 && twoIndex == -1 ) + return -1; + + /* If A not on the list but B is on the list, then B has priority. */ + if ( oneIndex == -1 && twoIndex >= 0 ) + return 1; + + /* Otherwise nothing is on the list, so just mark them as the same. */ + return 0; +} + + /* The "factory method" that returns a pointer to the comparator function */ static -ptAttValComparator GetAttValComparator(TidyAttrSortStrategy strat) +ptAttValComparator GetAttValComparator(TidyAttrSortStrategy strat, ctmbstr *list) { switch (strat) { case TidySortAttrAlpha: return AlphaComparator; case TidySortAttrNone: + if ( list && list[0] ) + return PriorityComparator; break; } return 0; @@ -2245,9 +2351,14 @@ ptAttValComparator GetAttValComparator(TidyAttrSortStrategy strat) /* The sort routine */ static -AttVal *SortAttVal( AttVal *list, TidyAttrSortStrategy strat) +AttVal *SortAttVal( TidyDocImpl* doc, AttVal *list, TidyAttrSortStrategy strat) { - ptAttValComparator ptComparator = GetAttValComparator(strat); + /* Get the list from the passed-in tidyDoc. */ +// ctmbstr* priorityList = (ctmbstr*)doc->attribs.priorityAttribs.list; +// ctmbstr priorityList[] = { "id", NULL }; + ctmbstr* priorityList = (ctmbstr*)doc->attribs.priorityAttribs.list; + + ptAttValComparator ptComparator = GetAttValComparator(strat, priorityList); AttVal *p, *q, *e, *tail; int insize, nmerges, psize, qsize, i; @@ -2258,6 +2369,10 @@ AttVal *SortAttVal( AttVal *list, TidyAttrSortStrategy strat) if (!list) return NULL; + /* If no comparator, return the list as-is */ + if (ptComparator == 0) + return list; + insize = 1; while (1) { @@ -2291,7 +2406,7 @@ AttVal *SortAttVal( AttVal *list, TidyAttrSortStrategy strat) } else if (qsize == 0 || !q) { /* q is empty; e must come from p. */ e = p; p = p->next; psize--; - } else if (ptComparator(p,q) <= 0) { + } else if (ptComparator(p,q, priorityList) <= 0) { /* First element of p is lower (or same); * e must come from p. */ e = p; p = p->next; psize--; diff --git a/src/attrs.h b/src/attrs.h index 0192efc..22b4041 100644 --- a/src/attrs.h +++ b/src/attrs.h @@ -60,6 +60,13 @@ enum ANCHOR_HASH_SIZE=1021u }; +/* Keeps a list of attributes that are sorted ahead of the others. */ +typedef struct _priorityAttribs { + tmbstr* list; + uint count; + uint capacity; +} PriorityAttribs; + struct _TidyAttribImpl { /* anchor/node lookup */ @@ -68,6 +75,9 @@ struct _TidyAttribImpl /* Declared literal attributes */ Attribute* declared_attr_list; + /* Prioritized list of attributes to write */ + PriorityAttribs priorityAttribs; + #if ATTRIBUTE_HASH_LOOKUP AttrHash* hashtab[ATTRIBUTE_HASH_SIZE]; #endif @@ -93,6 +103,9 @@ AttVal* TY_(AddAttribute)( TidyDocImpl* doc, AttVal* TY_(RepairAttrValue)(TidyDocImpl* doc, Node* node, ctmbstr name, ctmbstr value); +/* Add an item to the list of priority attributes to write first. */ +void TY_(DefinePriorityAttribute)(TidyDocImpl* doc, ctmbstr name); + Bool TY_(IsUrl)( TidyDocImpl* doc, ctmbstr attrname ); /* Bool IsBool( TidyDocImpl* doc, ctmbstr attrname ); */ @@ -132,13 +145,15 @@ void TY_(FreeAnchors)( TidyDocImpl* doc ); void TY_(InitAttrs)( TidyDocImpl* doc ); void TY_(FreeAttrTable)( TidyDocImpl* doc ); +void TY_(FreeAttrPriorityList)( TidyDocImpl* doc ); + void TY_(AppendToClassAttr)( TidyDocImpl* doc, AttVal *classattr, ctmbstr classname ); /* the same attribute name can't be used more than once in each element */ void TY_(RepairDuplicateAttributes)( TidyDocImpl* doc, Node* node, Bool isXml ); -void TY_(SortAttributes)(Node* node, TidyAttrSortStrategy strat); +void TY_(SortAttributes)(TidyDocImpl* doc, Node* node, TidyAttrSortStrategy strat); Bool TY_(IsBoolAttribute)( AttVal* attval ); Bool TY_(attrIsEvent)( AttVal* attval ); diff --git a/src/config.c b/src/config.c index 64003ea..8de74c6 100644 --- a/src/config.c +++ b/src/config.c @@ -175,6 +175,9 @@ static void AdjustConfig( TidyDocImpl* doc ); /* parser for integer values */ static ParseProperty ParseInt; +/* a space or comma separated list */ +static ParseProperty ParseList; + /* a string excluding whitespace */ static ParseProperty ParseName; @@ -277,6 +280,7 @@ static const TidyOptionImpl option_defs[] = { TidyPPrintTabs, PP, "indent-with-tabs", BL, no, ParseTabs, &boolPicks }, /* 20150515 - Issue #108 */ { TidyPreserveEntities, MU, "preserve-entities", BL, no, ParsePickList, &boolPicks }, { TidyPreTags, MU, "new-pre-tags", ST, 0, ParseTagNames, NULL }, + { TidyPriorityAttributes, MU, "priority-attributes", ST, 0, ParseList, NULL }, #if SUPPORT_ASIAN_ENCODINGS { TidyPunctWrap, PP, "punctuation-wrap", BL, no, ParsePickList, &boolPicks }, #endif @@ -1087,6 +1091,106 @@ void AdjustConfig( TidyDocImpl* doc ) } } + +/* Coordinates Config update and Attributes data for priority attributes, as + a service to ParseList(). + */ +void TY_(DeclarePriorityAttrib)( TidyDocImpl* doc, TidyOptionId optId, ctmbstr name ) +{ + ctmbstr prvval = cfgStr( doc, optId ); + tmbstr catval = NULL; + ctmbstr theval = name; + if ( prvval ) + { + uint len = TY_(tmbstrlen)(name) + TY_(tmbstrlen)(prvval) + 3; + catval = TY_(tmbstrndup)( doc->allocator, prvval, len ); + TY_(tmbstrcat)( catval, ", " ); + TY_(tmbstrcat)( catval, name ); + theval = catval; + } + + TY_(DefinePriorityAttribute)( doc, name ); + SetOptionValue( doc, optId, theval ); + if ( catval ) + TidyDocFree( doc, catval ); + } + +/* a space or comma separated list of attribute names */ +Bool ParseList( TidyDocImpl* doc, const TidyOptionImpl* option ) +{ + TidyConfigImpl* cfg = &doc->config; + tmbchar buf[1024]; + uint i = 0, nItems = 0; + uint c = SkipWhite( cfg ); + + SetOptionValue( doc, option->id, NULL ); + + do + { + if (c == ' ' || c == '\t' || c == ',') + { + c = AdvanceChar( cfg ); + continue; + } + + if ( c == '\r' || c == '\n' ) + { + uint c2 = AdvanceChar( cfg ); + if ( c == '\r' && c2 == '\n' ) + c = AdvanceChar( cfg ); + else + c = c2; + + if ( !TY_(IsWhite)(c) ) + { + buf[i] = 0; + TY_(UngetChar)( c, cfg->cfgIn ); + TY_(UngetChar)( '\n', cfg->cfgIn ); + break; + } + } + + while ( i < sizeof(buf)-2 && c != EndOfStream && !TY_(IsWhite)(c) && c != ',' ) + { + buf[i++] = (tmbchar) c; + c = AdvanceChar( cfg ); + } + + buf[i] = '\0'; + if (i == 0) /* Skip empty attribute definition. Possible when */ + continue; /* there is a trailing space on the line. */ + + /* add attribute to array */ + switch ( option->id ) + { + case TidyPriorityAttributes: + TY_(DeclarePriorityAttrib)( doc, option->id, buf ); + break; + + default: + break; + } + + i = 0; + ++nItems; + } + while ( c != EndOfStream ); + + if ( i > 0 ) + switch ( option->id ) + { + case TidyPriorityAttributes: + TY_(DeclarePriorityAttrib)( doc, option->id, buf ); + break; + + default: + break; + } + + return ( nItems > 0 ); +} + + /* unsigned integers */ Bool ParseInt( TidyDocImpl* doc, const TidyOptionImpl* entry ) { @@ -1351,9 +1455,9 @@ Bool ParseTagNames( TidyDocImpl* doc, const TidyOptionImpl* option ) return ( nTags > 0 ); } + /* a string including whitespace */ /* munges whitespace sequences */ - Bool ParseString( TidyDocImpl* doc, const TidyOptionImpl* option ) { TidyConfigImpl* cfg = &doc->config; diff --git a/src/language_en.h b/src/language_en.h old mode 100644 new mode 100755 index addf8d1..18db40c --- a/src/language_en.h +++ b/src/language_en.h @@ -1005,6 +1005,22 @@ static languageDefinition language_en = { whichPluralForm_en, { "
" "This option is ignored in XML mode. " }, + {/* Important notes for translators: + - Use only , , , , and +
. + - Entities, tags, attributes, etc., should be enclosed in . + - Option values should be enclosed in . + - It's very important that
be self-closing! + - The strings "Tidy" and "HTML Tidy" are the program name and must not + be translated. */ + TidyPriorityAttributes, 0, + "This option allows prioritizing the writing of attributes in tidied " + "documents, allowing them to written before the other attributes of an " + "element. For example, you might specify that id and " + "name are written before every other attribute. " + "
" + "This option takes a space or comma separated list of attribute names. " + }, #if SUPPORT_ASIAN_ENCODINGS {/* Important notes for translators: - Use only , , , , and @@ -1156,6 +1172,10 @@ static languageDefinition language_en = { whichPluralForm_en, { "This option specifies that Tidy should sort attributes within an element " "using the specified sort algorithm. If set to alpha, the " "algorithm is an ascending alphabetic sort. " + "
" + "When used while sorting with priority-attributes, any " + "attribute sorting will take place after the priority attributes have " + "been output. " }, {/* Important notes for translators: - Use only , , , , and @@ -1877,6 +1897,7 @@ static languageDefinition language_en = { whichPluralForm_en, { { MISSING_ENDTAG_FOR, 0, "missing " }, { MISSING_IMAGEMAP, 0, "%s should use client-side image map" }, { MISSING_QUOTEMARK, 0, "%s attribute with missing trailing quote mark" }, + { MISSING_QUOTEMARK_OPEN, 0, "value for attribute \"%s\" missing quote marks" }, { MISSING_SEMICOLON_NCR, 0, "numeric character reference \"%s\" doesn't end in ';'" }, { MISSING_SEMICOLON, 0, "entity \"%s\" doesn't end in ';'" }, { MISSING_STARTTAG, 0, "missing <%s>" }, diff --git a/src/lexer.c b/src/lexer.c old mode 100644 new mode 100755 index a23ed8e..4ff4388 --- a/src/lexer.c +++ b/src/lexer.c @@ -3621,8 +3621,9 @@ static Node *ParsePhp( TidyDocImpl* doc ) } /* consumes the '>' terminating start tags */ +/* @TODO: float the errors back to the calling method */ static tmbstr ParseAttribute( TidyDocImpl* doc, Bool *isempty, - Node **asp, Node **php) + Node **asp, Node **php ) { Lexer* lexer = doc->lexer; int start, len = 0; @@ -3984,8 +3985,6 @@ static tmbstr ParseValue( TidyDocImpl* doc, ctmbstr name, { uint q = c; - TY_(ReportAttrError)( doc, lexer->token, NULL, UNEXPECTED_QUOTEMARK ); - /* handle and ... */ /* this doesn't handle which browsers treat as */ /* 'foo"/' nor which browser treat as 'foo"' */ @@ -4156,7 +4155,7 @@ static tmbstr ParseValue( TidyDocImpl* doc, ctmbstr name, value = NULL; /* note delimiter if given */ - *pdelim = (delim ? delim : '"'); + *pdelim = delim; return value; } @@ -4273,11 +4272,13 @@ static AttVal* ParseAttrs( TidyDocImpl* doc, Bool *isempty ) (cfgBool(doc, TidyXmlTags) && IsValidXMLAttrName(attribute)))) { av = TY_(NewAttribute)(doc); - av->delim = delim; + av->delim = delim ? delim : '"'; av->attribute = attribute; av->value = value; av->dict = TY_(FindAttribute)( doc, av ); - AddAttrToList( &list, av ); + AddAttrToList( &list, av ); + if ( !delim && value ) + TY_(ReportAttrError)( doc, lexer->token, av, MISSING_QUOTEMARK_OPEN); } else { diff --git a/src/message.c b/src/message.c index f9149b4..409f571 100755 --- a/src/message.c +++ b/src/message.c @@ -309,6 +309,7 @@ static struct _dispatchTable { { MISSING_ENDTAG_FOR, TidyWarning, formatStandard }, { MISSING_IMAGEMAP, TidyWarning, formatAttributeReport }, { MISSING_QUOTEMARK, TidyWarning, formatAttributeReport }, + { MISSING_QUOTEMARK_OPEN, TidyInfo, formatAttributeReport }, { MISSING_SEMICOLON_NCR, TidyWarning, formatStandard }, { MISSING_SEMICOLON, TidyWarning, formatStandard }, { MISSING_STARTTAG, TidyWarning, formatStandard }, @@ -531,6 +532,9 @@ TidyMessageImpl *formatAttributeReport(TidyDocImpl* doc, Node *element, Node *no switch (code) { + case MISSING_QUOTEMARK_OPEN: + return TY_(tidyMessageCreateWithNode)(doc, node, code, level, name ); + case BACKSLASH_IN_URI: case ESCAPED_ILLEGAL_URI: case FIXED_BACKSLASH: @@ -546,14 +550,12 @@ TidyMessageImpl *formatAttributeReport(TidyDocImpl* doc, Node *element, Node *no case UNEXPECTED_QUOTEMARK: case WHITE_IN_URI: return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc ); - break; case ATTRIBUTE_IS_NOT_ALLOWED: case JOINING_ATTRIBUTE: case MISSING_ATTR_VALUE: case PROPRIETARY_ATTRIBUTE: return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, name ); - break; case ATTRIBUTE_VALUE_REPLACED: case BAD_ATTRIBUTE_VALUE: @@ -561,30 +563,25 @@ TidyMessageImpl *formatAttributeReport(TidyDocImpl* doc, Node *element, Node *no case INSERTING_AUTO_ATTRIBUTE: case INVALID_ATTRIBUTE: return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, name, value ); - break; case MISMATCHED_ATTRIBUTE_ERROR: case MISMATCHED_ATTRIBUTE_WARN: return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, name, HTMLVersion(doc)); - break; case ANCHOR_NOT_UNIQUE: case ATTR_VALUE_NOT_LCASE: case PROPRIETARY_ATTR_VALUE: case XML_ID_SYNTAX: return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, value ); - break; case REPEATED_ATTRIBUTE: return TY_(tidyMessageCreateWithNode)(doc, node, code, level, tagdesc, value, name ); - break; case UNEXPECTED_END_OF_FILE_ATTR: /* on end of file adjust reported position to end of input */ doc->lexer->lines = doc->docIn->curline; doc->lexer->columns = doc->docIn->curcol; return TY_(tidyMessageCreateWithLexer)(doc, code, level, tagdesc ); - break; } return NULL; @@ -1427,6 +1424,7 @@ static const TidyOptionId TidyNumEntitiesLinks[] = { TidyDoctype, TidyPreser static const TidyOptionId TidyOutCharEncodingLinks[] = { TidyCharEncoding, TidyUnknownOption }; static const TidyOptionId TidyOutFileLinks[] = { TidyErrFile, TidyUnknownOption }; static const TidyOptionId TidyPreTagsLinks[] = { TidyBlockTags, TidyEmptyTags, TidyInlineTags, TidyUseCustomTags, TidyUnknownOption }; +static const TidyOptionId TidySortAttributesLinks[] = { TidyPriorityAttributes, TidyUnknownOption }; static const TidyOptionId TidyUseCustomTagsLinks[] = { TidyBlockTags, TidyEmptyTags, TidyInlineTags, TidyPreTags, TidyUnknownOption }; static const TidyOptionId TidyWrapAttValsLinks[] = { TidyWrapScriptlets, TidyLiteralAttribs, TidyUnknownOption }; static const TidyOptionId TidyWrapScriptletsLinks[] = { TidyWrapAttVals, TidyUnknownOption }; @@ -1454,6 +1452,7 @@ static const TidyOptionDoc docs_xrefs[] = { TidyOutCharEncoding, TidyOutCharEncodingLinks }, { TidyOutFile, TidyOutFileLinks }, { TidyPreTags, TidyPreTagsLinks }, + { TidySortAttributes, TidySortAttributesLinks }, { TidyUseCustomTags, TidyUseCustomTagsLinks }, { TidyWrapAttVals, TidyWrapAttValsLinks }, { TidyWrapScriptlets, TidyWrapScriptletsLinks }, diff --git a/src/tidylib.c b/src/tidylib.c index 162fe5d..c6104eb 100755 --- a/src/tidylib.c +++ b/src/tidylib.c @@ -181,6 +181,7 @@ void tidyDocRelease( TidyDocImpl* doc ) TY_(FreeConfig)( doc ); TY_(FreeAttrTable)( doc ); + TY_(FreeAttrPriorityList)( doc ); TY_(FreeTags)( doc ); /*\ * Issue #186 - Now FreeNode depend on the doctype, so the lexer is needed @@ -2215,8 +2216,7 @@ int tidyDocSaveStream( TidyDocImpl* doc, StreamOut* out ) else TY_(ReplacePreformattedSpaces)(doc, &doc->root); - if ( sortAttrStrat != TidySortAttrNone ) - TY_(SortAttributes)(&doc->root, sortAttrStrat); + TY_(SortAttributes)(doc, &doc->root, sortAttrStrat); if ( showMarkup && (doc->errors == 0 || forceOutput) ) {