diff --git a/assets/css/base.css b/assets/css/base.css index 09370fa..169cda4 100644 --- a/assets/css/base.css +++ b/assets/css/base.css @@ -142,6 +142,9 @@ body { --color-setting-option-desc: var(--light, var(--color-gray-500)) var(--dark, var(--color-dt-gray-250)); --color-settings-theme-select-outline: var(--light, var(--color-primary-400)) var(--dark, var(--color-primary-400)); --color-settings-dropdown-option-bg: var(--light, var(--color-gray-200)) var(--dark, var(--color-dt-gray-400)); + + --tumblr-signpost-bg: var(--light, var(--color-gray-125)) var(--dark, var(--color-dt-gray-700)); + --tumblr-signpost-border: var(--light, var(--color-gray-300)) var(--dark, var(--color-dt-gray-500)); } html, body, .container { @@ -323,8 +326,9 @@ a.logo { .timeline, .blog-posts { display: flex; + flex-direction: column; + align-items: center; gap: 2em; - flex-wrap: wrap; max-width: 590px; } @@ -498,4 +502,4 @@ li.no-js .control-bar-dropdown-menu { .page-footer a { text-decoration: underline; -} \ No newline at end of file +} diff --git a/assets/css/timeline.css b/assets/css/timeline.css new file mode 100644 index 0000000..c2dd0cd --- /dev/null +++ b/assets/css/timeline.css @@ -0,0 +1,45 @@ +/* This file contains the styling for various Tumblr timeline objects */ + +.tumblr-signpost { + display: flex; + flex-direction: row; + align-items: center; + gap: 20px; + + width: 350px; + box-sizing: border-box; + overflow: hidden; + + margin: 0 20px; + padding: 20px 25px; + + background: var(--tumblr-signpost-bg); + color: var(--color-text); + border: 2px solid var(--tumblr-signpost-border); + border-radius: 10px; + + box-shadow: rgba(0,0,0,0.2) 0px 1px 3px; + } + + .tumblr-signpost svg { + min-width: max-content; + } + + .tumblr-signpost p { + line-height: 2; + font-size: 12px; + } + + .tumblr-signpost h3 { + font-weight: bold; + margin: 0; + margin-bottom: 10px; + font-size: 14px; + } + + + @media (max-width: 350px) { + .tumblr-signpost { + width: auto; + } + } diff --git a/src/priviblur_extractor/models/__init__.py b/src/priviblur_extractor/models/__init__.py index 34b5b05..a78f68b 100644 --- a/src/priviblur_extractor/models/__init__.py +++ b/src/priviblur_extractor/models/__init__.py @@ -1,3 +1,3 @@ -from . import base, blog, post, timelines +from . import base, blog, post, timelines, misc from .base import VERSION \ No newline at end of file diff --git a/src/priviblur_extractor/models/misc.py b/src/priviblur_extractor/models/misc.py new file mode 100644 index 0000000..655a3b9 --- /dev/null +++ b/src/priviblur_extractor/models/misc.py @@ -0,0 +1,15 @@ +from typing import NamedTuple, Optional + +class Signpost(NamedTuple): + title: str + description: Optional[str] = None + + def to_json_serialisable(self): + return { + "title": self.title, + "description": self.description + } + + @classmethod + def from_json(cls, json): + return cls(**json) diff --git a/src/priviblur_extractor/models/timelines.py b/src/priviblur_extractor/models/timelines.py index 1132deb..f729271 100644 --- a/src/priviblur_extractor/models/timelines.py +++ b/src/priviblur_extractor/models/timelines.py @@ -3,6 +3,7 @@ from . import base from .post import Post, ReplyNote, ReblogNote, LikeNote +from .misc import Signpost from. blog import Blog @@ -102,10 +103,12 @@ class Timeline(NamedTuple): def to_json_serialisable(self): elements = [] for element in self.elements: - if isinstance(element, Blog): + if isinstance(element, Post): + elements.append({"post": element.to_json_serialisable()}) + elif isinstance(element, Blog): elements.append({"blog": element.to_json_serialisable()}) else: - elements.append({"post": element.to_json_serialisable()}) + elements.append({"signpost": element.to_json_serialisable()}) next_ = self.next if next_: @@ -121,10 +124,12 @@ def to_json_serialisable(self): def from_json(cls, json): elements = [] for element in json["elements"]: - if blog := element.get("blog"): + if post := element.get("post"): + elements.append(Post.from_json(post)) + elif blog := element.get("blog"): elements.append(Blog.from_json(blog)) else: - elements.append(Post.from_json(element["post"])) + elements.append(Signpost.from_json(element["signpost"])) json["elements"] = elements diff --git a/src/priviblur_extractor/parse/collection_parsers.py b/src/priviblur_extractor/parse/collection_parsers.py index 8386cd7..9b89bd8 100644 --- a/src/priviblur_extractor/parse/collection_parsers.py +++ b/src/priviblur_extractor/parse/collection_parsers.py @@ -53,7 +53,12 @@ def parse(self): elements = [] total_raw_elements = len(self.target["elements"]) for element_index, element in enumerate(self.target["elements"]): - if result := items.parse_item(element, element_index, total_raw_elements): + if result := items.parse_item( + element, + element_index, + total_raw_elements, + use_parsers=(items.PostParser, items.SignpostParser) + ): elements.append(result) return models.timelines.Timeline( diff --git a/src/priviblur_extractor/parse/items.py b/src/priviblur_extractor/parse/items.py index 4c02789..16de047 100644 --- a/src/priviblur_extractor/parse/items.py +++ b/src/priviblur_extractor/parse/items.py @@ -349,6 +349,22 @@ def parse(self): ) +class SignpostParser: + def __init__(self, target) -> None: + self.target = target + + @classmethod + def process(cls, initial_data): + if initial_data.get("objectType") == "signpost_cta": + return cls(initial_data).parse() + + def parse(self): + return models.misc.Signpost( + title=self.target["display"]["title"], + description=helpers.dig_dict(self.target, ("resources", "description")), + ) + + def parse_item(element, element_index=0, total_elements=1, use_parsers=None): """Parses an item from Tumblr API's JSON response into a more usable structure""" item_number = f"({element_index + 1}/{total_elements})" diff --git a/src/templates/components/signpost.jinja b/src/templates/components/signpost.jinja new file mode 100644 index 0000000..378ed34 --- /dev/null +++ b/src/templates/components/signpost.jinja @@ -0,0 +1,7 @@ +
+ +
+

{{element.title}}

+

{{element.description or ""}}

+
+
\ No newline at end of file diff --git a/src/templates/macros/insert_content_list.jinja b/src/templates/macros/insert_content_list.jinja index 63b8830..8b2e87f 100644 --- a/src/templates/macros/insert_content_list.jinja +++ b/src/templates/macros/insert_content_list.jinja @@ -5,6 +5,8 @@ {%- if not element.is_advertisement -%} {%- include 'post/post.jinja' -%} {%- endif -%} + {% else %} + {%- include 'components/signpost.jinja' -%} {% endif %} {%- endfor -%} diff --git a/src/templates/timeline.jinja b/src/templates/timeline.jinja index 7cb57b3..a926a83 100644 --- a/src/templates/timeline.jinja +++ b/src/templates/timeline.jinja @@ -1,5 +1,8 @@ {% extends "base.jinja" %} {% from 'macros/insert_content_list.jinja' import insert_content_list with context %} + + +{% block head %}{% endblock %} {% block title %}{{title}}{% endblock%} {% block center %}