5
|
|
|
|
|
|
|
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include <tidyp.h>
#include <buffio.h>
#include <stdio.h>
#include <errno.h>
static void
_load_config_hash(TidyDoc tdoc, HV *tidy_options)
{
HE *entry;
(void) hv_iterinit(tidy_options);
while ( (entry = hv_iternext(tidy_options)) != NULL ) {
I32 key_len;
const char * const key = hv_iterkey(entry,&key_len);
const TidyOption opt = tidyGetOptionByName(tdoc,key);
if (!opt) {
warn( "HTML::Tidy: Unrecognized option: \"%s\"\n",key );
}
else {
const TidyOptionId id = tidyOptGetId(opt);
SV * const sv_data = hv_iterval(tidy_options,entry);
STRLEN data_len;
const char * const data = SvPV(sv_data,data_len);
if ( ! tidyOptSetValue(tdoc,id,data) ) {
warn( "HTML::Tidy: Can't set option: \"%s\" to \"%s\"\n", key, data );
}
}
}
}
MODULE = HTML::Tidy PACKAGE = HTML::Tidy
PROTOTYPES: ENABLE
void
_tidy_messages(input, configfile, tidy_options)
INPUT:
const char *input
const char *configfile
HV *tidy_options
PREINIT:
TidyBuffer errbuf = {0};
TidyDoc tdoc = tidyCreate(); /* Initialize "document" */
const char* newline;
int rc = 0;
PPCODE:
tidyBufInit(&errbuf);
rc = ( tidyOptSetValue( tdoc, TidyCharEncoding, "utf8" ) ? rc : -1 );
if ( (rc >= 0 ) && configfile && *configfile ) {
rc = tidyLoadConfig( tdoc, configfile );
}
if ( rc >= 0 ) {
_load_config_hash(tdoc,tidy_options);
}
if ( rc >= 0 ) {
/* Capture diagnostics */
rc = tidySetErrorBuffer( tdoc, &errbuf );
}
if ( rc >= 0 ) {
/* Parse the input */
rc = tidyParseString( tdoc, input );
}
if ( rc >= 0 && errbuf.bp) {
XPUSHs( sv_2mortal(newSVpvn((char *)errbuf.bp, errbuf.size)) );
/* TODO: Make this a function */
switch ( tidyOptGetInt(tdoc,TidyNewline) ) {
case TidyLF:
newline = "\n";
break;
case TidyCR:
newline = "\r";
break;
default:
newline = "\r\n";
break;
}
XPUSHs( sv_2mortal(newSVpv(newline, 0)) );
}
else {
rc = -1;
}
if ( errbuf.bp )
tidyBufFree( &errbuf );
tidyRelease( tdoc );
if ( rc < 0 ) {
XSRETURN_UNDEF;
}
void
_tidy_clean(input, configfile, tidy_options)
INPUT:
const char *input
const char *configfile
HV *tidy_options
PREINIT:
TidyBuffer errbuf = {0};
TidyBuffer output = {0};
TidyDoc tdoc = tidyCreate(); /* Initialize "document" */
const char* newline;
int rc = 0;
PPCODE:
tidyBufInit(&output);
tidyBufInit(&errbuf);
/* Set our default first. */
/* Don't word-wrap */
rc = ( tidyOptSetInt( tdoc, TidyWrapLen, 0 ) ? rc : -1 );
if ( (rc >= 0 ) && configfile && *configfile ) {
rc = tidyLoadConfig( tdoc, configfile );
}
/* XXX I think this cascade is a bug waiting to happen */
if ( rc >= 0 ) {
rc = ( tidyOptSetValue( tdoc, TidyCharEncoding, "utf8" ) ? rc : -1 );
}
if ( rc >= 0 ) {
_load_config_hash( tdoc, tidy_options );
}
if ( rc >= 0 ) {
rc = tidySetErrorBuffer( tdoc, &errbuf ); /* Capture diagnostics */
}
if ( rc >= 0 ) {
rc = tidyParseString( tdoc, input ); /* Parse the input */
}
if ( rc >= 0 ) {
rc = tidyCleanAndRepair(tdoc);
}
if ( rc > 1 ) {
rc = ( tidyOptSetBool( tdoc, TidyForceOutput, yes ) ? rc : -1 );
}
if ( rc >= 0) {
rc = tidySaveBuffer( tdoc, &output );
}
if ( rc >= 0) {
rc = tidyRunDiagnostics( tdoc );
}
if ( rc >= 0 && output.bp && errbuf.bp ) {
XPUSHs( sv_2mortal(newSVpvn((char *)output.bp, output.size)) );
XPUSHs( sv_2mortal(newSVpvn((char *)errbuf.bp, errbuf.size)) );
/* TODO: Hoist this into a function */
switch ( tidyOptGetInt(tdoc,TidyNewline) ) {
case TidyLF:
newline = "\n";
break;
case TidyCR:
newline = "\r";
break;
default:
newline = "\r\n";
break;
}
XPUSHs( sv_2mortal(newSVpv(newline, 0)) );
}
else {
rc = -1;
}
tidyBufFree( &output );
tidyBufFree( &errbuf );
tidyRelease( tdoc );
if ( rc < 0 ) {
XSRETURN_UNDEF;
}
SV*
_tidyp_version()
PREINIT:
const char* version;
CODE:
version = tidyVersion();
RETVAL = newSVpv(version,0); /* will be automatically "mortalized" */
OUTPUT:
RETVAL |