1 """CSSPageRule implements DOM Level 2 CSS CSSPageRule.
2 """
3 __all__ = ['CSSPageRule']
4 __docformat__ = 'restructuredtext'
5 __version__ = '$Id: csspagerule.py 1170 2008-03-20 17:42:07Z cthedot $'
6
7 import xml.dom
8 import cssrule
9 import cssutils
10 from selectorlist import SelectorList
11 from cssstyledeclaration import CSSStyleDeclaration
12
14 """
15 The CSSPageRule interface represents a @page rule within a CSS style
16 sheet. The @page rule is used to specify the dimensions, orientation,
17 margins, etc. of a page box for paged media.
18
19 Properties
20 ==========
21 atkeyword (cssutils only)
22 the literal keyword used
23 cssText: of type DOMString
24 The parsable textual representation of this rule
25 selectorText: of type DOMString
26 The parsable textual representation of the page selector for the rule.
27 style: of type CSSStyleDeclaration
28 The declaration-block of this rule.
29
30 Inherits properties from CSSRule
31
32 Format
33 ======
34 ::
35
36 page
37 : PAGE_SYM S* pseudo_page? S*
38 LBRACE S* declaration [ ';' S* declaration ]* '}' S*
39 ;
40 pseudo_page
41 : ':' IDENT # :first, :left, :right in CSS 2.1
42 ;
43
44 """
45 type = property(lambda self: cssrule.CSSRule.PAGE_RULE)
46
47 wellformed = True
48
51 """
52 if readonly allows setting of properties in constructor only
53
54 selectorText
55 type string
56 style
57 CSSStyleDeclaration for this CSSStyleRule
58 """
59 super(CSSPageRule, self).__init__(parentRule=parentRule,
60 parentStyleSheet=parentStyleSheet)
61 self._atkeyword = u'@page'
62 tempseq = self._tempSeq()
63 if selectorText:
64 self.selectorText = selectorText
65 tempseq.append(self.selectorText, 'selectorText')
66 else:
67 self._selectorText = u''
68 if style:
69 self.style = style
70 tempseq.append(self.style, 'style')
71 else:
72 self._style = CSSStyleDeclaration(parentRule=self)
73 self._setSeq(tempseq)
74
75 self._readonly = readonly
76
78 """
79 parses selectorText which may also be a list of tokens
80 and returns (selectorText, seq)
81
82 see _setSelectorText for details
83 """
84
85 new = {'selector': None, 'wellformed': True}
86
87 def _char(expected, seq, token, tokenizer=None):
88
89 val = self._tokenvalue(token)
90 if ':' == expected and u':' == val:
91 try:
92 identtoken = tokenizer.next()
93 except StopIteration:
94 self._log.error(
95 u'CSSPageRule selectorText: No IDENT found.', token)
96 else:
97 ival, ityp = self._tokenvalue(identtoken), self._type(identtoken)
98 if self._prods.IDENT != ityp:
99 self._log.error(
100 u'CSSPageRule selectorText: Expected IDENT but found: %r' %
101 ival, token)
102 else:
103 new['selector'] = val + ival
104 seq.append(new['selector'], 'selector')
105 return 'EOF'
106 return expected
107 else:
108 new['wellformed'] = False
109 self._log.error(
110 u'CSSPageRule selectorText: Unexpected CHAR: %r' % val, token)
111 return expected
112
113 def S(expected, seq, token, tokenizer=None):
114 "Does not raise if EOF is found."
115 return expected
116
117 def COMMENT(expected, seq, token, tokenizer=None):
118 "Does not raise if EOF is found."
119 seq.append(cssutils.css.CSSComment([token]), 'COMMENT')
120 return expected
121
122 newseq = self._tempSeq()
123 wellformed, expected = self._parse(expected=':',
124 seq=newseq, tokenizer=self._tokenize2(selectorText),
125 productions={'CHAR': _char,
126 'COMMENT': COMMENT,
127 'S': S},
128 new=new)
129 wellformed = wellformed and new['wellformed']
130 newselector = new['selector']
131
132
133 if expected == 'ident':
134 self._log.error(
135 u'CSSPageRule selectorText: No valid selector: %r' %
136 self._valuestr(selectorText))
137
138 if not newselector in (None, u':first', u':left', u':right'):
139 self._log.warn(u'CSSPageRule: Unknown CSS 2.1 @page selector: %r' %
140 newselector, neverraise=True)
141
142 return newselector, newseq
143
145 """
146 returns serialized property cssText
147 """
148 return cssutils.ser.do_CSSPageRule(self)
149
151 """
152 DOMException on setting
153
154 - SYNTAX_ERR: (self, StyleDeclaration)
155 Raised if the specified CSS string value has a syntax error and
156 is unparsable.
157 - INVALID_MODIFICATION_ERR: (self)
158 Raised if the specified CSS string value represents a different
159 type of rule than the current one.
160 - HIERARCHY_REQUEST_ERR: (CSSStylesheet)
161 Raised if the rule cannot be inserted at this point in the
162 style sheet.
163 - NO_MODIFICATION_ALLOWED_ERR: (CSSRule)
164 Raised if the rule is readonly.
165 """
166 super(CSSPageRule, self)._setCssText(cssText)
167
168 tokenizer = self._tokenize2(cssText)
169 if self._type(self._nexttoken(tokenizer)) != self._prods.PAGE_SYM:
170 self._log.error(u'CSSPageRule: No CSSPageRule found: %s' %
171 self._valuestr(cssText),
172 error=xml.dom.InvalidModificationErr)
173 else:
174 wellformed = True
175 selectortokens, startbrace = self._tokensupto2(tokenizer,
176 blockstartonly=True,
177 separateEnd=True)
178 styletokens, braceorEOFtoken = self._tokensupto2(tokenizer,
179 blockendonly=True,
180 separateEnd=True)
181 nonetoken = self._nexttoken(tokenizer)
182 if self._tokenvalue(startbrace) != u'{':
183 wellformed = False
184 self._log.error(
185 u'CSSPageRule: No start { of style declaration found: %r' %
186 self._valuestr(cssText), startbrace)
187 elif nonetoken:
188 wellformed = False
189 self._log.error(
190 u'CSSPageRule: Trailing content found.', token=nonetoken)
191
192
193 newselector, newselectorseq = self.__parseSelectorText(selectortokens)
194
195 newstyle = CSSStyleDeclaration()
196 val, typ = self._tokenvalue(braceorEOFtoken), self._type(braceorEOFtoken)
197 if val != u'}' and typ != 'EOF':
198 wellformed = False
199 self._log.error(
200 u'CSSPageRule: No "}" after style declaration found: %r' %
201 self._valuestr(cssText))
202 else:
203 if 'EOF' == typ:
204
205 styletokens.append(braceorEOFtoken)
206 newstyle.cssText = styletokens
207
208 if wellformed:
209 self._selectorText = newselector
210 self.style = newstyle
211 self._setSeq(newselectorseq)
212
213 cssText = property(_getCssText, _setCssText,
214 doc="(DOM) The parsable textual representation of the rule.")
215
217 """
218 wrapper for cssutils Selector object
219 """
220 return self._selectorText
221
223 """
224 wrapper for cssutils Selector object
225
226 selector: DOM String
227 in CSS 2.1 one of
228 - :first
229 - :left
230 - :right
231 - empty
232
233 If WS or Comments are included they are ignored here! Only
234 way to add a comment is via setting ``cssText``
235
236 DOMException on setting
237
238 - SYNTAX_ERR:
239 Raised if the specified CSS string value has a syntax error
240 and is unparsable.
241 - NO_MODIFICATION_ALLOWED_ERR: (self)
242 Raised if this rule is readonly.
243 """
244 self._checkReadonly()
245
246
247 newselectortext, newseq = self.__parseSelectorText(selectorText)
248
249 if newselectortext:
250 for i, x in enumerate(self.seq):
251 if x == self._selectorText:
252 self.seq[i] = newselectortext
253 self._selectorText = newselectortext
254
255 selectorText = property(_getSelectorText, _setSelectorText,
256 doc="""(DOM) The parsable textual representation of the page selector for the rule.""")
257
259
260 return self._style
261
263 """
264 style
265 StyleDeclaration or string
266 """
267 self._checkReadonly()
268
269 if isinstance(style, basestring):
270 self._style.cssText = style
271 else:
272
273
274 self._style.seq = style.seq
275
276 style = property(_getStyle, _setStyle,
277 doc="(DOM) The declaration-block of this rule set.")
278
280 return "cssutils.css.%s(selectorText=%r, style=%r)" % (
281 self.__class__.__name__, self.selectorText, self.style.cssText)
282
284 return "<cssutils.css.%s object selectorText=%r style=%r at 0x%x>" % (
285 self.__class__.__name__, self.selectorText, self.style.cssText,
286 id(self))
287