Initial commit of #434; WIP
This commit is contained in:
parent
64fb5640cb
commit
23c28e5b82
|
@ -608,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
|
||||
|
|
118
src/attrs.c
118
src/attrs.c
|
@ -929,6 +929,42 @@ AttVal* TY_(RepairAttrValue)(TidyDocImpl* doc, Node* node, ctmbstr name, ctmbstr
|
|||
return TY_(AddAttribute)(doc, node, name, value);
|
||||
}
|
||||
|
||||
|
||||
void TY_(DefinePriorityAttribute)(TidyDocImpl* doc, ctmbstr name)
|
||||
{
|
||||
enum { capacity = 10 };
|
||||
PriorityAttribs *priorities = &(doc->attribs.priorityAttribs);
|
||||
|
||||
/* @TODO: Don't forget to free this stuff */
|
||||
if ( !priorities->list )
|
||||
{
|
||||
priorities->list = malloc( 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;
|
||||
|
||||
uint i = 0;
|
||||
while ( priorities->list[i] != NULL )
|
||||
{
|
||||
printf("Array contains %s.\n", priorities->list[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
printf("Adding %s to list.\n", name);
|
||||
}
|
||||
|
||||
|
||||
static Bool CheckAttrType( TidyDocImpl* doc,
|
||||
ctmbstr attrname, AttrCheck type )
|
||||
{
|
||||
|
@ -2219,25 +2255,85 @@ 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 )
|
||||
{
|
||||
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[0] )
|
||||
return PriorityComparator;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
@ -2247,7 +2343,13 @@ ptAttValComparator GetAttValComparator(TidyAttrSortStrategy strat)
|
|||
static
|
||||
AttVal *SortAttVal( AttVal *list, TidyAttrSortStrategy strat)
|
||||
{
|
||||
ptAttValComparator ptComparator = GetAttValComparator(strat);
|
||||
/* Get the list from the pass-in tidyDoc, which is a to-do.
|
||||
We'll use this static list temporarily.
|
||||
*/
|
||||
// ctmbstr doc[] = { NULL };
|
||||
ctmbstr temp_list[] = { "id", "name", "class", NULL }; /* temp until option */
|
||||
|
||||
ptAttValComparator ptComparator = GetAttValComparator(strat, temp_list);
|
||||
AttVal *p, *q, *e, *tail;
|
||||
int insize, nmerges, psize, qsize, i;
|
||||
|
||||
|
@ -2258,6 +2360,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 +2397,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, temp_list) <= 0) {
|
||||
/* First element of p is lower (or same);
|
||||
* e must come from p. */
|
||||
e = p; p = p->next; psize--;
|
||||
|
|
12
src/attrs.h
12
src/attrs.h
|
@ -60,6 +60,12 @@ enum
|
|||
ANCHOR_HASH_SIZE=1021u
|
||||
};
|
||||
|
||||
typedef struct _priorityAttribs {
|
||||
ctmbstr* list;
|
||||
uint count;
|
||||
uint capacity;
|
||||
} PriorityAttribs;
|
||||
|
||||
struct _TidyAttribImpl
|
||||
{
|
||||
/* anchor/node lookup */
|
||||
|
@ -68,6 +74,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 +102,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 ); */
|
||||
|
|
88
src/config.c
88
src/config.c
|
@ -172,6 +172,9 @@ static PickListItems attributeCasePicks = {
|
|||
|
||||
static void AdjustConfig( TidyDocImpl* doc );
|
||||
|
||||
/* a space or comma separated list of attribute names */
|
||||
static ParseProperty ParseAttribNames;
|
||||
|
||||
/* parser for integer values */
|
||||
static ParseProperty ParseInt;
|
||||
|
||||
|
@ -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, ParseAttribNames, NULL },
|
||||
#if SUPPORT_ASIAN_ENCODINGS
|
||||
{ TidyPunctWrap, PP, "punctuation-wrap", BL, no, ParsePickList, &boolPicks },
|
||||
#endif
|
||||
|
@ -1087,6 +1091,88 @@ void AdjustConfig( TidyDocImpl* doc )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Coordinates Config update and Attributes data */
|
||||
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 ParseAttribNames( TidyDocImpl* doc, const TidyOptionImpl* option )
|
||||
{
|
||||
TidyConfigImpl* cfg = &doc->config;
|
||||
tmbchar buf[1024];
|
||||
uint i = 0, nAttribs = 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 */
|
||||
TY_(DeclarePriorityAttrib)( doc, option->id, buf );
|
||||
i = 0;
|
||||
++nAttribs;
|
||||
}
|
||||
while ( c != EndOfStream );
|
||||
|
||||
if ( i > 0 )
|
||||
TY_(DeclarePriorityAttrib)( doc, option->id, buf );
|
||||
|
||||
return ( nAttribs > 0 );
|
||||
}
|
||||
|
||||
|
||||
/* unsigned integers */
|
||||
Bool ParseInt( TidyDocImpl* doc, const TidyOptionImpl* entry )
|
||||
{
|
||||
|
@ -1351,9 +1437,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;
|
||||
|
|
|
@ -1005,6 +1005,22 @@ static languageDefinition language_en = { whichPluralForm_en, {
|
|||
"<br/>"
|
||||
"This option is ignored in XML mode. "
|
||||
},
|
||||
{/* Important notes for translators:
|
||||
- Use only <code></code>, <var></var>, <em></em>, <strong></strong>, and
|
||||
<br/>.
|
||||
- Entities, tags, attributes, etc., should be enclosed in <code></code>.
|
||||
- Option values should be enclosed in <var></var>.
|
||||
- It's very important that <br/> 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 <var>id</var> and "
|
||||
"<var>name</var> are written before every other attribute. "
|
||||
"<br/>"
|
||||
"This option takes a space or comma separated list of attribute names. "
|
||||
},
|
||||
#if SUPPORT_ASIAN_ENCODINGS
|
||||
{/* Important notes for translators:
|
||||
- Use only <code></code>, <var></var>, <em></em>, <strong></strong>, and
|
||||
|
|
|
@ -2215,8 +2215,7 @@ int tidyDocSaveStream( TidyDocImpl* doc, StreamOut* out )
|
|||
else
|
||||
TY_(ReplacePreformattedSpaces)(doc, &doc->root);
|
||||
|
||||
if ( sortAttrStrat != TidySortAttrNone )
|
||||
TY_(SortAttributes)(&doc->root, sortAttrStrat);
|
||||
TY_(SortAttributes)(&doc->root, sortAttrStrat);
|
||||
|
||||
if ( showMarkup && (doc->errors == 0 || forceOutput) )
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue