1 """CSSImportRule implements DOM Level 2 CSS CSSImportRule.
2
3 plus:
4 name
5 http://www.w3.org/TR/css3-cascade/#cascading
6
7 TODO:
8 - stylesheet: read and parse linked stylesheet
9 """
10 __all__ = ['CSSImportRule']
11 __docformat__ = 'restructuredtext'
12 __author__ = '$LastChangedBy: cthedot $'
13 __date__ = '$LastChangedDate: 2008-02-19 22:56:27 +0100 (Di, 19 Feb 2008) $'
14 __version__ = '$LastChangedRevision: 1068 $'
15
16 import xml.dom
17 import cssrule
18 import cssutils
19
21 """
22 Represents an @import rule within a CSS style sheet. The @import rule
23 is used to import style rules from other style sheets.
24
25 Properties
26 ==========
27 atkeyword: (cssutils only)
28 the literal keyword used
29 cssText: of type DOMString
30 The parsable textual representation of this rule
31 href: of type DOMString, (DOM readonly, cssutils also writable)
32 The location of the style sheet to be imported. The attribute will
33 not contain the url(...) specifier around the URI.
34 hreftype: 'uri' (serializer default) or 'string' (cssutils only)
35 The original type of href, not really relevant as it may be
36 reconfigured in the serializer but it is kept anyway
37 media: of type stylesheets::MediaList (DOM readonly)
38 A list of media types for this rule of type MediaList.
39 name:
40 An optional name used for cascading
41 stylesheet: of type CSSStyleSheet (DOM readonly)
42 The style sheet referred to by this rule. The value of this
43 attribute is None if the style sheet has not yet been loaded or if
44 it will not be loaded (e.g. if the stylesheet is for a media type
45 not supported by the user agent).
46
47 Currently always None
48
49 Inherits properties from CSSRule
50
51 Format
52 ======
53 import
54 : IMPORT_SYM S*
55 [STRING|URI] S* [ medium [ COMMA S* medium]* ]? S* STRING? S* ';' S*
56 ;
57 """
58 type = cssrule.CSSRule.IMPORT_RULE
59
60 - def __init__(self, href=None, mediaText=u'all', name=None,
61 parentRule=None, parentStyleSheet=None, readonly=False):
97
98 - def _getCssText(self):
99 """
100 returns serialized property cssText
101 """
102 return cssutils.ser.do_CSSImportRule(self)
103
104 - def _setCssText(self, cssText):
105 """
106 DOMException on setting
107
108 - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
109 Raised if the rule cannot be inserted at this point in the
110 style sheet.
111 - INVALID_MODIFICATION_ERR: (self)
112 Raised if the specified CSS string value represents a different
113 type of rule than the current one.
114 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
115 Raised if the rule is readonly.
116 - SYNTAX_ERR: (self)
117 Raised if the specified CSS string value has a syntax error and
118 is unparsable.
119 """
120 super(CSSImportRule, self)._setCssText(cssText)
121 tokenizer = self._tokenize2(cssText)
122 attoken = self._nexttoken(tokenizer, None)
123 if self._type(attoken) != self._prods.IMPORT_SYM:
124 self._log.error(u'CSSImportRule: No CSSImportRule found: %s' %
125 self._valuestr(cssText),
126 error=xml.dom.InvalidModificationErr)
127 else:
128
129 new = {'keyword': self._tokenvalue(attoken),
130 'href': None,
131 'hreftype': None,
132 'media': cssutils.stylesheets.MediaList(),
133 'name': None,
134 'wellformed': True
135 }
136
137 def __doname(seq, token):
138
139 new['name'] = self._stringtokenvalue(token)
140 seq.append(new['name'], 'name')
141 return ';'
142
143 def _string(expected, seq, token, tokenizer=None):
144 if 'href' == expected:
145
146 new['href'] = self._stringtokenvalue(token)
147 new['hreftype'] = 'string'
148 seq.append(new['href'], 'href')
149 return 'media name ;'
150 elif 'name' in expected:
151
152 return __doname(seq, token)
153 else:
154 new['wellformed'] = False
155 self._log.error(
156 u'CSSImportRule: Unexpected string.', token)
157 return expected
158
159 def _uri(expected, seq, token, tokenizer=None):
160
161 if 'href' == expected:
162 uri = self._uritokenvalue(token)
163 new['hreftype'] = 'uri'
164 new['href'] = uri
165 seq.append(new['href'], 'href')
166 return 'media name ;'
167 else:
168 new['wellformed'] = False
169 self._log.error(
170 u'CSSImportRule: Unexpected URI.', token)
171 return expected
172
173 def _ident(expected, seq, token, tokenizer=None):
174
175 if expected.startswith('media'):
176 mediatokens = self._tokensupto2(
177 tokenizer, importmediaqueryendonly=True)
178 mediatokens.insert(0, token)
179
180 last = mediatokens.pop()
181 lastval, lasttyp = self._tokenvalue(last), self._type(last)
182 if lastval != u';' and lasttyp not in ('EOF', self._prods.STRING):
183 new['wellformed'] = False
184 self._log.error(u'CSSImportRule: No ";" found: %s' %
185 self._valuestr(cssText), token=token)
186
187 media = cssutils.stylesheets.MediaList()
188 media.mediaText = mediatokens
189 if media.wellformed:
190 new['media'] = media
191 seq.append(media, 'media')
192 else:
193 new['wellformed'] = False
194 self._log.error(u'CSSImportRule: Invalid MediaList: %s' %
195 self._valuestr(cssText), token=token)
196
197 if lasttyp == self._prods.STRING:
198
199 return __doname(seq, last)
200 else:
201 return 'EOF'
202 else:
203 new['wellformed'] = False
204 self._log.error(
205 u'CSSImportRule: Unexpected ident.', token)
206 return expected
207
208 def _char(expected, seq, token, tokenizer=None):
209
210 val = self._tokenvalue(token)
211 if expected.endswith(';') and u';' == val:
212 return 'EOF'
213 else:
214 new['wellformed'] = False
215 self._log.error(
216 u'CSSImportRule: Unexpected char.', token)
217 return expected
218
219
220
221
222
223 newseq = self._tempSeq()
224 wellformed, expected = self._parse(expected='href',
225 seq=newseq, tokenizer=tokenizer,
226 productions={'STRING': _string,
227 'URI': _uri,
228
229 'IDENT': _ident,
230 'CHAR': _char})
231
232
233 wellformed = wellformed and new['wellformed']
234
235
236 if not new['href']:
237 wellformed = False
238 self._log.error(u'CSSImportRule: No href found: %s' %
239 self._valuestr(cssText))
240
241 if expected != 'EOF':
242 wellformed = False
243 self._log.error(u'CSSImportRule: No ";" found: %s' %
244 self._valuestr(cssText))
245
246
247 if wellformed:
248 self.atkeyword = new['keyword']
249 self.href = new['href']
250 self.hreftype = new['hreftype']
251 self._media = new['media']
252 self.name = new['name']
253 self._setSeq(newseq)
254
255 cssText = property(fget=_getCssText, fset=_setCssText,
256 doc="(DOM attribute) The parsable textual representation.")
257
271
272 href = property(lambda self: self._href, _setHref,
273 doc="Location of the style sheet to be imported.")
274
275 media = property(lambda self: self._media,
276 doc=u"(DOM readonly) A list of media types for this rule"
277 " of type MediaList")
278
280
281 for i, item in enumerate(self.seq):
282 val, typ = item.value, item.type
283 if 'name' == typ:
284 self._seq[i] = (name, typ, item.line, item.col)
285 break
286 else:
287
288 seq = self._tempSeq()
289 for item in self.seq:
290
291 seq.append(item.value, item.type, item.line, item.col)
292 seq.append(self.href, 'href')
293 self._setSeq(seq)
294 self._name = name
295
296 name = property(lambda self: self._name, _setName,
297 doc=u"An optional name for the imported sheet")
298
299 styleSheet = property(lambda self: self._styleSheet,
300 doc="(readonly) The style sheet referred to by this rule.")
301
302 wellformed = property(lambda self: bool(self.href and self.media.wellformed))
303
305 return "cssutils.css.%s(href=%r, mediaText=%r, name=%r)" % (
306 self.__class__.__name__,
307 self.href, self.media.mediaText, self.name)
308
310 return "<cssutils.css.%s object href=%r at 0x%x>" % (
311 self.__class__.__name__, self.href, id(self))
312