~alinuxninja/nginx-edge/trunk

« back to all changes in this revision

Viewing changes to debian/modules/ngx_pagespeed/psol/include/net/instaweb/rewriter/public/css_util.h

  • Committer: Vivian
  • Date: 2015-12-04 18:20:11 UTC
  • Revision ID: git-v1:a36f2bc32e884f7473b3a47040e5411306144d7d
* Do not extract psol.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2011 Google Inc.
3
 
 *
4
 
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 
 * you may not use this file except in compliance with the License.
6
 
 * You may obtain a copy of the License at
7
 
 *
8
 
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 
 *
10
 
 * Unless required by applicable law or agreed to in writing, software
11
 
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 
 * See the License for the specific language governing permissions and
14
 
 * limitations under the License.
15
 
 */
16
 
 
17
 
// Author: nforman@google.com (Naomi Forman)
18
 
//
19
 
// Functionality for parsing css declarations.
20
 
// Currently this file deals with dimensions only, but could
21
 
// be explanded to include other types of values.
22
 
 
23
 
#ifndef NET_INSTAWEB_REWRITER_PUBLIC_CSS_UTIL_H_
24
 
#define NET_INSTAWEB_REWRITER_PUBLIC_CSS_UTIL_H_
25
 
 
26
 
#include <vector>
27
 
 
28
 
#include "net/instaweb/util/public/basictypes.h"
29
 
#include "net/instaweb/util/public/scoped_ptr.h"
30
 
#include "net/instaweb/util/public/string.h"
31
 
#include "net/instaweb/util/public/string_util.h"
32
 
 
33
 
namespace Css {
34
 
class Declarations;
35
 
class MediaQueries;
36
 
class MediaQuery;
37
 
class Selector;
38
 
}
39
 
 
40
 
namespace net_instaweb {
41
 
 
42
 
class HtmlElement;
43
 
 
44
 
// TODO(nforman): remove this namespace and put everything into the
45
 
// StyleExtractor class.
46
 
namespace css_util {
47
 
 
48
 
static const char kAllMedia[] = "all";
49
 
static const int kNoValue = -1;
50
 
 
51
 
enum DimensionState {
52
 
  kNoDimensions,       // No dimensions found.
53
 
  kHasHeightOnly,      // Found height only.
54
 
  kHasWidthOnly,       // Found width only.
55
 
  kHasBothDimensions,  // Found both width and height.
56
 
  kNotParsable         // Found a dimension, but couldn't extract a value.
57
 
};
58
 
 
59
 
// Extract the width and height values out of a list of declarations.
60
 
// If a value was not found, it will be populated with kNoValue.
61
 
// This is "safe" because even if someone specifies a width:-1; it will be
62
 
// ignored:
63
 
// "If a negative length value is set on a property that does not allow
64
 
// negative length values, the declaration is ignored."
65
 
// http://www.w3.org/TR/CSS2/syndata.html#value-def-length
66
 
DimensionState GetDimensions(Css::Declarations* decls, int* width, int* height);
67
 
 
68
 
class StyleExtractor {
69
 
 public:
70
 
  explicit StyleExtractor(HtmlElement* element);
71
 
  virtual ~StyleExtractor();
72
 
 
73
 
 
74
 
  DimensionState state() const { return state_; }
75
 
 
76
 
  // If a value was not found, it will be populated with kNoValue.
77
 
  int width() const { return width_px_; }
78
 
  int height() const { return height_px_; }
79
 
 
80
 
  // Returns true if there is any dimension specified in a style attribute,
81
 
  // whether or not they're parsable.
82
 
  bool HasAnyDimensions() { return (state_ != kNoDimensions); }
83
 
 
84
 
  DimensionState dimension_state() { return state_; }
85
 
 
86
 
 private:
87
 
  static Css::Declarations* GetDeclsFromElement(HtmlElement* element);
88
 
  scoped_ptr<Css::Declarations> decls_;
89
 
  int width_px_;
90
 
  int height_px_;
91
 
  DimensionState state_;
92
 
  DISALLOW_COPY_AND_ASSIGN(StyleExtractor);
93
 
};
94
 
 
95
 
// Utility functions for handling CSS media types as vectors of strings.
96
 
// There is an argument to use StringPiece's rather than GoogleString's here,
97
 
// but CssFilter::FlattenImportsContext cannot use StringPiece's because it
98
 
// doesn't keep the original strings, so copies in GoogleString's are required.
99
 
 
100
 
// Convert a media string, from either a media attribute or after @import, to
101
 
// a vector of media types. If any of the input media types are 'all' then an
102
 
// empty vector is returned: 'all' means all media types are accepted so it
103
 
// subsumes all other types, and an empty vector representation is most useful.
104
 
void VectorizeMediaAttribute(const StringPiece& input_media,
105
 
                             StringVector* output_vector);
106
 
 
107
 
// Convert a vector of media types to a media string. If the input vector is
108
 
// empty then the answer is 'all', the inverse of the vectorizing function
109
 
// above; if you want the empty string then test the vector yourself. Otherwise
110
 
// the answer is a comma-separated list of media types.
111
 
GoogleString StringifyMediaVector(const StringVector& import_media);
112
 
 
113
 
// Checks if query is not simply a media type. In other words, whether it has
114
 
// a qualifier ("not" or "only") or media expressions (like "and (color)").
115
 
bool IsComplexMediaQuery(const Css::MediaQuery& query);
116
 
 
117
 
// Convert a set of MediaQueries to a vector of UTF-8 GoogleString's for use
118
 
// of the above functions. Elements are trimmed and any empty elements are
119
 
// ignored.
120
 
//
121
 
// Only simple media queries are accepted, returns false for complex queries.
122
 
bool ConvertMediaQueriesToStringVector(const Css::MediaQueries& in_vector,
123
 
                                       StringVector* out_vector);
124
 
 
125
 
// Convert a vector of UTF-8 GoogleString's to MediaQueries. Elements are
126
 
// trimmed and any empty elements are ignored. The strings are interpreted
127
 
// as simple media types (no complex media query syntax like "not screen" or
128
 
// "(max-width: 200px)").
129
 
void ConvertStringVectorToMediaQueries(const StringVector& in_vector,
130
 
                                       Css::MediaQueries* out_vector);
131
 
 
132
 
// Clear the given vector if it contains the media 'all'. This is required
133
 
// because Css::Parser doesn't treat 'all' specially but we do for efficiency.
134
 
void ClearVectorIfContainsMediaAll(StringVector* media);
135
 
 
136
 
// Can this media attribute include some kind of screen?
137
 
bool CanMediaAffectScreen(const StringPiece& media);
138
 
 
139
 
// Strip a parsed selector down to a string that can be used by a
140
 
// querySelectorAll call in the browser to select DOM elements.
141
 
GoogleString JsDetectableSelector(const Css::Selector& selector);
142
 
 
143
 
// Eliminate all elements from the first vector that are not in the second
144
 
// vector, with the caveat that an empty vector (first or second) means 'the
145
 
// set of all possible values', meaning that if the second vector is empty
146
 
// then no elements are removed from the first vector, and if the first vector
147
 
// is empty then the second vector is copied into it. Both vectors must be
148
 
// sorted on entry.
149
 
template<typename T>
150
 
void EliminateElementsNotIn(std::vector<T>* sorted_inner,
151
 
                            const std::vector<T>& sorted_outer) {
152
 
  if (!sorted_outer.empty()) {
153
 
    if (sorted_inner->empty()) {
154
 
      *sorted_inner = sorted_outer;
155
 
    } else {
156
 
      typename std::vector<T>::const_iterator outer_iter = sorted_outer.begin();
157
 
      typename std::vector<T>::iterator inner_iter = sorted_inner->begin();
158
 
 
159
 
      while (inner_iter != sorted_inner->end()) {
160
 
        if (outer_iter == sorted_outer.end()) {
161
 
          // No more outer elements => delete all remaining inner elements.
162
 
          inner_iter = sorted_inner->erase(inner_iter, sorted_inner->end());
163
 
        } else if (*outer_iter == *inner_iter) {
164
 
          // This inner element is in the outer => keep it and move on.
165
 
          ++outer_iter;
166
 
          ++inner_iter;
167
 
        } else if (*outer_iter < *inner_iter) {
168
 
          // This outer element isn't in the inner => skip it, try the next.
169
 
          ++outer_iter;
170
 
        } else {
171
 
          // This inner element isn't in the outer => delete it, move on.
172
 
          inner_iter = sorted_inner->erase(inner_iter);
173
 
        }
174
 
      }
175
 
    }
176
 
  }
177
 
}
178
 
 
179
 
}  // namespace css_util
180
 
 
181
 
}  // namespace net_instaweb
182
 
 
183
 
#endif  // NET_INSTAWEB_REWRITER_PUBLIC_CSS_UTIL_H_