punkweb-bb 0.5.0__py3-none-any.whl → 0.5.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. punkweb_bb/__pycache__/__init__.cpython-313.pyc +0 -0
  2. punkweb_bb/__pycache__/admin.cpython-313.pyc +0 -0
  3. punkweb_bb/__pycache__/admin_forms.cpython-313.pyc +0 -0
  4. punkweb_bb/__pycache__/apps.cpython-313.pyc +0 -0
  5. punkweb_bb/__pycache__/bbcode.cpython-313.pyc +0 -0
  6. punkweb_bb/__pycache__/decorators.cpython-313.pyc +0 -0
  7. punkweb_bb/__pycache__/forms.cpython-313.pyc +0 -0
  8. punkweb_bb/__pycache__/guests.cpython-313.pyc +0 -0
  9. punkweb_bb/__pycache__/middleware.cpython-313.pyc +0 -0
  10. punkweb_bb/__pycache__/mixins.cpython-313.pyc +0 -0
  11. punkweb_bb/__pycache__/models.cpython-311.pyc +0 -0
  12. punkweb_bb/__pycache__/models.cpython-313.pyc +0 -0
  13. punkweb_bb/__pycache__/pagination.cpython-313.pyc +0 -0
  14. punkweb_bb/__pycache__/response.cpython-313.pyc +0 -0
  15. punkweb_bb/__pycache__/searching.cpython-313.pyc +0 -0
  16. punkweb_bb/__pycache__/settings.cpython-313.pyc +0 -0
  17. punkweb_bb/__pycache__/signals.cpython-313.pyc +0 -0
  18. punkweb_bb/__pycache__/tests.cpython-313.pyc +0 -0
  19. punkweb_bb/__pycache__/urls.cpython-313.pyc +0 -0
  20. punkweb_bb/__pycache__/utils.cpython-313.pyc +0 -0
  21. punkweb_bb/__pycache__/views.cpython-311.pyc +0 -0
  22. punkweb_bb/__pycache__/views.cpython-313.pyc +0 -0
  23. punkweb_bb/__pycache__/widgets.cpython-313.pyc +0 -0
  24. punkweb_bb/bbcode.py +16 -4
  25. punkweb_bb/migrations/0008_alter_groupstyle_username_style.py +18 -0
  26. punkweb_bb/migrations/__pycache__/0001_initial.cpython-313.pyc +0 -0
  27. punkweb_bb/migrations/__pycache__/0002_thread_view_count.cpython-313.pyc +0 -0
  28. punkweb_bb/migrations/__pycache__/0003_alter_thread_options.cpython-313.pyc +0 -0
  29. punkweb_bb/migrations/__pycache__/0004_groupstyle.cpython-313.pyc +0 -0
  30. punkweb_bb/migrations/__pycache__/0005_alter_thread_options.cpython-313.pyc +0 -0
  31. punkweb_bb/migrations/__pycache__/0006_remove_boardprofile__signature_rendered_and_more.cpython-313.pyc +0 -0
  32. punkweb_bb/migrations/__pycache__/0007_boardprofile_bio.cpython-313.pyc +0 -0
  33. punkweb_bb/migrations/__pycache__/0008_alter_groupstyle_username_style.cpython-311.pyc +0 -0
  34. punkweb_bb/migrations/__pycache__/0008_alter_groupstyle_username_style.cpython-313.pyc +0 -0
  35. punkweb_bb/migrations/__pycache__/0009_report.cpython-313.pyc +0 -0
  36. punkweb_bb/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  37. punkweb_bb/models.py +6 -3
  38. punkweb_bb/settings.py +2 -0
  39. punkweb_bb/static/punkweb_bb/css/bbcode-editor-content.css +4 -0
  40. punkweb_bb/static/punkweb_bb/css/members.css +6 -0
  41. punkweb_bb/static/punkweb_bb/css/punkweb.css +4 -0
  42. punkweb_bb/static/punkweb_bb/vendor/prism-duotone-sea.css +170 -0
  43. punkweb_bb/static/punkweb_bb/vendor/punkweb-ui.min.css +1 -1
  44. punkweb_bb/templates/punkweb_bb/base.html +84 -96
  45. punkweb_bb/templates/punkweb_bb/base_delete_dialog.html +13 -10
  46. punkweb_bb/templates/punkweb_bb/base_dialog.html +6 -6
  47. punkweb_bb/templates/punkweb_bb/bbcode.html +12 -14
  48. punkweb_bb/templates/punkweb_bb/category_create.html +26 -27
  49. punkweb_bb/templates/punkweb_bb/category_update.html +27 -30
  50. punkweb_bb/templates/punkweb_bb/components/pagination_controls.html +36 -44
  51. punkweb_bb/templates/punkweb_bb/components/profile_image.html +8 -8
  52. punkweb_bb/templates/punkweb_bb/forms/inline_form.html +5 -5
  53. punkweb_bb/templates/punkweb_bb/forms/stacked_form.html +35 -32
  54. punkweb_bb/templates/punkweb_bb/index.html +205 -211
  55. punkweb_bb/templates/punkweb_bb/login.html +24 -30
  56. punkweb_bb/templates/punkweb_bb/members.html +57 -61
  57. punkweb_bb/templates/punkweb_bb/partials/category_delete.html +3 -3
  58. punkweb_bb/templates/punkweb_bb/partials/post_delete.html +3 -3
  59. punkweb_bb/templates/punkweb_bb/partials/post_update.html +12 -11
  60. punkweb_bb/templates/punkweb_bb/partials/shout_delete.html +3 -3
  61. punkweb_bb/templates/punkweb_bb/partials/subcategory_delete.html +3 -3
  62. punkweb_bb/templates/punkweb_bb/partials/thread_delete.html +3 -3
  63. punkweb_bb/templates/punkweb_bb/partials/thread_move.html +13 -12
  64. punkweb_bb/templates/punkweb_bb/profile.html +73 -84
  65. punkweb_bb/templates/punkweb_bb/search.html +12 -16
  66. punkweb_bb/templates/punkweb_bb/settings.html +29 -36
  67. punkweb_bb/templates/punkweb_bb/shoutbox/shout_list.html +17 -19
  68. punkweb_bb/templates/punkweb_bb/shoutbox/shoutbox.html +18 -29
  69. punkweb_bb/templates/punkweb_bb/signup.html +24 -30
  70. punkweb_bb/templates/punkweb_bb/subcategory.html +114 -132
  71. punkweb_bb/templates/punkweb_bb/subcategory_create.html +32 -39
  72. punkweb_bb/templates/punkweb_bb/subcategory_update.html +33 -42
  73. punkweb_bb/templates/punkweb_bb/thread.html +207 -238
  74. punkweb_bb/templates/punkweb_bb/thread_create.html +36 -43
  75. punkweb_bb/templates/punkweb_bb/thread_update.html +36 -45
  76. punkweb_bb/templates/punkweb_bb/widgets/markdown-editor.html +3 -1
  77. punkweb_bb/templatetags/__pycache__/__init__.cpython-313.pyc +0 -0
  78. punkweb_bb/templatetags/__pycache__/can_delete.cpython-313.pyc +0 -0
  79. punkweb_bb/templatetags/__pycache__/can_edit.cpython-313.pyc +0 -0
  80. punkweb_bb/templatetags/__pycache__/can_post.cpython-313.pyc +0 -0
  81. punkweb_bb/templatetags/__pycache__/humanize_int.cpython-313.pyc +0 -0
  82. punkweb_bb/templatetags/__pycache__/punkweb_bb.cpython-313.pyc +0 -0
  83. punkweb_bb/templatetags/__pycache__/render.cpython-313.pyc +0 -0
  84. punkweb_bb/templatetags/__pycache__/styled_group_name.cpython-313.pyc +0 -0
  85. punkweb_bb/templatetags/__pycache__/styled_username.cpython-313.pyc +0 -0
  86. punkweb_bb/tests.py +21 -0
  87. punkweb_bb/views.py +27 -27
  88. {punkweb_bb-0.5.0.dist-info → punkweb_bb-0.5.2.dist-info}/METADATA +93 -37
  89. {punkweb_bb-0.5.0.dist-info → punkweb_bb-0.5.2.dist-info}/RECORD +92 -49
  90. {punkweb_bb-0.5.0.dist-info → punkweb_bb-0.5.2.dist-info}/WHEEL +1 -1
  91. {punkweb_bb-0.5.0.dist-info → punkweb_bb-0.5.2.dist-info/licenses}/LICENSE +0 -0
  92. {punkweb_bb-0.5.0.dist-info → punkweb_bb-0.5.2.dist-info}/top_level.txt +0 -0
