- Create Economist SubmissionTracking package correctly: * mainArticle = full blog post content * coverLetter = 216-word SIR— letter * Links to blog post via blogPostId - Archive 'Letter to The Economist' from blog posts (it's the cover letter) - Fix date display on article cards (use published_at) - Target publication already displaying via blue badge Database changes: - Make blogPostId optional in SubmissionTracking model - Economist package ID: 68fa85ae49d4900e7f2ecd83 - Le Monde package ID: 68fa2abd2e6acd5691932150 Next: Enhanced modal with tabs, validation, export 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
67 lines
1.7 KiB
Python
67 lines
1.7 KiB
Python
import os
|
|
import platform
|
|
|
|
_WINDOWS_PLATFORM = platform.system() == "Windows"
|
|
|
|
|
|
def combine(path1: str, path2) -> str:
|
|
if not path1:
|
|
return path2
|
|
return "{}/{}".format(path1.rstrip("/"), path2.lstrip("/"))
|
|
|
|
|
|
def split(path: str) -> tuple[str, str]:
|
|
if "/" not in path:
|
|
return ("", path)
|
|
split = path.rsplit("/", 1)
|
|
return (split[0] or "/", split[1])
|
|
|
|
|
|
def dirname(path: str) -> str:
|
|
return split(path)[0]
|
|
|
|
|
|
def basename(path: str) -> str:
|
|
return split(path)[1]
|
|
|
|
|
|
def forcedir(path: str) -> str:
|
|
# Ensure the path ends with a trailing forward slash.
|
|
if not path.endswith("/"):
|
|
return path + "/"
|
|
return path
|
|
|
|
|
|
def abspath(path: str) -> str:
|
|
# FS objects have no concept of a *current directory*. This simply
|
|
# ensures the path starts with a forward slash.
|
|
if not path.startswith("/"):
|
|
return "/" + path
|
|
return path
|
|
|
|
|
|
def isbase(path1: str, path2: str) -> bool:
|
|
# Check if `path1` is a base or prefix of `path2`.
|
|
_path1 = forcedir(abspath(path1))
|
|
_path2 = forcedir(abspath(path2))
|
|
return _path2.startswith(_path1)
|
|
|
|
|
|
def frombase(path1: str, path2: str) -> str:
|
|
# Get the final path of `path2` that isn't in `path1`.
|
|
if not isbase(path1, path2):
|
|
raise ValueError(f"path1 must be a prefix of path2: {path1!r} vs {path2!r}")
|
|
return path2[len(path1) :]
|
|
|
|
|
|
def relpath(path: str) -> str:
|
|
return path.lstrip("/")
|
|
|
|
|
|
def normpath(path: str) -> str:
|
|
normalized = os.path.normpath(path)
|
|
if _WINDOWS_PLATFORM:
|
|
# os.path.normpath converts backslashes to forward slashes on Windows
|
|
# but we want forward slashes, so we convert them back
|
|
normalized = normalized.replace("\\", "/")
|
|
return normalized
|