Issue #70 - Initial implmentation of SVG support.
An immense thanks to Ger Hobbelt who had already done this in his github.com/GerHobbelt/htmltidy fork. The two sources have diverges so was not a simple cut an paste. But again thanks Ger for this.
This commit is contained in:
parent
201f3cb49e
commit
885c7caab7
|
@ -423,6 +423,7 @@ typedef enum
|
||||||
TidyTag_STYLE, /**< STYLE */
|
TidyTag_STYLE, /**< STYLE */
|
||||||
TidyTag_SUB, /**< SUB */
|
TidyTag_SUB, /**< SUB */
|
||||||
TidyTag_SUP, /**< SUP */
|
TidyTag_SUP, /**< SUP */
|
||||||
|
TidyTag_SVG, /**< SVG (HTML5) */
|
||||||
TidyTag_TABLE, /**< TABLE */
|
TidyTag_TABLE, /**< TABLE */
|
||||||
TidyTag_TBODY, /**< TBODY */
|
TidyTag_TBODY, /**< TBODY */
|
||||||
TidyTag_TD, /**< TD */
|
TidyTag_TD, /**< TD */
|
||||||
|
@ -783,8 +784,15 @@ typedef enum
|
||||||
TidyAttr_ARIA_VALUENOW,
|
TidyAttr_ARIA_VALUENOW,
|
||||||
TidyAttr_ARIA_VALUETEXT,
|
TidyAttr_ARIA_VALUETEXT,
|
||||||
|
|
||||||
|
/* SVG attributes (SVG 1.1) */
|
||||||
|
TidyAttr_X, /**< X= */
|
||||||
|
TidyAttr_Y, /**< Y= */
|
||||||
|
TidyAttr_VIEWBOX, /**< VIEWBOX= */
|
||||||
|
TidyAttr_PRESERVEASPECTRATIO, /**< PRESERVEASPECTRATIO= */
|
||||||
|
TidyAttr_ZOOMANDPAN, /**< ZOOMANDPAN= */
|
||||||
|
TidyAttr_BASEPROFILE, /**< BASEPROFILE= */
|
||||||
|
TidyAttr_CONTENTSCRIPTTYPE, /**< CONTENTSCRIPTTYPE= */
|
||||||
|
TidyAttr_CONTENTSTYLETYPE, /**< CONTENTSTYLETYPE= */
|
||||||
|
|
||||||
N_TIDY_ATTRIBS /**< Must be last */
|
N_TIDY_ATTRIBS /**< Must be last */
|
||||||
} TidyAttrId;
|
} TidyAttrId;
|
||||||
|
|
|
@ -11693,6 +11693,41 @@ const AttrVersion TY_(W3CAttrsFor_SUP)[] =
|
||||||
{ TidyAttr_UNKNOWN, 0 },
|
{ TidyAttr_UNKNOWN, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const AttrVersion TY_(W3CAttrsFor_SVG)[] =
|
||||||
|
{
|
||||||
|
{ TidyAttr_ALIGN, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_CLASS, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_DIR, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_ID, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_HEIGHT, xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|XB10|HT50|XH50 },
|
||||||
|
{ TidyAttr_LANG, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|xxxx|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnCLICK, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnDBLCLICK, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnKEYDOWN, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnKEYPRESS, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnKEYUP, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnMOUSEDOWN, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnMOUSEMOVE, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnMOUSEOUT, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnMOUSEOVER, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_OnMOUSEUP, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_STYLE, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_TITLE, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_WIDTH, xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|XB10|HT50|XH50 },
|
||||||
|
{ TidyAttr_XML_LANG, xxxx|xxxx|xxxx|xxxx|X10T|xxxx|xxxx|X10F|xxxx|xxxx|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_XMLNS, xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_X, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_Y, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_VIEWBOX, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_PRESERVEASPECTRATIO, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_ZOOMANDPAN, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_VERSION, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_BASEPROFILE, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_CONTENTSCRIPTTYPE, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_CONTENTSTYLETYPE, xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50 },
|
||||||
|
{ TidyAttr_UNKNOWN, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
const AttrVersion TY_(W3CAttrsFor_TABLE)[] =
|
const AttrVersion TY_(W3CAttrsFor_TABLE)[] =
|
||||||
{
|
{
|
||||||
{ TidyAttr_ACCESSKEY, xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|HT50|XH50 },
|
{ TidyAttr_ACCESSKEY, xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|xxxx|HT50|XH50 },
|
||||||
|
|
|
@ -103,6 +103,7 @@ extern const AttrVersion TY_(W3CAttrsFor_STRONG)[];
|
||||||
extern const AttrVersion TY_(W3CAttrsFor_STYLE)[];
|
extern const AttrVersion TY_(W3CAttrsFor_STYLE)[];
|
||||||
extern const AttrVersion TY_(W3CAttrsFor_SUB)[];
|
extern const AttrVersion TY_(W3CAttrsFor_SUB)[];
|
||||||
extern const AttrVersion TY_(W3CAttrsFor_SUP)[];
|
extern const AttrVersion TY_(W3CAttrsFor_SUP)[];
|
||||||
|
extern const AttrVersion TY_(W3CAttrsFor_SVG)[];
|
||||||
extern const AttrVersion TY_(W3CAttrsFor_TABLE)[];
|
extern const AttrVersion TY_(W3CAttrsFor_TABLE)[];
|
||||||
extern const AttrVersion TY_(W3CAttrsFor_TBODY)[];
|
extern const AttrVersion TY_(W3CAttrsFor_TBODY)[];
|
||||||
extern const AttrVersion TY_(W3CAttrsFor_TD)[];
|
extern const AttrVersion TY_(W3CAttrsFor_TD)[];
|
||||||
|
|
18
src/attrs.c
18
src/attrs.c
|
@ -397,6 +397,24 @@ static const Attribute attribute_defs [] =
|
||||||
{ TidyAttr_ARIA_VALUENOW, "aria-valuenow", CH_PCDATA },
|
{ TidyAttr_ARIA_VALUENOW, "aria-valuenow", CH_PCDATA },
|
||||||
{ TidyAttr_ARIA_VALUETEXT, "aria-valuetext", CH_PCDATA },
|
{ TidyAttr_ARIA_VALUETEXT, "aria-valuetext", CH_PCDATA },
|
||||||
|
|
||||||
|
{ TidyAttr_X, "x", CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_Y, "y", CH_PCDATA }, /* for <svg> */
|
||||||
|
#if 0 /* with uppercase chars taken directly from W3C; are these case-insensitive everywhere? */
|
||||||
|
{ TidyAttr_VIEWBOX, "viewBox", VERS_INLINE_SVG, CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_PRESERVEASPECTRATIO, "preserveAspectRatio", VERS_INLINE_SVG, CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_ZOOMANDPAN, "zoomAndPan", VERS_INLINE_SVG, CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_BASEPROFILE, "baseProfile", VERS_INLINE_SVG, CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_CONTENTSCRIPTTYPE, "contentScriptType", VERS_INLINE_SVG, CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_CONTENTSTYLETYPE, "contentStyleType", VERS_INLINE_SVG, CH_PCDATA }, /* for <svg> */
|
||||||
|
#else
|
||||||
|
{ TidyAttr_VIEWBOX, "viewbox", CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_PRESERVEASPECTRATIO, "preserveaspectratio", CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_ZOOMANDPAN, "zoomandpan", CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_BASEPROFILE, "baseprofile", CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_CONTENTSCRIPTTYPE, "contentscripttype", CH_PCDATA }, /* for <svg> */
|
||||||
|
{ TidyAttr_CONTENTSTYLETYPE, "contentstyletype", CH_PCDATA }, /* for <svg> */
|
||||||
|
#endif
|
||||||
|
|
||||||
/* this must be the final entry */
|
/* this must be the final entry */
|
||||||
{ N_TIDY_ATTRIBS, NULL, NULL }
|
{ N_TIDY_ATTRIBS, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
@ -525,6 +525,7 @@ typedef enum
|
||||||
MixedContent,
|
MixedContent,
|
||||||
Preformatted,
|
Preformatted,
|
||||||
IgnoreMarkup,
|
IgnoreMarkup,
|
||||||
|
OtherNamespace,
|
||||||
CdataContent
|
CdataContent
|
||||||
} GetTokenMode;
|
} GetTokenMode;
|
||||||
|
|
||||||
|
|
173
src/parser.c
173
src/parser.c
|
@ -1359,6 +1359,179 @@ void TY_(ParseBlock)( TidyDocImpl* doc, Node *element, GetTokenMode mode)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [i_a] svg / math */
|
||||||
|
|
||||||
|
struct MatchingDescendantData
|
||||||
|
{
|
||||||
|
Node *found_node;
|
||||||
|
Bool *passed_marker_node;
|
||||||
|
|
||||||
|
/* input: */
|
||||||
|
TidyTagId matching_tagId;
|
||||||
|
Node *node_to_find;
|
||||||
|
Node *marker_node;
|
||||||
|
};
|
||||||
|
|
||||||
|
static NodeTraversalSignal FindDescendant_cb(TidyDocImpl* ARG_UNUSED(doc), Node* node, void *propagate)
|
||||||
|
{
|
||||||
|
struct MatchingDescendantData *cb_data = (struct MatchingDescendantData *)propagate;
|
||||||
|
|
||||||
|
if (TagId(node) == cb_data->matching_tagId)
|
||||||
|
{
|
||||||
|
/* make sure we match up 'unknown' tags exactly! */
|
||||||
|
if (cb_data->matching_tagId != TidyTag_UNKNOWN ||
|
||||||
|
(node->element != NULL &&
|
||||||
|
cb_data->node_to_find != NULL &&
|
||||||
|
cb_data->node_to_find->element != NULL &&
|
||||||
|
0 == TY_(tmbstrcmp)(cb_data->node_to_find->element, node->element)))
|
||||||
|
{
|
||||||
|
cb_data->found_node = node;
|
||||||
|
return ExitTraversal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cb_data->passed_marker_node && node == cb_data->marker_node)
|
||||||
|
*cb_data->passed_marker_node = yes;
|
||||||
|
|
||||||
|
return VisitParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Search the parent chain (from 'parent' upwards up to the root) for a node matching the
|
||||||
|
given 'node'.
|
||||||
|
|
||||||
|
When the search passes beyond the 'marker_node' (which is assumed to sit in the
|
||||||
|
parent chain), this will be flagged by setting the boolean referenced by
|
||||||
|
'is_parent_of_marker' to yes.
|
||||||
|
|
||||||
|
'is_parent_of_marker' and 'marker_node' are optional parameters and may be NULL.
|
||||||
|
*/
|
||||||
|
static Node *FindMatchingDescendant( Node *parent, Node *node, Node *marker_node, Bool *is_parent_of_marker )
|
||||||
|
{
|
||||||
|
struct MatchingDescendantData cb_data = { 0 };
|
||||||
|
cb_data.matching_tagId = TagId(node);
|
||||||
|
cb_data.node_to_find = node;
|
||||||
|
cb_data.marker_node = marker_node;
|
||||||
|
|
||||||
|
assert(node);
|
||||||
|
|
||||||
|
if (is_parent_of_marker)
|
||||||
|
*is_parent_of_marker = no;
|
||||||
|
|
||||||
|
TY_(TraverseNodeTree)(NULL, parent, FindDescendant_cb, &cb_data);
|
||||||
|
return cb_data.found_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Act as a generic XML (sub)tree parser: collect each node and add it to the DOM, without any further validation.
|
||||||
|
TODO : add schema- or other-hierarchy-definition-based validation of the subtree here...
|
||||||
|
*/
|
||||||
|
void TY_(ParseNamespace)(TidyDocImpl* doc, Node *basenode, GetTokenMode mode)
|
||||||
|
{
|
||||||
|
Lexer* lexer = doc->lexer;
|
||||||
|
Node *node;
|
||||||
|
Node *parent = basenode;
|
||||||
|
uint istackbase;
|
||||||
|
|
||||||
|
/* a la <table>: defer popping elements off the inline stack */
|
||||||
|
TY_(DeferDup)( doc );
|
||||||
|
istackbase = lexer->istackbase;
|
||||||
|
lexer->istackbase = lexer->istacksize;
|
||||||
|
|
||||||
|
mode = OtherNamespace; /* Preformatted; IgnoreWhitespace; */
|
||||||
|
|
||||||
|
while ((node = TY_(GetToken)(doc, mode)) != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
fix check to skip action in InsertMisc for regular/empty
|
||||||
|
nodes, which we don't want here...
|
||||||
|
|
||||||
|
The way we do it here is by checking and processing everything
|
||||||
|
and only what remains goes into InsertMisc()
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* is this a close tag? And does it match the current parent node? */
|
||||||
|
if (node->type == EndTag)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
to prevent end tags flowing from one 'alternate namespace' we
|
||||||
|
check this in two phases: first we check if the tag is a
|
||||||
|
descendant of the current node, and when it is, we check whether
|
||||||
|
it is the end tag for a node /within/ or /outside/ the basenode.
|
||||||
|
*/
|
||||||
|
Bool outside;
|
||||||
|
Node *mp = FindMatchingDescendant(parent, node, basenode, &outside);
|
||||||
|
|
||||||
|
if (mp != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
when mp != parent as we might expect,
|
||||||
|
infer end tags until we 'hit' the matched
|
||||||
|
parent or the basenode
|
||||||
|
*/
|
||||||
|
Node *n;
|
||||||
|
|
||||||
|
for (n = parent;
|
||||||
|
n != NULL && n != basenode->parent && n != mp;
|
||||||
|
n = n->parent)
|
||||||
|
{
|
||||||
|
/* n->implicit = yes; */
|
||||||
|
n->closed = yes;
|
||||||
|
TY_(ReportError)(doc, n->parent, n, MISSING_ENDTAG_BEFORE);
|
||||||
|
}
|
||||||
|
assert(outside == no ? n == mp : 1);
|
||||||
|
assert(outside == yes ? n == basenode->parent : 1);
|
||||||
|
|
||||||
|
if (outside == no)
|
||||||
|
{
|
||||||
|
/* EndTag for a node within the basenode subtree. Roll on... */
|
||||||
|
n->closed = yes;
|
||||||
|
TY_(FreeNode)(doc, node);
|
||||||
|
|
||||||
|
node = n;
|
||||||
|
parent = node->parent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* EndTag for a node outside the basenode subtree: let the caller handle that. */
|
||||||
|
TY_(UngetToken)( doc );
|
||||||
|
node = basenode;
|
||||||
|
parent = node->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* when we've arrived at the end-node for the base node, it's quitting time */
|
||||||
|
if (node == basenode)
|
||||||
|
{
|
||||||
|
lexer->istackbase = istackbase;
|
||||||
|
assert(basenode->closed == yes);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* unmatched close tag: report an error and discard */
|
||||||
|
TY_(ReportError)(doc, parent, node, NON_MATCHING_ENDTAG);
|
||||||
|
TY_(ReportError)(doc, parent, node, DISCARDING_UNEXPECTED);
|
||||||
|
assert(parent);
|
||||||
|
assert(parent->tag != node->tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node->type == StartTag)
|
||||||
|
{
|
||||||
|
/* add another child to the current parent */
|
||||||
|
TY_(InsertNodeAtEnd)(parent, node);
|
||||||
|
parent = node;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TY_(InsertNodeAtEnd)(parent, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TY_(ReportError)(doc, basenode->parent, basenode, MISSING_ENDTAG_FOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void TY_(ParseInline)( TidyDocImpl* doc, Node *element, GetTokenMode mode )
|
void TY_(ParseInline)( TidyDocImpl* doc, Node *element, GetTokenMode mode )
|
||||||
{
|
{
|
||||||
#if !defined(NDEBUG) && defined(_MSC_VER)
|
#if !defined(NDEBUG) && defined(_MSC_VER)
|
||||||
|
|
37
src/tags.c
37
src/tags.c
|
@ -108,6 +108,7 @@ static CheckAttribs CheckHTML;
|
||||||
#define VERS_ELEM_STYLE (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
#define VERS_ELEM_STYLE (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
||||||
#define VERS_ELEM_SUB (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
#define VERS_ELEM_SUB (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
||||||
#define VERS_ELEM_SUP (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
#define VERS_ELEM_SUP (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
||||||
|
#define VERS_ELEM_SVG (xxxx|xxxx|xxxx|H41T|X10T|xxxx|H41F|X10F|xxxx|H41S|X10S|XH11|xxxx|HT50|XH50)
|
||||||
#define VERS_ELEM_TABLE (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|XB10|HT50|XH50)
|
#define VERS_ELEM_TABLE (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|XB10|HT50|XH50)
|
||||||
#define VERS_ELEM_TBODY (xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
#define VERS_ELEM_TBODY (xxxx|xxxx|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|xxxx|HT50|XH50)
|
||||||
#define VERS_ELEM_TD (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|XB10|HT50|XH50)
|
#define VERS_ELEM_TD (xxxx|HT32|H40T|H41T|X10T|H40F|H41F|X10F|H40S|H41S|X10S|XH11|XB10|HT50|XH50)
|
||||||
|
@ -247,6 +248,7 @@ static const Dict tag_defs[] =
|
||||||
{ TidyTag_STYLE, "style", VERS_ELEM_STYLE, &TY_(W3CAttrsFor_STYLE)[0], (CM_HEAD|CM_BLOCK), TY_(ParseScript), NULL },
|
{ TidyTag_STYLE, "style", VERS_ELEM_STYLE, &TY_(W3CAttrsFor_STYLE)[0], (CM_HEAD|CM_BLOCK), TY_(ParseScript), NULL },
|
||||||
{ TidyTag_SUB, "sub", VERS_ELEM_SUB, &TY_(W3CAttrsFor_SUB)[0], (CM_INLINE), TY_(ParseInline), NULL },
|
{ TidyTag_SUB, "sub", VERS_ELEM_SUB, &TY_(W3CAttrsFor_SUB)[0], (CM_INLINE), TY_(ParseInline), NULL },
|
||||||
{ TidyTag_SUP, "sup", VERS_ELEM_SUP, &TY_(W3CAttrsFor_SUP)[0], (CM_INLINE), TY_(ParseInline), NULL },
|
{ TidyTag_SUP, "sup", VERS_ELEM_SUP, &TY_(W3CAttrsFor_SUP)[0], (CM_INLINE), TY_(ParseInline), NULL },
|
||||||
|
{ TidyTag_SVG, "svg", VERS_ELEM_SVG, &TY_(W3CAttrsFor_SVG)[0], (CM_INLINE|CM_BLOCK|CM_MIXED), TY_(ParseNamespace),NULL },
|
||||||
{ TidyTag_TABLE, "table", VERS_ELEM_TABLE, &TY_(W3CAttrsFor_TABLE)[0], (CM_BLOCK), TY_(ParseTableTag), CheckTABLE },
|
{ TidyTag_TABLE, "table", VERS_ELEM_TABLE, &TY_(W3CAttrsFor_TABLE)[0], (CM_BLOCK), TY_(ParseTableTag), CheckTABLE },
|
||||||
{ TidyTag_TBODY, "tbody", VERS_ELEM_TBODY, &TY_(W3CAttrsFor_TBODY)[0], (CM_TABLE|CM_ROWGRP|CM_OPT), TY_(ParseRowGroup), NULL },
|
{ TidyTag_TBODY, "tbody", VERS_ELEM_TBODY, &TY_(W3CAttrsFor_TBODY)[0], (CM_TABLE|CM_ROWGRP|CM_OPT), TY_(ParseRowGroup), NULL },
|
||||||
{ TidyTag_TD, "td", VERS_ELEM_TD, &TY_(W3CAttrsFor_TD)[0], (CM_ROW|CM_OPT|CM_NO_INDENT), TY_(ParseBlock), NULL },
|
{ TidyTag_TD, "td", VERS_ELEM_TD, &TY_(W3CAttrsFor_TD)[0], (CM_ROW|CM_OPT|CM_NO_INDENT), TY_(ParseBlock), NULL },
|
||||||
|
@ -949,6 +951,41 @@ uint TY_(nodeHeaderLevel)( Node* node )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* [i_a] generic node tree traversal; see also <tidy-int.h> */
|
||||||
|
NodeTraversalSignal TY_(TraverseNodeTree)(TidyDocImpl* doc, Node* node, NodeTraversalCallBack *cb, void *propagate )
|
||||||
|
{
|
||||||
|
while (node)
|
||||||
|
{
|
||||||
|
NodeTraversalSignal s = (*cb)(doc, node, propagate);
|
||||||
|
|
||||||
|
if (node->content && (s == ContinueTraversal || s == SkipSiblings))
|
||||||
|
{
|
||||||
|
s = TY_(TraverseNodeTree)(doc, node->content, cb, propagate);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (s)
|
||||||
|
{
|
||||||
|
case ExitTraversal:
|
||||||
|
return ExitTraversal;
|
||||||
|
|
||||||
|
case VisitParent:
|
||||||
|
node = node->parent;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case SkipSiblings:
|
||||||
|
case SkipChildrenAndSiblings:
|
||||||
|
return ContinueTraversal;
|
||||||
|
|
||||||
|
default:
|
||||||
|
node = node->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ContinueTraversal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* local variables:
|
* local variables:
|
||||||
* mode: c
|
* mode: c
|
||||||
|
|
|
@ -111,6 +111,7 @@ Parser TY_(ParseSelect);
|
||||||
Parser TY_(ParseOptGroup);
|
Parser TY_(ParseOptGroup);
|
||||||
Parser TY_(ParseText);
|
Parser TY_(ParseText);
|
||||||
Parser TY_(ParseDatalist);
|
Parser TY_(ParseDatalist);
|
||||||
|
Parser TY_(ParseNamespace);
|
||||||
|
|
||||||
CheckAttribs TY_(CheckAttributes);
|
CheckAttribs TY_(CheckAttributes);
|
||||||
|
|
||||||
|
|
|
@ -121,4 +121,26 @@ TidyOption tidyImplToOption( const TidyOptionImpl* option );
|
||||||
|
|
||||||
int TY_(DocParseStream)( TidyDocImpl* impl, StreamIn* in );
|
int TY_(DocParseStream)( TidyDocImpl* impl, StreamIn* in );
|
||||||
|
|
||||||
|
/*
|
||||||
|
[i_a] generic node tree traversal code; used in several spots.
|
||||||
|
|
||||||
|
Define your own callback, which returns one of the NodeTraversalSignal values
|
||||||
|
to instruct the tree traversal routine TraverseNodeTree() what to do.
|
||||||
|
|
||||||
|
Pass custom data to/from the callback using the 'propagate' reference.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ContinueTraversal, /* visit siblings and children */
|
||||||
|
SkipChildren, /* visit siblings of this node; ignore its children */
|
||||||
|
SkipSiblings, /* ignore subsequent siblings of this node; ignore their children; traverse */
|
||||||
|
SkipChildrenAndSiblings, /* visit siblings of this node; ignore its children */
|
||||||
|
VisitParent, /* REVERSE traversal: visit the parent of the current node */
|
||||||
|
ExitTraversal /* terminate traversal on the spot */
|
||||||
|
} NodeTraversalSignal;
|
||||||
|
|
||||||
|
typedef NodeTraversalSignal NodeTraversalCallBack(TidyDocImpl* doc, Node* node, void *propagate);
|
||||||
|
|
||||||
|
NodeTraversalSignal TY_(TraverseNodeTree)(TidyDocImpl* doc, Node* node, NodeTraversalCallBack *cb, void *propagate);
|
||||||
|
|
||||||
#endif /* __TIDY_INT_H__ */
|
#endif /* __TIDY_INT_H__ */
|
||||||
|
|
Loading…
Reference in a new issue