punkweb_bb/bbcode.py CHANGED
@@ -1,5 +1,13 @@
1
1
  import bbcode
2
2
 
3
+ from punkweb_bb.settings import ALLOWED_URL_SCHEMES
4
+
5
+ def safe_url(href):
6
+ href = (href or "").strip()
7
+ if not href:
8
+ return None
9
+ lower = href.lower()
10
+ return href if any(lower.startswith(s + ":") for s in ALLOWED_URL_SCHEMES) else None
3
11
 
4
12
  def add_font_tag(parser):
5
13
  def _render_font(name, value, options, parent, context):
@@ -40,19 +48,23 @@ def add_shadow_tag(parser):
40
48
 
41
49
  parser.add_formatter("shadow", _render_shadow)
42
50
 
43
-
44
51
  def add_url_tag(parser):
45
52
  def _render_url(name, value, options, parent, context):
46
53
  if "url" in options:
47
- url = options["url"]
54
+ url = safe_url(options["url"])
55
+ if url is None:
56
+ return value
48
57
  return f'<a href="{url}">{value}</a>'
49
- return f'<a href="{value}">{value}</a>'
58
+
59
+ url = safe_url(value)
60
+ if url is None:
61
+ return value
62
+ return f'<a href="{url}">{value}</a>'
50
63
 
