wordpress-markdown-blog-loader 1.7.3__tar.gz → 1.7.4__tar.gz
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.
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/PKG-INFO +2 -2
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/README.md +1 -1
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/pyproject.toml +1 -1
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/api.py +24 -12
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/blog.py +9 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/html_to_gutenberg.py +2 -3
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/new.py +20 -17
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader.egg-info/PKG-INFO +2 -2
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/tests/test_html_to_gutenberg.py +5 -1
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/LICENSE +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/setup.cfg +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/__init__.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/__main__.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/check_links.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/download.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/name_to_email.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/remove_newlines.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader/upload.py +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader.egg-info/SOURCES.txt +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader.egg-info/dependency_links.txt +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader.egg-info/entry_points.txt +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader.egg-info/requires.txt +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/src/wordpress_markdown_blog_loader.egg-info/top_level.txt +0 -0
- {wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/tests/test_blog.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wordpress-markdown-blog-loader
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.4
|
|
4
4
|
Summary: load markdown blogs into wordpress
|
|
5
5
|
Author-email: Mark van Holsteijn <markvanholsteijn@binx.io>
|
|
6
6
|
License: APL2
|
|
@@ -119,7 +119,7 @@ alias wp-md='docker run \
|
|
|
119
119
|
-v $HOME:$HOME \
|
|
120
120
|
-v $HOME/.wordpress.ini:/root/.wordpress.ini \
|
|
121
121
|
-v $PWD:/$PWD \
|
|
122
|
-
-w $PWD ghcr.io/binxio/wordpress-markdown-blog-loader:1.7.
|
|
122
|
+
-w $PWD ghcr.io/binxio/wordpress-markdown-blog-loader:1.7.4
|
|
123
123
|
```'
|
|
124
124
|
Assuming that your WordPress app password is stored in the 1password Private vault under the name `wordpress app password`
|
|
125
125
|
|
|
@@ -68,7 +68,7 @@ alias wp-md='docker run \
|
|
|
68
68
|
-v $HOME:$HOME \
|
|
69
69
|
-v $HOME/.wordpress.ini:/root/.wordpress.ini \
|
|
70
70
|
-v $PWD:/$PWD \
|
|
71
|
-
-w $PWD ghcr.io/binxio/wordpress-markdown-blog-loader:1.7.
|
|
71
|
+
-w $PWD ghcr.io/binxio/wordpress-markdown-blog-loader:1.7.4
|
|
72
72
|
```'
|
|
73
73
|
Assuming that your WordPress app password is stored in the 1password Private vault under the name `wordpress app password`
|
|
74
74
|
|
{wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/pyproject.toml
RENAMED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "wordpress-markdown-blog-loader"
|
|
7
|
-
version = "1.7.
|
|
7
|
+
version = "1.7.4"
|
|
8
8
|
authors = [{name = "Mark van Holsteijn", email = "markvanholsteijn@binx.io"}]
|
|
9
9
|
license = {text = "APL2"}
|
|
10
10
|
description = "load markdown blogs into wordpress"
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import configparser
|
|
2
|
-
import json
|
|
3
2
|
import logging
|
|
4
3
|
import mimetypes
|
|
5
4
|
import os
|
|
6
5
|
import re
|
|
7
|
-
import
|
|
6
|
+
import subprocess
|
|
8
7
|
from datetime import datetime
|
|
9
|
-
from functools import cache
|
|
8
|
+
from functools import cache, lru_cache
|
|
10
9
|
from os.path import expanduser
|
|
11
10
|
from pathlib import Path
|
|
12
11
|
from typing import List, Dict, Iterator
|
|
@@ -26,6 +25,21 @@ def get_default_host() -> Optional[str]:
|
|
|
26
25
|
return config.defaults().get("host")
|
|
27
26
|
|
|
28
27
|
|
|
28
|
+
@lru_cache
|
|
29
|
+
def get_from_1password(password: str) -> str:
|
|
30
|
+
"""
|
|
31
|
+
returns the password from 1password vault, if the password has the op:// prefix.
|
|
32
|
+
"""
|
|
33
|
+
if not password.startswith("op://"):
|
|
34
|
+
return password
|
|
35
|
+
result = subprocess.run(
|
|
36
|
+
["op", "read", password],
|
|
37
|
+
check=True,
|
|
38
|
+
capture_output=True,
|
|
39
|
+
)
|
|
40
|
+
return result.stdout.decode("utf-8").rstrip("\n")
|
|
41
|
+
|
|
42
|
+
|
|
29
43
|
def get_password(host: str) -> Optional[str]:
|
|
30
44
|
"""
|
|
31
45
|
Returns a password from the environment variable for the specified host.
|
|
@@ -46,10 +60,10 @@ def get_password(host: str) -> Optional[str]:
|
|
|
46
60
|
'default_password'
|
|
47
61
|
"""
|
|
48
62
|
h = re.sub(r"[^a-zA-Z-0-9]", "_", host).upper()
|
|
49
|
-
if result := os.getenv(f"WP_APP_PASSWORD_{h}"):
|
|
50
|
-
return result
|
|
63
|
+
if result := os.getenv(f"WP_APP_PASSWORD_{h}", os.getenv("WP_APP_PASSWORD")):
|
|
64
|
+
return get_from_1password(result)
|
|
51
65
|
|
|
52
|
-
return
|
|
66
|
+
return None
|
|
53
67
|
|
|
54
68
|
|
|
55
69
|
class WordpressEndpoint:
|
|
@@ -290,7 +304,7 @@ class Wordpress(object):
|
|
|
290
304
|
self._media: List[Medium] = {}
|
|
291
305
|
self.headers = {
|
|
292
306
|
"accept": "application/json",
|
|
293
|
-
"User-Agent": "wordpress-blog-uploader/" + self.app_version
|
|
307
|
+
"User-Agent": "wordpress-blog-uploader/" + self.app_version,
|
|
294
308
|
}
|
|
295
309
|
self.session = requests.Session()
|
|
296
310
|
|
|
@@ -436,7 +450,7 @@ class Wordpress(object):
|
|
|
436
450
|
@property
|
|
437
451
|
@cache
|
|
438
452
|
def industries_taxonomy_by_id(self) -> Dict[str, int]:
|
|
439
|
-
return
|
|
453
|
+
return {id: slug for slug, id in self.industries_taxonomy.items()}
|
|
440
454
|
|
|
441
455
|
@property
|
|
442
456
|
@cache
|
|
@@ -446,7 +460,7 @@ class Wordpress(object):
|
|
|
446
460
|
@property
|
|
447
461
|
@cache
|
|
448
462
|
def partners_taxonomy_by_id(self) -> Dict[str, int]:
|
|
449
|
-
return
|
|
463
|
+
return {id: slug for slug, id in self.partners_taxonomy.items()}
|
|
450
464
|
|
|
451
465
|
@property
|
|
452
466
|
@cache
|
|
@@ -456,8 +470,7 @@ class Wordpress(object):
|
|
|
456
470
|
@property
|
|
457
471
|
@cache
|
|
458
472
|
def capabilities_by_id(self) -> Dict[str, int]:
|
|
459
|
-
return
|
|
460
|
-
|
|
473
|
+
return {id: slug for slug, id in self.capabilities.items()}
|
|
461
474
|
|
|
462
475
|
@property
|
|
463
476
|
@cache
|
|
@@ -647,7 +660,6 @@ class Wordpress(object):
|
|
|
647
660
|
)
|
|
648
661
|
)
|
|
649
662
|
|
|
650
|
-
|
|
651
663
|
def get_tag_id_by_name(self, tag: str) -> str:
|
|
652
664
|
if tag in self.tags:
|
|
653
665
|
return self.tags[tag]
|
|
@@ -230,6 +230,14 @@ class Blog(object):
|
|
|
230
230
|
def tags(self, tags: list[str]):
|
|
231
231
|
self.blog.metadata["tags"] = tags
|
|
232
232
|
|
|
233
|
+
@property
|
|
234
|
+
def capabilities(self):
|
|
235
|
+
return self.blog.metadata.get("capabilities", [])
|
|
236
|
+
|
|
237
|
+
@capabilities.setter
|
|
238
|
+
def capabilities(self, capabilities: list[str]):
|
|
239
|
+
self.blog.metadata["capabilities"] = capabilities
|
|
240
|
+
|
|
233
241
|
@property
|
|
234
242
|
def guid(self):
|
|
235
243
|
return self.blog.metadata.get("guid")
|
|
@@ -401,6 +409,7 @@ class Blog(object):
|
|
|
401
409
|
"status": self.status,
|
|
402
410
|
"author": author.id,
|
|
403
411
|
"categories": [wp.get_category_id_by_name(c) for c in self.categories],
|
|
412
|
+
"capabilities": [wp.get_capability_id_by_name(c) for c in self.capabilities],
|
|
404
413
|
"tags": [wp.get_tag_id_by_name(c) for c in self.tags],
|
|
405
414
|
"acf": {"show_header_image": bool(self.image)},
|
|
406
415
|
"industries_taxonomy": [wp.get_industry_by_name(c) for c in self.industries],
|
|
@@ -24,7 +24,7 @@ def _wrap_paragraph(element):
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def _wrap_quote(element):
|
|
27
|
-
element["class"] = ["wp-block-quote"]
|
|
27
|
+
element["class"] = ["wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"]
|
|
28
28
|
# Wrap nested elements
|
|
29
29
|
for child in list(element.contents):
|
|
30
30
|
if isinstance(child, (NavigableString, Comment)):
|
|
@@ -34,8 +34,7 @@ def _wrap_quote(element):
|
|
|
34
34
|
# Since _wrap_in_gutenberg_comments returns a string,
|
|
35
35
|
# we replace the child with a NavigableString of that result
|
|
36
36
|
wrapped_child = _wrap_in_gutenberg_comments(child)
|
|
37
|
-
|
|
38
|
-
child.replace_with(BeautifulSoup(wrapped_child, "html.parser"))
|
|
37
|
+
child.replace_with(BeautifulSoup(wrapped_child, "html.parser"))
|
|
39
38
|
|
|
40
39
|
return f"<!-- wp:quote -->\n{str(element)}\n<!-- /wp:quote -->"
|
|
41
40
|
|
|
@@ -42,6 +42,7 @@ class ImageType(click.ParamType):
|
|
|
42
42
|
@click.option("--email", required=False, help="of the author")
|
|
43
43
|
@click.option("--image", required=False, type=ImageType(), help="for the banner")
|
|
44
44
|
@click.option("--image-credits", required=False, type=str, help="for the used image")
|
|
45
|
+
@click.option("--capability", required=False, multiple=True, help="for the used capabilities selection")
|
|
45
46
|
@click.option(
|
|
46
47
|
"--brand",
|
|
47
48
|
type=click.Choice(["xebia.com", "binx.io"]),
|
|
@@ -49,12 +50,12 @@ class ImageType(click.ParamType):
|
|
|
49
50
|
default="xebia.com",
|
|
50
51
|
help="of the banner",
|
|
51
52
|
)
|
|
52
|
-
def command(title, subtitle, author, image, brand, email, image_credits):
|
|
53
|
+
def command(title, subtitle, author, image, brand, email, image_credits, capability):
|
|
53
54
|
"""
|
|
54
55
|
a new frontmatter blog
|
|
55
56
|
|
|
56
57
|
the index.md will be written in a subdirectory with the name of the slug for the blog.
|
|
57
|
-
The slug is created from the title. The image will be resized and cropped to
|
|
58
|
+
The slug is created from the title. The image will be resized and cropped to 1440x460.
|
|
58
59
|
"""
|
|
59
60
|
slug = slugify(title)
|
|
60
61
|
|
|
@@ -78,6 +79,8 @@ def command(title, subtitle, author, image, brand, email, image_credits):
|
|
|
78
79
|
blog.date = (datetime.now().astimezone() + timedelta(days=7)).replace(
|
|
79
80
|
hour=0, minute=0, second=0, microsecond=0
|
|
80
81
|
)
|
|
82
|
+
if capability:
|
|
83
|
+
blog.capabilities = list(capability)
|
|
81
84
|
|
|
82
85
|
if not blog.title:
|
|
83
86
|
click.echo("a title is required", err=True)
|
|
@@ -100,26 +103,26 @@ def command(title, subtitle, author, image, brand, email, image_credits):
|
|
|
100
103
|
|
|
101
104
|
def save_og_image(image: Image, path: Path) -> Path:
|
|
102
105
|
"""
|
|
103
|
-
save the image to be the perfect og image size:
|
|
106
|
+
save the image to be the perfect og image size: 1440x460px
|
|
104
107
|
"""
|
|
105
108
|
width, height = image.size
|
|
106
|
-
if width !=
|
|
107
|
-
new_height = int(height *
|
|
108
|
-
logging.info("resizing %dx%d to %dx%d", width, height,
|
|
109
|
-
image = image.resize((
|
|
110
|
-
width =
|
|
109
|
+
if width != 1440:
|
|
110
|
+
new_height = int(height * 1440 / width)
|
|
111
|
+
logging.info("resizing %dx%d to %dx%d", width, height, 1440, new_height)
|
|
112
|
+
image = image.resize((1440, new_height))
|
|
113
|
+
width = 1440
|
|
111
114
|
width, height = image.size
|
|
112
115
|
|
|
113
|
-
if height >
|
|
114
|
-
logging.info("cropping to maximum height of
|
|
115
|
-
top = int((height -
|
|
116
|
-
bottom =
|
|
117
|
-
image = image.crop((0, top,
|
|
116
|
+
if height > 460:
|
|
117
|
+
logging.info("cropping to maximum height of 460px")
|
|
118
|
+
top = int((height - 460) / 2)
|
|
119
|
+
bottom = 460 + top
|
|
120
|
+
image = image.crop((0, top, 1440, bottom))
|
|
118
121
|
width, height = image.size
|
|
119
122
|
|
|
120
|
-
if height <
|
|
121
|
-
new_image = Image.new("RGBA", (
|
|
122
|
-
new_image.paste(image, (0, int((
|
|
123
|
+
if height < 460:
|
|
124
|
+
new_image = Image.new("RGBA", (1440, 460), (255, 0, 0, 0))
|
|
125
|
+
new_image.paste(image, (0, int((460 - height) / 2)))
|
|
123
126
|
image = new_image
|
|
124
127
|
|
|
125
128
|
path.parent.mkdir(exist_ok=True, parents=True)
|
|
@@ -144,7 +147,7 @@ def update_banner_command(blog, image, brand):
|
|
|
144
147
|
"""
|
|
145
148
|
of the blog.
|
|
146
149
|
|
|
147
|
-
reads the image, crops it to the
|
|
150
|
+
reads the image, crops it to the 1440x460 dimensions and updates the blog's banner property.
|
|
148
151
|
Regenerates and updates the og-banner too.
|
|
149
152
|
"""
|
|
150
153
|
path = Path(blog).joinpath("index.md")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: wordpress-markdown-blog-loader
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.4
|
|
4
4
|
Summary: load markdown blogs into wordpress
|
|
5
5
|
Author-email: Mark van Holsteijn <markvanholsteijn@binx.io>
|
|
6
6
|
License: APL2
|
|
@@ -119,7 +119,7 @@ alias wp-md='docker run \
|
|
|
119
119
|
-v $HOME:$HOME \
|
|
120
120
|
-v $HOME/.wordpress.ini:/root/.wordpress.ini \
|
|
121
121
|
-v $PWD:/$PWD \
|
|
122
|
-
-w $PWD ghcr.io/binxio/wordpress-markdown-blog-loader:1.7.
|
|
122
|
+
-w $PWD ghcr.io/binxio/wordpress-markdown-blog-loader:1.7.4
|
|
123
123
|
```'
|
|
124
124
|
Assuming that your WordPress app password is stored in the 1password Private vault under the name `wordpress app password`
|
|
125
125
|
|
|
@@ -97,7 +97,10 @@ class TestGutenbergWrapFunctions(unittest.TestCase):
|
|
|
97
97
|
soup = BeautifulSoup("<blockquote>quotie quote</blockquote>", "html.parser")
|
|
98
98
|
elem = soup.blockquote
|
|
99
99
|
result = _wrap_quote(elem)
|
|
100
|
-
self.assertEqual(
|
|
100
|
+
self.assertEqual(
|
|
101
|
+
result,
|
|
102
|
+
'<!-- wp:quote -->\n<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">quotie quote</blockquote>\n<!-- /wp:quote -->',
|
|
103
|
+
)
|
|
101
104
|
|
|
102
105
|
def test_wrap_quote_nested_elements(self):
|
|
103
106
|
html = "<blockquote><p>Quote line 1</p><p>Quote line 2</p></blockquote>"
|
|
@@ -154,5 +157,6 @@ class TestConvertFunction(unittest.TestCase):
|
|
|
154
157
|
self.assertIn("<!-- wp:heading -->", result)
|
|
155
158
|
self.assertIn("<!-- wp:code -->", result)
|
|
156
159
|
|
|
160
|
+
|
|
157
161
|
if __name__ == "__main__":
|
|
158
162
|
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{wordpress_markdown_blog_loader-1.7.3 → wordpress_markdown_blog_loader-1.7.4}/tests/test_blog.py
RENAMED
|
File without changes
|