1
  
2
  
3
  
4
  
5
  
6
  
7
  
8
  
9
  
10
  
11
  
12
  
13
  
14
  
15
  
16
  
17
  
18
  
19
  
20
  
21
  
22
  
23
  
24
  
25
  
26
  
27
  
28
  
29
  
30
  
31
  
32
  
33
  
34
  
35
  
36
  
37
  
38
  
39
  
40
  
41
  
42
  
43
  
44
  
45
  
46
  
47
  
48
  
49
  
50
  
51
  
52
  
53
  
54
  
55
  
56
  
57
  
58
  
59
  
60
  
61
  
62
  
63
  
64
  
65
  
66
  
67
  
68
  
69
  
70
  
71
  
72
  
73
  
74
  
75
  
76
  
77
  
78
  
79
  
80
  
81
  
82
  
83
  
84
  
85
  
86
  
87
  
88
  
89
  
// This is a roxen module. Copyright © 2000 - 2009, Roxen IS. 
 
inherit "module"; 
 
constant cvs_version = "$Id$"; 
constant thread_safe = 1; 
constant module_type = MODULE_FILTER; 
constant module_name = "Whitespace Remover"; 
constant module_doc  = "Removes all whitespace from pages."; 
 
void create() { 
 
  defvar("comment", 
         Variable.Flag(0, 0, "Strip HTML comments", 
                       "Removes all <!-- --> type of comments") ); 
  defvar("verbatim", 
         Variable.StringList( ({ "pre", "textarea", "script", "style", 
                                 "code" }), 
                              0, "Verbatim tags", 
                              "Whitespace stripping is not performed on the " 
                              "contents of these tags." ) ); 
} 
 
int gain; 
 
string status() 
{ 
  return sprintf("<b>%d bytes</b> have been dropped.", gain); 
} 
 
protected string most_significant_whitespace(string ws) 
{ 
  int size = sizeof( ws ); 
  if( size ) 
    gain += size-1; 
  return !size ? "" : has_value(ws, "\n") ? "\n" 
                    : has_value(ws, "\t") ? "\t" : " "; 
} 
 
protected array(string) remove_consecutive_whitespace(Parser.HTML p, string in) 
{ 
  sscanf(in, "%{%[ \t\r\n]%[^ \t\r\n]%}", array(array(string)) ws_nws); 
  if(sizeof(ws_nws)) 
  { 
    ws_nws = Array.transpose( ws_nws ); 
    ws_nws[0] = map(ws_nws[0], most_significant_whitespace); 
  } 
  return ({ Array.transpose( ws_nws ) * ({}) * "" }); 
} 
 
array(string) verbatim(Parser.HTML p, mapping(string:string) args, string c) { 
  return ({ p->current() }); 
} 
 
mapping filter(mapping result, RequestID id) 
{ 
  if(!result) 
    return 0; 
  string|array(string) type = result->type; 
  if (arrayp(type)) 
    type = type[0]; 
  if (!type || 
      !has_prefix(type, "text/html") && 
      !has_prefix(type, "text/xml") && 
      !has_prefix(type, "application/xml") && 
      !has_suffix(type, "+xml")) 
    return 0; 
  type = (id->misc->moreheads && id->misc->moreheads["Content-Type"]); 
  if (type && 
      !has_prefix(type, "text/html") && 
      !has_prefix(type, "text/xml") && 
      !has_prefix(type, "application/xml") && 
      !has_suffix(type, "+xml")) 
    return 0; 
  if (!stringp(result->data) || 
      id->prestate->keepws || 
      id->misc->ws_filtered++) 
    return 0; 
 
  Parser.HTML parser = Parser.HTML(); 
  foreach(query("verbatim"), string tag) 
    parser->add_container( tag, verbatim ); 
  parser->add_quote_tag("!--", query("comment")&&"", "--"); 
  parser->_set_data_callback( remove_consecutive_whitespace ); 
  result->data = parser->finish( result->data )->read(); 
  return result; 
}