Compare commits
7 Commits
virtual-tr
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
55e19d4825 | ||
![]() |
b245ff75c5 | ||
![]() |
8769185b8d | ||
![]() |
164a1e8228 | ||
![]() |
3cc90f6dc2 | ||
![]() |
00f3ed6cf9 | ||
![]() |
3ab94aa388 |
@ -106,6 +106,9 @@ prepend_h1: false # Add title of articles as Markdown h1, looks better on certai
|
|||||||
# dest: title
|
# dest: title
|
||||||
# repr: "{} _" # (this is the default repr)
|
# repr: "{} _" # (this is the default repr)
|
||||||
move_fields: []
|
move_fields: []
|
||||||
|
# Some taxonomies (Spip Mots types) to not export, typically specific to Spip functions
|
||||||
|
ignore_taxonomies: ["Gestion du site", "Gestion des articles", "Mise en page"]
|
||||||
|
rename_taxonomies: { equipes: "tag-equipes" } # Rename taxonomies (prenvent conflict)
|
||||||
|
|
||||||
# Ignored data settings
|
# Ignored data settings
|
||||||
export_drafts: true # Should we export drafts
|
export_drafts: true # Should we export drafts
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "spip2md"
|
name = "spip2md"
|
||||||
version = "0.1.0"
|
version = "0.1.1"
|
||||||
description = "Generate a static website with plain Markdown+YAML files from a SPIP CMS database"
|
description = "Generate a static website with plain Markdown+YAML files from a SPIP CMS database"
|
||||||
license = "GPL-2.0"
|
license = "GPL-2.0"
|
||||||
|
|
||||||
|
@ -72,6 +72,8 @@ class Configuration:
|
|||||||
export_drafts: bool = True # Should we export drafts as draft:true articles
|
export_drafts: bool = True # Should we export drafts as draft:true articles
|
||||||
export_empty: bool = True # Should we export empty articles
|
export_empty: bool = True # Should we export empty articles
|
||||||
remove_html: bool = True # Should spip2md remove every HTML tags
|
remove_html: bool = True # Should spip2md remove every HTML tags
|
||||||
|
ignore_taxonomies = ("Gestion du site", "Gestion des articles", "Mise en page")
|
||||||
|
rename_taxonomies: dict[str, str] = {"equipes": "tag-equipes"}
|
||||||
metadata_markup: bool = False # Should spip2md keep the markup in metadata fields
|
metadata_markup: bool = False # Should spip2md keep the markup in metadata fields
|
||||||
title_max_length: int = 40 # Maximum length of a single title for directory names
|
title_max_length: int = 40 # Maximum length of a single title for directory names
|
||||||
unknown_char_replacement: str = "??" # Replaces unknown characters
|
unknown_char_replacement: str = "??" # Replaces unknown characters
|
||||||
|
@ -52,6 +52,8 @@ from spip2md.spip_models import (
|
|||||||
SpipAuteursLiens,
|
SpipAuteursLiens,
|
||||||
SpipDocuments,
|
SpipDocuments,
|
||||||
SpipDocumentsLiens,
|
SpipDocumentsLiens,
|
||||||
|
SpipMots,
|
||||||
|
SpipMotsLiens,
|
||||||
SpipRubriques,
|
SpipRubriques,
|
||||||
)
|
)
|
||||||
from spip2md.style import BOLD, CYAN, GREEN, WARNING_STYLE, YELLOW, esc
|
from spip2md.style import BOLD, CYAN, GREEN, WARNING_STYLE, YELLOW, esc
|
||||||
@ -61,6 +63,9 @@ DeepDict = dict[str, "list[DeepDict] | list[str] | str"]
|
|||||||
# Define logger for this file’s logs
|
# Define logger for this file’s logs
|
||||||
LOG = logging.getLogger(NAME + ".models")
|
LOG = logging.getLogger(NAME + ".models")
|
||||||
|
|
||||||
|
# Define type that images can have
|
||||||
|
IMG_TYPES = ("jpg", "png", "jpeg", "gif", "webp", "ico")
|
||||||
|
|
||||||
|
|
||||||
class SpipWritable:
|
class SpipWritable:
|
||||||
# From SPIP database
|
# From SPIP database
|
||||||
@ -349,8 +354,10 @@ class SpipRedactional(SpipWritable):
|
|||||||
langue_choisie: str
|
langue_choisie: str
|
||||||
# Converted
|
# Converted
|
||||||
_text: str
|
_text: str
|
||||||
|
_taxonomies: dict[str, list[str]] = {}
|
||||||
_url_title: str # Title in metadata of articles
|
_url_title: str # Title in metadata of articles
|
||||||
_parenturl: str # URL relative to lang to direct parent
|
_parenturl: str # URL relative to lang to direct parent
|
||||||
|
_static_img_path: Optional[str] = None # Path to the static img of this article
|
||||||
|
|
||||||
# Get rid of other lang than forced in text and modify lang to forced if found
|
# Get rid of other lang than forced in text and modify lang to forced if found
|
||||||
def translate_multi(
|
def translate_multi(
|
||||||
@ -372,6 +379,9 @@ class SpipRedactional(SpipWritable):
|
|||||||
self.lang = forced_lang # So write-all will not be cancelled
|
self.lang = forced_lang # So write-all will not be cancelled
|
||||||
# Replace the mutli blocks with the text in the proper lang
|
# Replace the mutli blocks with the text in the proper lang
|
||||||
text = text.replace(block.group(), lang.group(1))
|
text = text.replace(block.group(), lang.group(1))
|
||||||
|
else:
|
||||||
|
# Replace the mutli blocks with the text inside
|
||||||
|
text = text.replace(block.group(), block.group(1))
|
||||||
if lang is None:
|
if lang is None:
|
||||||
LOG.debug(f"{forced_lang} not found in `{self._url_title}`")
|
LOG.debug(f"{forced_lang} not found in `{self._url_title}`")
|
||||||
return text
|
return text
|
||||||
@ -563,6 +573,37 @@ class SpipRedactional(SpipWritable):
|
|||||||
LOG.debug(f"Apply conversions to {self.lang} `{self._url_title}` extra")
|
LOG.debug(f"Apply conversions to {self.lang} `{self._url_title}` extra")
|
||||||
self._extra = self.convert_field(self._extra, CFG.metadata_markup)
|
self._extra = self.convert_field(self._extra, CFG.metadata_markup)
|
||||||
|
|
||||||
|
def convert_taxonomies(self, forcedlang: str) -> None:
|
||||||
|
self._taxonomies = {}
|
||||||
|
|
||||||
|
for tag in self.taxonomies():
|
||||||
|
taxonomy = str(tag.type)
|
||||||
|
if taxonomy not in CFG.ignore_taxonomies:
|
||||||
|
LOG.debug(
|
||||||
|
f"Translate taxonomy of `{self._url_title}`: {tag.descriptif}"
|
||||||
|
)
|
||||||
|
if taxonomy in CFG.rename_taxonomies:
|
||||||
|
LOG.debug(
|
||||||
|
f"Rename taxonomy {taxonomy}: {CFG.rename_taxonomies[taxonomy]}"
|
||||||
|
)
|
||||||
|
taxonomy = CFG.rename_taxonomies[taxonomy]
|
||||||
|
if str(taxonomy) in self._taxonomies:
|
||||||
|
self._taxonomies[taxonomy].append(
|
||||||
|
self.convert_field(
|
||||||
|
self.translate_multi(forcedlang, str(tag.descriptif), False)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._taxonomies[taxonomy] = [
|
||||||
|
self.convert_field(
|
||||||
|
self.translate_multi(forcedlang, str(tag.descriptif), False)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
LOG.debug(
|
||||||
|
f"After translation, taxonomies of `{self._url_title}`: {self._taxonomies}"
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
# Initialize converted fields, beginning with underscore
|
# Initialize converted fields, beginning with underscore
|
||||||
@ -626,6 +667,28 @@ class SpipRedactional(SpipWritable):
|
|||||||
body += "\n\n# EXTRA\n\n" + self._extra
|
body += "\n\n# EXTRA\n\n" + self._extra
|
||||||
return body
|
return body
|
||||||
|
|
||||||
|
def authors(self) -> tuple[SpipAuteurs, ...]:
|
||||||
|
LOG.debug(f"Initialize authors of `{self._url_title}`")
|
||||||
|
return (
|
||||||
|
SpipAuteurs.select()
|
||||||
|
.join(
|
||||||
|
SpipAuteursLiens,
|
||||||
|
on=(SpipAuteurs.id_auteur == SpipAuteursLiens.id_auteur),
|
||||||
|
)
|
||||||
|
.where(SpipAuteursLiens.id_objet == self._id)
|
||||||
|
)
|
||||||
|
|
||||||
|
def taxonomies(self) -> tuple[SpipMots, ...]:
|
||||||
|
LOG.debug(f"Initialize taxonomies of `{self._url_title}`")
|
||||||
|
return (
|
||||||
|
SpipMots.select()
|
||||||
|
.join(
|
||||||
|
SpipMotsLiens,
|
||||||
|
on=(SpipMots.id_mot == SpipMotsLiens.id_mot),
|
||||||
|
)
|
||||||
|
.where(SpipMotsLiens.id_objet == self._id)
|
||||||
|
)
|
||||||
|
|
||||||
# Write all the documents of this object
|
# Write all the documents of this object
|
||||||
def write_children(
|
def write_children(
|
||||||
self,
|
self,
|
||||||
@ -697,19 +760,40 @@ class SpipRedactional(SpipWritable):
|
|||||||
# Write the content of this object into a file named as self.filename()
|
# Write the content of this object into a file named as self.filename()
|
||||||
with open(self.dest_path(), "w") as f:
|
with open(self.dest_path(), "w") as f:
|
||||||
f.write(self.content())
|
f.write(self.content())
|
||||||
|
# Write the eventual static image of this object
|
||||||
|
if self._static_img_path:
|
||||||
|
copyfile(
|
||||||
|
self._static_img_path,
|
||||||
|
self.dest_directory() + basename(self._static_img_path),
|
||||||
|
)
|
||||||
return self.dest_path()
|
return self.dest_path()
|
||||||
|
|
||||||
|
# Append static images based on filename instead of DB to objects texts
|
||||||
|
def append_static_images(self, obj_str: str = "art", load_str: str = "on"):
|
||||||
|
for t in IMG_TYPES:
|
||||||
|
path: str = CFG.data_dir + obj_str + load_str + str(self._id) + "." + t
|
||||||
|
LOG.debug(f"Search static image of `{self._url_title}` at: {path}")
|
||||||
|
if isfile(path):
|
||||||
|
LOG.debug(f"Found static image of `{self._url_title}` at: {path}")
|
||||||
|
# Append static image to content
|
||||||
|
self._text += f"\n\n![]({basename(path)})"
|
||||||
|
# Store it’s path to write it later
|
||||||
|
self._static_img_path = path
|
||||||
|
break
|
||||||
|
|
||||||
# Apply post-init conversions and cancel the export if self not of the right lang
|
# Apply post-init conversions and cancel the export if self not of the right lang
|
||||||
def convert(self, forced_lang: str) -> None:
|
def convert(self, forced_lang: str) -> None:
|
||||||
self.convert_title(forced_lang)
|
self.convert_title(forced_lang)
|
||||||
self.convert_text(forced_lang)
|
self.convert_text(forced_lang)
|
||||||
self.convert_extra()
|
self.convert_extra()
|
||||||
|
self.convert_taxonomies(forced_lang)
|
||||||
if self.lang != forced_lang:
|
if self.lang != forced_lang:
|
||||||
raise LangNotFoundError(
|
raise LangNotFoundError(
|
||||||
f"`{self._url_title}` lang is {self.lang} instead of the wanted"
|
f"`{self._url_title}` lang is {self.lang} instead of the wanted"
|
||||||
+ f" {forced_lang} and it don’t contains"
|
+ f" {forced_lang} and it don’t contains"
|
||||||
+ f" {forced_lang} translation in Markup either"
|
+ f" {forced_lang} translation in Markup either"
|
||||||
)
|
)
|
||||||
|
self.append_static_images()
|
||||||
|
|
||||||
|
|
||||||
class Article(SpipRedactional, SpipArticles):
|
class Article(SpipRedactional, SpipArticles):
|
||||||
@ -741,7 +825,9 @@ class Article(SpipRedactional, SpipArticles):
|
|||||||
}
|
}
|
||||||
# Add debugging meta if needed
|
# Add debugging meta if needed
|
||||||
if CFG.debug_meta:
|
if CFG.debug_meta:
|
||||||
meta = meta | {"spip_id_rubrique": self.id_rubrique}
|
meta |= {"spip_id_rubrique": self.id_rubrique}
|
||||||
|
if self._taxonomies:
|
||||||
|
meta |= self._taxonomies
|
||||||
if append is not None:
|
if append is not None:
|
||||||
return super().frontmatter(meta | append)
|
return super().frontmatter(meta | append)
|
||||||
else:
|
else:
|
||||||
@ -760,17 +846,6 @@ class Article(SpipRedactional, SpipArticles):
|
|||||||
body += "\n\n# MICROBLOGGING\n\n" + self._microblog
|
body += "\n\n# MICROBLOGGING\n\n" + self._microblog
|
||||||
return body
|
return body
|
||||||
|
|
||||||
def authors(self) -> list[SpipAuteurs]:
|
|
||||||
LOG.debug(f"Initialize authors of `{self._url_title}`")
|
|
||||||
return (
|
|
||||||
SpipAuteurs.select()
|
|
||||||
.join(
|
|
||||||
SpipAuteursLiens,
|
|
||||||
on=(SpipAuteurs.id_auteur == SpipAuteursLiens.id_auteur),
|
|
||||||
)
|
|
||||||
.where(SpipAuteursLiens.id_objet == self._id)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Perform all the write steps of this object
|
# Perform all the write steps of this object
|
||||||
def write_all(
|
def write_all(
|
||||||
self,
|
self,
|
||||||
@ -853,3 +928,7 @@ class Section(SpipRedactional, SpipRubriques):
|
|||||||
"articles": self.write_children(self.articles(), forced_lang),
|
"articles": self.write_children(self.articles(), forced_lang),
|
||||||
"sections": self.write_children(self.sections(), forced_lang),
|
"sections": self.write_children(self.sections(), forced_lang),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Append static images based on filename instead of DB to objects texts
|
||||||
|
def append_static_images(self, obj_str: str = "rub", load_str: str = "on"):
|
||||||
|
super().append_static_images(obj_str, load_str)
|
||||||
|
Loading…
Reference in New Issue
Block a user