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