~ubuntu-branches/debian/sid/calibre/sid

« back to all changes in this revision

Viewing changes to src/calibre/gui2/tweak_book/editor/syntax/html.py

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2014-02-27 07:48:06 UTC
  • mto: This revision was merged to the branch mainline in revision 74.
  • Revision ID: package-import@ubuntu.com-20140227074806-64wdebb3ptosxhhx
Tags: upstream-1.25.0+dfsg
ImportĀ upstreamĀ versionĀ 1.25.0+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
8
8
 
9
9
import re
10
10
from functools import partial
 
11
from collections import namedtuple
11
12
 
12
 
from PyQt4.Qt import QFont
 
13
from PyQt4.Qt import QFont, QTextBlockUserData
13
14
 
14
15
from calibre.gui2.tweak_book.editor import SyntaxTextCharFormat
15
16
from calibre.gui2.tweak_book.editor.syntax.base import SyntaxHighlighter, run_loop
20
21
cdata_tags = cdataElements | rcdataElements
21
22
bold_tags = {'b', 'strong'} | {'h%d' % d for d in range(1, 7)}
22
23
italic_tags = {'i', 'em'}
23
 
normal_pat = re.compile(r'[^<>&]')
 
24
normal_pat = re.compile(r'[^<>&]+')
24
25
entity_pat = re.compile(r'&#{0,1}[a-zA-Z0-9]{1,8};')
25
26
tag_name_pat = re.compile(r'/{0,1}[a-zA-Z0-9:]+')
26
27
space_chars = ' \t\r\n\u000c'
76
77
        self.parse = self.bold = self.italic = self.css = 0
77
78
        self.tag = self.UNKNOWN_TAG
78
79
 
 
80
TagStart = namedtuple('TagStart', 'offset prefix name closing is_start')
 
81
TagEnd = namedtuple('TagEnd', 'offset self_closing is_start')
 
82
 
 
83
def add_tag_data(state, tag):
 
84
    ud = q = state.get_user_data()
 
85
    if ud is None:
 
86
        ud = HTMLUserData()
 
87
    ud.tags.append(tag)
 
88
    if q is None:
 
89
        state.set_user_data(ud)
 
90
 
79
91
def css(state, text, i, formats):
80
92
    ' Inside a <style> tag '
81
93
    pat = cdata_close_pats['style']
92
104
    if m is not None:
93
105
        state.clear()
94
106
        state.parse = State.IN_CLOSING_TAG
 
107
        add_tag_data(state, TagStart(m.start(), 'style', '', True, True))
95
108
        ans.extend([(2, formats['end_tag']), (len(m.group()) - 2, formats['tag_name'])])
96
109
    return ans
97
110
 
104
117
        return [(len(text) - i, fmt)]
105
118
    state.parse = State.IN_CLOSING_TAG
106
119
    num = m.start() - i
 
120
    add_tag_data(state, TagStart(m.start(), state.tag, '', True, True))
107
121
    return [(num, fmt), (2, formats['end_tag']), (len(m.group()) - 2, formats['tag_name'])]
108
122
 
109
123
def mark_nbsp(state, text, nbsp_format):
118
132
    last = 0
119
133
    for m in nbsp_pat.finditer(text):
120
134
        ans.extend([(m.start() - last, fmt), (m.end() - m.start(), nbsp_format)])
 
135
        last = m.end()
121
136
    if not ans:
122
137
        ans = [(len(text), fmt)]
123
138
    return ans
124
139
 
 
140
class HTMLUserData(QTextBlockUserData):
 
141
 
 
142
    def __init__(self):
 
143
        QTextBlockUserData.__init__(self)
 
144
        self.tags = []
125
145
 
126
146
def normal(state, text, i, formats):
127
147
    ' The normal state in between tags '
154
174
        if prefix and name:
155
175
            ans.append((len(prefix)+1, formats['nsprefix']))
156
176
        ans.append((len(name or prefix), formats['tag_name']))
 
177
        add_tag_data(state, TagStart(i, prefix, name, closing, True))
157
178
        return ans
158
179
 
159
180
    if ch == '&':
179
200
            return [(1, formats['/'])]
180
201
        state.parse = state.NORMAL
181
202
        state.tag = State.UNKNOWN_TAG
182
 
        return [(len(m.group()), formats['tag'])]
 
203
        l = len(m.group())
 
204
        add_tag_data(state, TagEnd(i + l - 1, True, False))
 
205
        return [(l, formats['tag'])]
183
206
    if ch == '>':
184
207
        state.parse = state.NORMAL
185
208
        tag = state.tag.lower()
190
213
                state.parse = state.CSS
191
214
        state.bold += int(tag in bold_tags)
192
215
        state.italic += int(tag in italic_tags)
 
216
        add_tag_data(state, TagEnd(i, False, False))
193
217
        return [(1, formats['tag'])]
194
218
    m = attribute_name_pat.match(text, i)
195
219
    if m is None:
256
280
    if num > 1:
257
281
        ans.insert(0, (num - 1, formats['bad-closing']))
258
282
    state.tag = State.UNKNOWN_TAG
 
283
    add_tag_data(state, TagEnd(pos, False, False))
259
284
    return ans
260
285
 
261
286
def in_comment(state, text, i, formats):