51
64
  parser.add_formatter(
52
65
  "url", _render_url, replace_links=False, replace_cosmetic=False
53
66
  )
54
67
 
55
-
56
68
  def add_quote_tag(parser):
57
69
  def _render_quote(name, value, options, parent, context):
58
70
  if "quote" in options:
@@ -0,0 +1,18 @@
1
+ # Generated by Django 4.2.11 on 2024-10-08 21:21
2
+
3
+ from django.db import migrations, models
4
+
5
+
6
+ class Migration(migrations.Migration):
7
+
8
+ dependencies = [
9
+ ('punkweb_bb', '0007_boardprofile_bio'),
10
+ ]
11
+
12
+ operations = [
13
+ migrations.AlterField(
14
+ model_name='groupstyle',
15
+ name='username_style',
16
+ field=models.TextField(help_text='BBCode style for the username. Use {USER} as a placeholder for the username. Example: [b]{USER}[/b]'),
17
+ ),
18
+ ]
punkweb_bb/models.py CHANGED
@@ -195,9 +195,10 @@ class Post(UUIDPrimaryKeyMixin, TimestampMixin):
195
195
  return thread_url
196
196
 
197
197
  def save(self, *args, **kwargs):
198
- if self.thread.is_closed:
199
- raise ValidationError("Cannot add posts to a closed thread.")
200
198
  if self._state.adding:
199
+ if self.thread.is_closed:
200
+ raise ValidationError("Cannot add posts to a closed thread.")
201
+
201
202
  self.thread.last_post_created_at = timezone.now()
202
203
  self.thread.save()
203
204
  super().save(*args, **kwargs)
@@ -223,7 +224,9 @@ class GroupStyle(UUIDPrimaryKeyMixin, TimestampMixin):
223
224
  default=0,
224
225
  help_text="Highest priority is displayed",
225
226
  )
226
- username_style = models.TextField()
227
+ username_style = models.TextField(
228
+ help_text="BBCode style for the username. Use {USER} as a placeholder for the username. Example: [b]{USER}[/b]"
229
+ )
227
230
 
