##// END OF EJS Templates
Parse text with <p> tag. Use single newline after replying a post. Removed...
neko259 -
r744:3db85d22 2.0-dev
parent child Browse files
Show More
@@ -1,152 +1,152 b''
1 1 # coding=utf-8
2 2
3 3 import re
4 4 import bbcode
5 5
6 6 import boards
7 7
8 8
9 9 __author__ = 'neko259'
10 10
11 11
12 12 REFLINK_PATTERN = re.compile(r'\d+')
13 13
14 14
15 15 class TextFormatter():
16 16 """
17 17 An interface for formatter that can be used in the text format panel
18 18 """
19 19
20 20 def __init__(self):
21 21 pass
22 22
23 23 name = ''
24 24
25 25 # Left and right tags for the button preview
26 26 preview_left = ''
27 27 preview_right = ''
28 28
29 29 # Left and right characters for the textarea input
30 30 format_left = ''
31 31 format_right = ''
32 32
33 33
34 34 class AutolinkPattern():
35 35 def handleMatch(self, m):
36 36 link_element = etree.Element('a')
37 37 href = m.group(2)
38 38 link_element.set('href', href)
39 39 link_element.text = href
40 40
41 41 return link_element
42 42
43 43
44 44 class QuotePattern(TextFormatter):
45 45 name = 'q'
46 46 preview_left = '<span class="multiquote">'
47 47 preview_right = '</span>'
48 48
49 49 format_left = '[quote]'
50 50 format_right = '[/quote]'
51 51
52 52
53 53 class SpoilerPattern(TextFormatter):
54 54 name = 'spoiler'
55 55 preview_left = '<span class="spoiler">'
56 56 preview_right = '</span>'
57 57
58 58 format_left = '[spoiler]'
59 59 format_right = '[/spoiler]'
60 60
61 61 def handleMatch(self, m):
62 62 quote_element = etree.Element('span')
63 63 quote_element.set('class', 'spoiler')
64 64 quote_element.text = m.group(2)
65 65
66 66 return quote_element
67 67
68 68
69 69 class CommentPattern(TextFormatter):
70 70 name = ''
71 71 preview_left = '<span class="comment">// '
72 72 preview_right = '</span>'
73 73
74 74 format_left = '[comment]'
75 75 format_right = '[/comment]'
76 76
77 77
78 78 class StrikeThroughPattern(TextFormatter):
79 79 name = 's'
80 80 preview_left = '<span class="strikethrough">'
81 81 preview_right = '</span>'
82 82
83 83 format_left = '[s]'
84 84 format_right = '[/s]'
85 85
86 86
87 87 class ItalicPattern(TextFormatter):
88 88 name = 'i'
89 89 preview_left = '<i>'
90 90 preview_right = '</i>'
91 91
92 92 format_left = '[i]'
93 93 format_right = '[/i]'
94 94
95 95
96 96 class BoldPattern(TextFormatter):
97 97 name = 'b'
98 98 preview_left = '<b>'
99 99 preview_right = '</b>'
100 100
101 101 format_left = '[b]'
102 102 format_right = '[/b]'
103 103
104 104
105 105 class CodePattern(TextFormatter):
106 106 name = 'code'
107 107 preview_left = '<code>'
108 108 preview_right = '</code>'
109 109
110 110 format_left = '[code]'
111 111 format_right = '[/code]'
112 112
113 113
114 114 def render_reflink(tag_name, value, options, parent, context):
115 115 if not REFLINK_PATTERN.match(value):
116 116 return u'>>%s' % value
117 117
118 118 post_id = int(value)
119 119
120 120 posts = boards.models.Post.objects.filter(id=post_id)
121 121 if posts.exists():
122 122 post = posts[0]
123 123
124 124 return u'<a href=%s>&gt;&gt;%s</a>' % (post.get_url(), post_id)
125 125 else:
126 126 return u'>>%s' % value
127 127
128 128
129 129 def bbcode_extended(markup):
130 parser = bbcode.Parser()
130 parser = bbcode.Parser(newline='</p><p>')
131 131 parser.add_formatter('post', render_reflink, strip=True)
132 132 parser.add_simple_formatter('quote',
133 133 u'<span class="multiquote">%(value)s</span>')
134 134 parser.add_simple_formatter('comment',
135 135 u'<span class="comment">//%(value)s</span>')
136 136 parser.add_simple_formatter('spoiler',
137 137 u'<span class="spoiler">%(value)s</span>')
138 138 parser.add_simple_formatter('s',
139 139 u'<span class="strikethrough">%(value)s</span>')
140 140 parser.add_simple_formatter('code',
141 141 u'<pre><code>%(value)s</pre></code>')
142 return parser.format(markup)
142 return '<p>%s</p>' % parser.format(markup)
143 143
144 144 formatters = [
145 145 QuotePattern,
146 146 SpoilerPattern,
147 147 ItalicPattern,
148 148 BoldPattern,
149 149 CommentPattern,
150 150 StrikeThroughPattern,
151 151 CodePattern,
152 152 ]
@@ -1,448 +1,440 b''
1 1 html {
2 2 background: #555;
3 3 color: #ffffff;
4 4 }
5 5
6 6 body {
7 7 margin: 0;
8 8 }
9 9
10 10 #admin_panel {
11 11 background: #FF0000;
12 12 color: #00FF00
13 13 }
14 14
15 15 .input_field_error {
16 16 color: #FF0000;
17 17 }
18 18
19 19 .title {
20 20 font-weight: bold;
21 21 color: #ffcc00;
22 22 }
23 23
24 24 .link, a {
25 25 color: #afdcec;
26 26 }
27 27
28 28 .block {
29 29 display: inline-block;
30 30 vertical-align: top;
31 31 }
32 32
33 33 .tag {
34 34 color: #FFD37D;
35 35 }
36 36
37 37 .post_id {
38 38 color: #fff380;
39 39 }
40 40
41 41 .post, .dead_post, .archive_post, #posts-table {
42 42 background: #333;
43 43 padding: 10px;
44 44 clear: left;
45 45 word-wrap: break-word;
46 46 border-top: 1px solid #777;
47 47 border-bottom: 1px solid #777;
48 48 }
49 49
50 50 .post + .post {
51 51 border-top: none;
52 52 }
53 53
54 54 .dead_post + .dead_post {
55 55 border-top: none;
56 56 }
57 57
58 58 .archive_post + .archive_post {
59 59 border-top: none;
60 60 }
61 61
62 62 .metadata {
63 63 padding-top: 5px;
64 64 margin-top: 10px;
65 65 border-top: solid 1px #666;
66 66 color: #ddd;
67 67 }
68 68
69 69 .navigation_panel, .tag_info {
70 70 background: #444;
71 71 margin-bottom: 5px;
72 72 margin-top: 5px;
73 73 padding: 10px;
74 74 border-bottom: solid 1px #888;
75 75 border-top: solid 1px #888;
76 76 color: #eee;
77 77 }
78 78
79 79 .navigation_panel .link {
80 80 border-right: 1px solid #fff;
81 81 font-weight: bold;
82 82 margin-right: 1ex;
83 83 padding-right: 1ex;
84 84 }
85 85 .navigation_panel .link:last-child {
86 86 border-left: 1px solid #fff;
87 87 border-right: none;
88 88 float: right;
89 89 margin-left: 1ex;
90 90 margin-right: 0;
91 91 padding-left: 1ex;
92 92 padding-right: 0;
93 93 }
94 94
95 95 .navigation_panel::after, .post::after {
96 96 clear: both;
97 97 content: ".";
98 98 display: block;
99 99 height: 0;
100 100 line-height: 0;
101 101 visibility: hidden;
102 102 }
103 103
104 104 p {
105 105 margin-top: .5em;
106 106 margin-bottom: .5em;
107 107 }
108 108
109 109 .post-form-w {
110 110 background: #333344;
111 111 border-top: solid 1px #888;
112 112 border-bottom: solid 1px #888;
113 113 color: #fff;
114 114 padding: 10px;
115 115 margin-bottom: 5px;
116 116 margin-top: 5px;
117 117 }
118 118
119 119 .form-row {
120 120 width: 100%;
121 121 }
122 122
123 123 .form-label {
124 124 padding: .25em 1ex .25em 0;
125 125 vertical-align: top;
126 126 }
127 127
128 128 .form-input {
129 129 padding: .25em 0;
130 130 }
131 131
132 132 .form-errors {
133 133 font-weight: bolder;
134 134 vertical-align: middle;
135 padding: 3px;
136 background: repeating-linear-gradient(
137 -45deg,
138 #330,
139 #330 10px,
140 #111 10px,
141 #111 20px
142 );
143 135 }
144 136
145 137 .post-form input:not([name="image"]), .post-form textarea {
146 138 background: #333;
147 139 color: #fff;
148 140 border: solid 1px;
149 141 padding: 0;
150 142 font: medium sans-serif;
151 143 width: 100%;
152 144 }
153 145
154 146 .form-submit {
155 147 display: table;
156 148 margin-bottom: 1ex;
157 149 margin-top: 1ex;
158 150 }
159 151
160 152 .form-title {
161 153 font-weight: bold;
162 154 font-size: 2ex;
163 155 margin-bottom: 0.5ex;
164 156 }
165 157
166 158 .post-form input[type="submit"], input[type="submit"] {
167 159 background: #222;
168 160 border: solid 2px #fff;
169 161 color: #fff;
170 162 padding: 0.5ex;
171 163 }
172 164
173 165 input[type="submit"]:hover {
174 166 background: #060;
175 167 }
176 168
177 169 blockquote {
178 170 border-left: solid 2px;
179 171 padding-left: 5px;
180 172 color: #B1FB17;
181 173 margin: 0;
182 174 }
183 175
184 176 .post > .image {
185 177 float: left;
186 178 margin: 0 1ex .5ex 0;
187 179 min-width: 1px;
188 180 text-align: center;
189 181 display: table-row;
190 182 }
191 183
192 184 .post > .metadata {
193 185 clear: left;
194 186 }
195 187
196 188 .get {
197 189 font-weight: bold;
198 190 color: #d55;
199 191 }
200 192
201 193 * {
202 194 text-decoration: none;
203 195 }
204 196
205 197 .dead_post {
206 198 background-color: #442222;
207 199 }
208 200
209 201 .archive_post {
210 202 background-color: #000;
211 203 }
212 204
213 205 .mark_btn {
214 206 border: 1px solid;
215 207 min-width: 2ex;
216 208 padding: 2px 2ex;
217 209 }
218 210
219 211 .mark_btn:hover {
220 212 background: #555;
221 213 }
222 214
223 215 .quote {
224 216 color: #92cf38;
225 217 font-style: italic;
226 218 }
227 219
228 220 .multiquote {
229 221 border-left: solid 4px #ccc;
230 222 padding: 3px;
231 223 display: inline-block;
232 224 background: #222;
233 225 border-right: solid 1px #ccc;
234 226 border-top: solid 1px #ccc;
235 227 border-bottom: solid 1px #ccc;
236 228 }
237 229
238 230 .spoiler {
239 231 background: white;
240 232 color: white;
241 233 }
242 234
243 235 .spoiler:hover {
244 236 color: black;
245 237 }
246 238
247 239 .comment {
248 240 color: #eb2;
249 241 }
250 242
251 243 a:hover {
252 244 text-decoration: underline;
253 245 }
254 246
255 247 .last-replies {
256 248 margin-left: 3ex;
257 249 margin-right: 3ex;
258 250 }
259 251
260 252 .thread {
261 253 margin-bottom: 3ex;
262 254 margin-top: 1ex;
263 255 }
264 256
265 257 .post:target {
266 258 border: solid 2px white;
267 259 }
268 260
269 261 pre{
270 262 white-space:pre-wrap
271 263 }
272 264
273 265 li {
274 266 list-style-position: inside;
275 267 }
276 268
277 269 .fancybox-skin {
278 270 position: relative;
279 271 background-color: #fff;
280 272 color: #ddd;
281 273 text-shadow: none;
282 274 }
283 275
284 276 .fancybox-image {
285 277 border: 1px solid black;
286 278 }
287 279
288 280 .image-mode-tab {
289 281 background: #444;
290 282 color: #eee;
291 283 margin-top: 5px;
292 284 padding: 5px;
293 285 border-top: 1px solid #888;
294 286 border-bottom: 1px solid #888;
295 287 }
296 288
297 289 .image-mode-tab > label {
298 290 margin: 0 1ex;
299 291 }
300 292
301 293 .image-mode-tab > label > input {
302 294 margin-right: .5ex;
303 295 }
304 296
305 297 #posts-table {
306 298 margin-top: 5px;
307 299 margin-bottom: 5px;
308 300 }
309 301
310 302 .tag_info > h2 {
311 303 margin: 0;
312 304 }
313 305
314 306 .post-info {
315 307 color: #ddd;
316 308 margin-bottom: 1ex;
317 309 }
318 310
319 311 .moderator_info {
320 312 color: #e99d41;
321 313 float: right;
322 314 font-weight: bold;
323 315 }
324 316
325 317 .refmap {
326 318 font-size: 0.9em;
327 319 color: #ccc;
328 320 margin-top: 1em;
329 321 }
330 322
331 323 .fav {
332 324 color: yellow;
333 325 }
334 326
335 327 .not_fav {
336 328 color: #ccc;
337 329 }
338 330
339 331 .role {
340 332 text-decoration: underline;
341 333 }
342 334
343 335 .form-email {
344 336 display: none;
345 337 }
346 338
347 339 .footer {
348 340 margin: 5px;
349 341 }
350 342
351 343 .bar-value {
352 344 background: rgba(50, 55, 164, 0.45);
353 345 font-size: 0.9em;
354 346 height: 1.5em;
355 347 }
356 348
357 349 .bar-bg {
358 350 position: relative;
359 351 border-top: solid 1px #888;
360 352 border-bottom: solid 1px #888;
361 353 margin-top: 5px;
362 354 overflow: hidden;
363 355 }
364 356
365 357 .bar-text {
366 358 padding: 2px;
367 359 position: absolute;
368 360 left: 0;
369 361 top: 0;
370 362 }
371 363
372 364 .page_link {
373 365 background: #444;
374 366 border-top: solid 1px #888;
375 367 border-bottom: solid 1px #888;
376 368 padding: 5px;
377 369 color: #eee;
378 370 font-size: 2ex;
379 371 }
380 372
381 373 .skipped_replies {
382 374 margin: 5px;
383 375 }
384 376
385 377 .current_page {
386 378 border: solid 1px #afdcec;
387 379 padding: 2px;
388 380 }
389 381
390 382 .current_mode {
391 383 font-weight: bold;
392 384 }
393 385
394 386 .gallery_image {
395 387 border: solid 1px;
396 388 padding: 0.5ex;
397 389 margin: 0.5ex;
398 390 text-align: center;
399 391 }
400 392
401 393 code {
402 394 border: dashed 1px #ccc;
403 395 background: #111;
404 396 padding: 2px;
405 397 font-size: 1.2em;
406 398 display: inline-block;
407 399 }
408 400
409 401 pre {
410 402 overflow: auto;
411 403 }
412 404
413 405 .img-full {
414 406 background: #222;
415 407 border: solid 1px white;
416 408 }
417 409
418 410 .tag_item {
419 411 display: inline-block;
420 412 border: 1px dashed #666;
421 413 margin: 0.2ex;
422 414 padding: 0.1ex;
423 415 }
424 416
425 417 #id_models li {
426 418 list-style: none;
427 419 }
428 420
429 421 #id_q {
430 422 margin-left: 1ex;
431 423 }
432 424
433 425 ul {
434 426 padding-left: 0px;
435 427 }
436 428
437 429 /* Reflink preview */
438 430 .post_preview {
439 431 border-left: 1px solid #777;
440 432 border-right: 1px solid #777;
441 433 }
442 434
443 435 /* Code highlighter */
444 436 .hljs {
445 437 color: #fff;
446 438 background: #000;
447 439 display: inline-block;
448 440 }
@@ -1,61 +1,61 b''
1 1 /*
2 2 @licstart The following is the entire license notice for the
3 3 JavaScript code in this page.
4 4
5 5
6 6 Copyright (C) 2013 neko259
7 7
8 8 The JavaScript code in this page is free software: you can
9 9 redistribute it and/or modify it under the terms of the GNU
10 10 General Public License (GNU GPL) as published by the Free Software
11 11 Foundation, either version 3 of the License, or (at your option)
12 12 any later version. The code is distributed WITHOUT ANY WARRANTY;
13 13 without even the implied warranty of MERCHANTABILITY or FITNESS
14 14 FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
15 15
16 16 As additional permission under GNU GPL version 3 section 7, you
17 17 may distribute non-source (e.g., minimized or compacted) forms of
18 18 that code without the copy of the GNU GPL normally required by
19 19 section 4, provided you include this license notice and a URL
20 20 through which recipients can access the Corresponding Source.
21 21
22 22 @licend The above is the entire license notice
23 23 for the JavaScript code in this page.
24 24 */
25 25
26 26 function moveCaretToEnd(el) {
27 27 if (typeof el.selectionStart == "number") {
28 28 el.selectionStart = el.selectionEnd = el.value.length;
29 29 } else if (typeof el.createTextRange != "undefined") {
30 30 el.focus();
31 31 var range = el.createTextRange();
32 32 range.collapse(false);
33 33 range.select();
34 34 }
35 35 }
36 36
37 37 function addQuickReply(postId) {
38 var textToAdd = '[post]' + postId + '[/post]\n\n';
38 var textToAdd = '[post]' + postId + '[/post]\n';
39 39 var selection = window.getSelection().toString();
40 40 if (selection.length > 0) {
41 textToAdd += '[quote]' + selection + '[/quote]\n\n';
41 textToAdd += '[quote]' + selection + '[/quote]\n';
42 42 }
43 43
44 44 var textAreaId = 'textarea';
45 45 $(textAreaId).val($(textAreaId).val()+ textToAdd);
46 46
47 47 var textarea = document.getElementsByTagName('textarea')[0];
48 48 $(textAreaId).focus();
49 49 moveCaretToEnd(textarea);
50 50
51 51 $("html, body").animate({ scrollTop: $(textAreaId).offset().top }, "slow");
52 52 }
53 53
54 54 function scrollToBottom() {
55 55 var $target = $('html,body');
56 56 $target.animate({scrollTop: $target.height()}, "fast");
57 57 }
58 58
59 59 $(document).ready(function() {
60 60 swapForm();
61 61 })
General Comments 0
You need to be logged in to leave comments. Login now