diff --git a/include/tidyenum.h b/include/tidyenum.h
index 7168a06..949d464 100644
--- a/include/tidyenum.h
+++ b/include/tidyenum.h
@@ -604,6 +604,7 @@ typedef enum
TidyJoinClasses, /**< Join multiple class attributes */
TidyJoinStyles, /**< Join multiple style attributes */
TidyKeepFileTimes, /**< If yes last modied time is preserved */
+ TidyKeepTabs, /**< If yes keep input source tabs */
TidyLiteralAttribs, /**< If true attributes may use newlines */
TidyLogicalEmphasis, /**< Replace i by em and b by strong */
TidyLowerLiterals, /**< Folds known attribute values to lower case */
diff --git a/src/config.c b/src/config.c
index 234d1e5..cb53989 100644
--- a/src/config.c
+++ b/src/config.c
@@ -214,6 +214,7 @@ static const TidyOptionImpl option_defs[] =
{ TidyJoinClasses, MX, "join-classes", BL, no, ParsePickList, &boolPicks },
{ TidyJoinStyles, MX, "join-styles", BL, yes, ParsePickList, &boolPicks },
{ TidyKeepFileTimes, IO, "keep-time", BL, no, ParsePickList, &boolPicks },
+ { TidyKeepTabs, PP, "keep-tabs", BL, no, ParsePickList, &boolPicks }, /* 20171103 - Issue #403 */
{ TidyLiteralAttribs, MR, "literal-attributes", BL, no, ParsePickList, &boolPicks },
{ TidyLogicalEmphasis, MC, "logical-emphasis", BL, no, ParsePickList, &boolPicks },
{ TidyLowerLiterals, MR, "lower-literals", BL, yes, ParsePickList, &boolPicks },
diff --git a/src/language_en.h b/src/language_en.h
index f56f1ec..f1468a9 100644
--- a/src/language_en.h
+++ b/src/language_en.h
@@ -699,6 +699,27 @@ static languageDefinition language_en = { whichPluralForm_en, {
"
"
"Note this feature is not supported on some platforms. "
},
+ {/* 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. */
+ TidyKeepTabs, 0,
+ "With the default no Tidy will replace all source tabs, with spaces, "
+ "controlled by the option tab-size
, and the current line offset. "
+ "Of course, except in the special blocks/elements enumerated below, this will later "
+ "be reduced to just one space. "
+ "
"
+ "If set yes this option specifies Tidy should keep certain tabs "
+ "found in the source, but only "
+ "in preformatted blocks like <pre>
, and other CDATA elements like "
+ "<script>
, <style>, and other pseudo elements like "
+ "<?php ... ?>
. As always, all other tabs, or sequences of tabs, in "
+ "the source will continue to be replaced with a space. "
+ },
{/* Important notes for translators:
- Use only
, , , , and
.
diff --git a/src/lexer.c b/src/lexer.c
index 857017b..3d6a489 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -63,6 +63,9 @@ static tmbstr get_text_string(Lexer* lexer, Node *node)
if (c == '\n') {
buffer[i++] = '\\';
buffer[i++] = 'n';
+ } else if (c == '\t') {
+ buffer[i++] = '\\';
+ buffer[i++] = 't';
} else if ( c == ' ' ) {
if (!insp)
buffer[i++] = c;
@@ -84,6 +87,9 @@ static tmbstr get_text_string(Lexer* lexer, Node *node)
if (c == '\n') {
buffer[i++] = '\\';
buffer[i++] = 'n';
+ } else if (c == '\t') {
+ buffer[i++] = '\\';
+ buffer[i++] = 't';
} else if ( c == ' ' ) {
if (!insp)
buffer[i++] = c;
@@ -116,6 +122,9 @@ static tmbstr get_text_string(Lexer* lexer, Node *node)
if (c == '\n') {
buffer[i++] = '\\';
buffer[i++] = 'n';
+ } else if (c == '\t') {
+ buffer[i++] = '\\';
+ buffer[i++] = 't';
} else if ( c == ' ' ) {
if (!insp)
buffer[i++] = c;
diff --git a/src/streamio.c b/src/streamio.c
index cd36efe..bf75a1a 100644
--- a/src/streamio.c
+++ b/src/streamio.c
@@ -239,7 +239,6 @@ static void RestoreLastPos( StreamIn *in )
uint TY_(ReadChar)( StreamIn *in )
{
uint c = EndOfStream;
- uint tabsize = cfg( in->doc, TidyTabSize );
if ( in->pushed )
return PopChar( in );
@@ -269,11 +268,15 @@ uint TY_(ReadChar)( StreamIn *in )
if (c == '\t')
{
- in->tabs = tabsize > 0 ?
- tabsize - ((in->curcol - 1) % tabsize) - 1
- : 0;
+ Bool keeptabs = cfg( in->doc, TidyKeepTabs );
in->curcol++;
- c = ' ';
+ if (!keeptabs) {
+ uint tabsize = cfg(in->doc, TidyTabSize);
+ in->tabs = tabsize > 0 ?
+ tabsize - ((in->curcol - 1) % tabsize) - 1
+ : 0;
+ c = ' ';
+ }
break;
}