228
231
  class Meta:
229
232
  ordering = ("-priority",)
punkweb_bb/settings.py CHANGED
@@ -13,3 +13,5 @@ SHOUTBOX_POLLING_INTERVAL = PUNKWEB_BB.get("SHOUTBOX_POLLING_INTERVAL", 30)
13
13
  DISCORD_WIDGET_ENABLED = PUNKWEB_BB.get("DISCORD_WIDGET_ENABLED", False)
14
14
  DISCORD_WIDGET_THEME = PUNKWEB_BB.get("DISCORD_WIDGET_THEME", "dark")
15
15
  DISCORD_SERVER_ID = PUNKWEB_BB.get("DISCORD_SERVER_ID", None)
16
+ # allow listing `javascript` will enable the weaponization of shoutbox bbcode.
17
+ ALLOWED_URL_SCHEMES = PUNKWEB_BB.get("ALLOWED_URL_SCHEMES", ["http", "https"])
@@ -72,6 +72,10 @@ code {
72
72
  direction: ltr;
73
73
  }
74
74
 
75
+ pre code {
76
+ font-size: 0.75rem;
77
+ }
78
+
75
79
  blockquote {
76
80
  background: #f1f3f5;
77
81
  margin: 0.25rem 0;
@@ -42,3 +42,9 @@
42
42
  .members__user__stat__value {
43
43
  color: var(--oc-gray-9);
44
44
  }
45
+
46
+ @media screen and (max-width: 768px) {
47
+ .members__header {
48
+ flex-direction: column;
49
+ }
50
+ }
@@ -154,3 +154,7 @@ hr {
154
154
  margin: 0;
155
155
  padding: 0;
156
156
  }
157
+
158
+ pre[class*="language-"] {
159
+ font-size: 0.75rem;
160
+ }
@@ -0,0 +1,170 @@
1
+ code[class*='language-'],
2
+ pre[class*='language-'] {
3
+ font-family: Consolas, Menlo, Monaco, 'Andale Mono WT', 'Andale Mono', 'Lucida Console', 'Lucida Sans Typewriter',
4
+ 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Liberation Mono', 'Nimbus Mono L', 'Courier New', Courier,
5
+ monospace;
6
+ font-size: 14px;
7
+ line-height: 1.375;
8
+ direction: ltr;
9
+ text-align: left;
10
+ white-space: pre;
11
+ word-spacing: normal;
12
+ word-break: normal;
13
+
14
+ -moz-tab-size: 4;
15
+ -o-tab-size: 4;
16
+ tab-size: 4;
17
+
18
+ -webkit-hyphens: none;
19
+ -moz-hyphens: none;
20
+ -ms-hyphens: none;
21
+ hyphens: none;
22
+ background: oklch(27.8% 0.033 256.848); /* gray 800 */
23
+ color: oklch(87.2% 0.01 258.338); /* gray 400 */
24
+ }
25
+
26
+ pre > code[class*='language-'] {
27
+ font-size: 1em;
28
+ }
29
+
30
+ pre[class*='language-']::-moz-selection,
31
+ pre[class*='language-'] ::-moz-selection,
32
+ code[class*='language-']::-moz-selection,
33
+ code[class*='language-'] ::-moz-selection {
34
+ text-shadow: none;
35
+ background: oklch(50% 0.134 242.749); /* sky 700 */
36
+ }
37
+
38
+ pre[class*='language-']::selection,
39
+ pre[class*='language-'] ::selection,
40
+ code[class*='language-']::selection,
41
+ code[class*='language-'] ::selection {
42
+ text-shadow: none;
43
+ background: oklch(50% 0.134 242.749); /* sky 700 */
44
+ }
45
+
46
+ /* Code blocks */
47
+ pre[class*='language-'] {
48
+ padding: 1em;
49
+ margin: 0.5em 0;
50
+ overflow: auto;
51
+ }
52
+
53
+ /* Inline code */
54
+ :not(pre) > code[class*='language-'] {
55
+ padding: 0.1em;
56
+ border-radius: 0.3em;
57
+ }
58
+
59
+ .token.comment,
60
+ .token.prolog,
61
+ .token.doctype,
62
+ .token.cdata {
63
+ color: oklch(70.7% 0.022 261.325); /* gray 400 */
64
+ }
65
+
66
+ .token.punctuation {
67
+ color: oklch(70.7% 0.022 261.325); /* gray 400 */
68
+ }
69
+
70
+ .token.namespace {
71
+ opacity: 0.7;
72
+ }
73
+
74
+ .token.tag,
75
+ .token.operator,
76
+ .token.number {
77
+ color: oklch(69.6% 0.17 162.48); /* emerald 500 */
78
+ }
79
+
80
+ .token.property,
81
+ .token.function {
82
+ color: oklch(87.2% 0.01 258.338); /* gray 400 */
83
+ }
84
+
85
+ .token.tag-id,
86
+ .token.selector,
87
+ .token.atrule-id {
88
+ color: oklch(95.1% 0.026 236.824); /* sky 100 */
89
+ }
90
+
91
+ code.language-javascript,
92
+ .token.attr-name {
93
+ color: oklch(90.1% 0.058 230.902); /* sky 200 */
94
+ }
95
+
96
+ code.language-css,
97
+ code.language-scss,
98
+ .token.boolean,
99
+ .token.string,
100
+ .token.entity,
101
+ .token.url,
102
+ .language-css .token.string,
103
+ .language-scss .token.string,
104
+ .style .token.string,
105
+ .token.attr-value,
106
+ .token.keyword,
107
+ .token.control,
108
+ .token.directive,
109
+ .token.unit,
110
+ .token.statement,
111
+ .token.regex,
112
+ .token.atrule {
113
+ color: oklch(84.5% 0.143 164.978); /* emerald 300 */
114
+ }
115
+
116
+ .token.placeholder,
117
+ .token.variable {
118
+ color: oklch(84.5% 0.143 164.978); /* emerald 300 */
119
+ }
120
+
121
+ .token.deleted {
122
+ text-decoration: line-through;
123
+ }
124
+
125
+ .token.inserted {
126
+ border-bottom: 1px dotted oklch(95.1% 0.026 236.824); /* sky 100 */
127
+ text-decoration: none;
128
+ }
129
+
130
+ .token.italic {
131
+ font-style: italic;
132
+ }
133
+
134
+ .token.important,
135
+ .token.bold {
136
+ font-weight: bold;
137
+ }
138
+
139
+ .token.important {
140
+ color: oklch(74.6% 0.16 232.661); /* sky 400 */
141
+ }
142
+
143
+ .token.entity {
144
+ cursor: help;
145
+ }
146
+
147
+ pre > code.highlight {
148
+ outline: 0.4em solid oklch(58.8% 0.158 241.966); /* sky 600 */
149
+ outline-offset: 0.4em;
150
+ }
151
+
152
+ /* overrides color-values for the Line Numbers plugin
153
+ * http://prismjs.com/plugins/line-numbers/
154
+ */
155
+ .line-numbers.line-numbers .line-numbers-rows {
156
+ border-right-color: oklch(44.6% 0.03 256.802); /* gray 600 */
157
+ }
158
+
159
+ .line-numbers .line-numbers-rows > span:before {
160
+ color: oklch(55.1% 0.027 264.364); /* gray 500 */
161
+ }
162
+
163
+ /* overrides color-values for the Line Highlight plugin
164
+ * http://prismjs.com/plugins/line-highlight/
165
+ */
166
+ .line-highlight.line-highlight {
167
+ background: rgba(10, 163, 112, 0.2);
168
+ background: -webkit-linear-gradient(left, rgba(10, 163, 112, 0.2) 70%, rgba(10, 163, 112, 0));
169
+ background: linear-gradient(to right, rgba(10, 163, 112, 0.2) 70%, rgba(10, 163, 112, 0));
170
+ }