[1.9.50]
This commit is contained in:
parent
03960f733b
commit
7849ca4f4b
212
CHANGELOG.md
212
CHANGELOG.md
|
@ -10,213 +10,5 @@ Tyto - Littérateur
|
|||
|
||||
# CURRENTLY IN DEV (in devel branch) !
|
||||
|
||||
## [1.9.39]
|
||||
- fix datepub in modules when "check domain"
|
||||
- add Tyto - Littérateur generator links at HTML footer creation
|
||||
- fix settings from command line options
|
||||
- add "RSS" and "sitemap" links to default footer (not yet processed)
|
||||
- add command "set 'MODULE_NAME'" to create default module (header, footer...)
|
||||
- Create again all HTML modules with option -F, --force
|
||||
- With option -E, --errors: only show warning and error logs
|
||||
- Avoid creating a domain in a directory domain set yet
|
||||
- better modules managed in "wip" process
|
||||
- Added logs file (include ALL logs) in /var/log/tyto
|
||||
- - current.log for current session only
|
||||
- - archive.log for all sessions
|
||||
- Sitemap (! In dev)
|
||||
- - Create sitemaps in root and sub-directories
|
||||
|
||||
## [1.9.38]
|
||||
- Moved: HTML footer in div site_container
|
||||
- fix: main title in HTML page h1
|
||||
- Fill Article HTML metas datas
|
||||
- Working on files copies to wip server with "wip" command
|
||||
- - some changes in post DB and check process
|
||||
|
||||
## [1.9.37]
|
||||
- Preparing full HTML Page
|
||||
- Some fixes
|
||||
- Added web target (without index.html) in section "FILE" in post DB
|
||||
- Added article footer contents
|
||||
|
||||
## [1.9.36]
|
||||
- fix translations modules
|
||||
- added metas module
|
||||
- added command "show metas" to see those already set in page with post
|
||||
|
||||
## [1.9.35]
|
||||
- Working on creating modules
|
||||
- - Todo last: metas
|
||||
- check
|
||||
- - target: domain, wip, www to check directories and files
|
||||
- - - domain: create .raw modules and wip modules (.html)
|
||||
- wip
|
||||
- - html values are now in wip.py
|
||||
- fixes and more...
|
||||
|
||||
## [1.9.34]
|
||||
- Working on creating modules
|
||||
- - fixes typos codes
|
||||
- - header, navbar, sidebar = ok
|
||||
- - toto footer contents and testing things
|
||||
- - Manage modules with an ini db file to avoid creating HTML updated modules
|
||||
|
||||
## [1.9.33]
|
||||
- Working on creating modules (header, navbar, sidebar, header)
|
||||
- - Added working header module
|
||||
- - Finishing navbar module...
|
||||
- - Todo Next: sidebar and footer modules
|
||||
|
||||
## [1.9.32]
|
||||
- Working on creating modules (header, navbar, sidebar, header)
|
||||
|
||||
## [1.9.31]
|
||||
- Fix replacing markers starting LINE with HTML
|
||||
- Added tpl_files directory
|
||||
- - addes styles.css (empty with classes used)
|
||||
|
||||
## [1.9.30]
|
||||
- 'wip' process
|
||||
- - About all markers done !
|
||||
|
||||
## [1.9.29]
|
||||
- Translations
|
||||
- - added for logs (english)
|
||||
- - updated french logs
|
||||
- wip (working on...)
|
||||
- - added modules conversions (source to HTML)
|
||||
- check
|
||||
- - some fixes and updated code
|
||||
- tools
|
||||
- - check css content
|
||||
- readme : updated article example with comments
|
||||
|
||||
## [1.9.28]
|
||||
- readme
|
||||
- - updated tyto article, with comments to show how to
|
||||
- multiple targets
|
||||
- - fix CSS classe name error
|
||||
- - reset stats, post.error, HEADERS datas
|
||||
- check process:
|
||||
- - Added hr and br tags (CSS class name check)
|
||||
- - fix blockquote title HTML
|
||||
- - New method to split separator in article
|
||||
- - fix icode, bcode contents HTML signs (converted)
|
||||
|
||||
## [1.9.27]
|
||||
- fix when target article .tyto is missing
|
||||
- Nearly all stats are added in DB from modules
|
||||
- Only used tags and stats (or nearly) are added to DB
|
||||
- cleaner code
|
||||
- check:
|
||||
- - added words_tags (strong, italics...)
|
||||
- - "all" target now ready
|
||||
|
||||
## [1.9.26]
|
||||
- user can indent titles in text
|
||||
- prepared words markers (strong, bolds) (some to add soon)
|
||||
|
||||
## [1.9.25]
|
||||
- fix typo when creating HTML list
|
||||
- new anchors process (HTML prepared at 'check')
|
||||
|
||||
## [1.9.24]
|
||||
- new list process (HTML prepared at 'check')
|
||||
|
||||
## [1.9.23]
|
||||
- new quote process (HTML prepared at 'check')
|
||||
|
||||
## [1.9.22]
|
||||
- new bcode process (html prepared for wip)
|
||||
- new post database management values
|
||||
- new icode process (html prepared for wip)
|
||||
- bcodes and icodes are FIRST processed in text article
|
||||
- generic check fonction for bcodes, quotes, lists, paragraphs
|
||||
- lots more
|
||||
|
||||
## [1.9.21]
|
||||
- new indentation (3 spaces)
|
||||
- added 'raw:' marker
|
||||
- (for wip process):
|
||||
- - added html titles to post database
|
||||
- - added html comments to post database (default: ';; a comment')
|
||||
- - added val3 tag as html comment to content, and convert content to base64
|
||||
- - - added values to post database
|
||||
- cleaner code
|
||||
|
||||
## [1.9.20]
|
||||
- working on 'check' process
|
||||
- - updated 'logo:' process
|
||||
- - added 'abbr:' process
|
||||
|
||||
## [1.9.19]
|
||||
- working on 'check' process
|
||||
- - Added post 'logo: URI' (for social network share + opt show on page)
|
||||
|
||||
## [1.9.18]
|
||||
- working on 'check' process
|
||||
- - added image: tag
|
||||
- - added value 2 (tag line 2) uri check (generic, root, post)
|
||||
- - some corrections for domain config file
|
||||
- - prepared html values for wip
|
||||
|
||||
## [1.9.17]
|
||||
- working on 'check' process
|
||||
- - dev on checking file used in some post header tags
|
||||
|
||||
## [1.9.16]
|
||||
- working on 'check' process
|
||||
- - dev: post database values (lots are missing)
|
||||
- - added links, files supports
|
||||
- - testing some new markers
|
||||
|
||||
## [1.9.15]
|
||||
- Added 'check' process for bcodes, quotes and paragraphs + stats
|
||||
- - Their contents must be indented
|
||||
- - replace with empty lines for bcodes and quotes
|
||||
|
||||
## [1.9.14]
|
||||
- added 'check' process for block-codes
|
||||
|
||||
## [1.9.13]
|
||||
- Check: One-Line needed tags, titles
|
||||
- Added first stats
|
||||
- move ini template from tyto to domain for domain config file
|
||||
- Check valid date in article and form domain date
|
||||
|
||||
## [1.9.12]
|
||||
- preparing check process : head tags in article
|
||||
|
||||
## [1.9.11]
|
||||
- Preparing for multi-targets with "all"
|
||||
- check if article is a .tyto format
|
||||
- preparing values for articles
|
||||
|
||||
## [1.9.10]
|
||||
- cleaner code
|
||||
- start/stop domain by user
|
||||
- User directories check/create when domain activated
|
||||
- Check install configuration
|
||||
|
||||
## [1.9.9]
|
||||
- cleaner code with new check/update domain process
|
||||
|
||||
## [1.9.8]
|
||||
- Check/create/update a domain is ready
|
||||
|
||||
## [1.9.7]
|
||||
- new process to check and update configuration file (bug at write some values)
|
||||
|
||||
## [1.9.6]
|
||||
- Better management to create/update domain
|
||||
|
||||
## [1.9.5]
|
||||
- Preparing post database
|
||||
|
||||
## [1.9.4]
|
||||
- Added start/strop action to activate (or deactivate) domain
|
||||
- Directories creation for user working domain
|
||||
- better log management for user
|
||||
|
||||
|
||||
|
||||
## [1.9.50]
|
||||
- Complete new code
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -629,7 +629,7 @@ to attach them to the start of each source file to most effectively
|
|||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
GSL Statique Littérateur
|
||||
Tyto - Littérateur
|
||||
Copyright (C) 2022 Libre en Communs / Commissions / Infrastructure
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
|
|
473
README.md
473
README.md
|
@ -1,372 +1,195 @@
|
|||
# Very early IN dev code
|
||||
This program can ve tested but not at all usable. Lots of work to do...
|
||||
This program can ve tested and should mainly work. Please report any problems
|
||||
|
||||
Tyto - Littérateur is translated in french and english.
|
||||
|
||||
# Commands
|
||||
```
|
||||
# Get commands list help
|
||||
# Get commands help
|
||||
tyto
|
||||
|
||||
# Get all documentation
|
||||
tyto help all
|
||||
|
||||
# How to write words tags (strong...) and anchors
|
||||
tyto help words anchor
|
||||
```
|
||||
|
||||
# Create new domain
|
||||
- create a domain directory, like www.domain.tld
|
||||
- Go to this directory
|
||||
- type `tyto new domain`
|
||||
- type `tyto check domain`
|
||||
- create in new directory domain ".../articles/", an article (see tuto below)
|
||||
- type `check myfile.tyto` (or use "wip" instead of check)
|
||||
- create in new directory domain ".../articles/", an article (see help)
|
||||
- type `wip myfile.tyto`
|
||||
|
||||
|
||||
## Working on
|
||||
- 'wip' action processes
|
||||
- Create HTML full page from article
|
||||
- Create/Manage modules (metas, header, navbar, sidebar, footer)
|
||||
|
||||
## ToDo
|
||||
- thinking about creating an auto top article menu from titles
|
||||
- create full HTML page
|
||||
- sitemaps
|
||||
- RSS
|
||||
- 'publish' process
|
||||
|
||||
## Exemple d'article .tyto commenté
|
||||
```
|
||||
#================================================#
|
||||
# Entete de l'article #
|
||||
# Fin de l'entête avec au moins 5 tirets "-----" #
|
||||
# Toute ligne de commentaire "# ..." est ignorée #
|
||||
# ! Recommandé de ne pas utiliser le signe "_" #
|
||||
#================================================#
|
||||
title: Tests
|
||||
about: Tests divers
|
||||
date: 2023-02-28
|
||||
tags: tests
|
||||
authors: echolib
|
||||
|
||||
# Pour ne pas inclure cet article dans les sitemaps :
|
||||
! NoSitemap
|
||||
abbr: CSS
|
||||
Cascading SteelSheet
|
||||
en
|
||||
|
||||
# Données uniques sur UNE ligne
|
||||
title: tests d'un article
|
||||
about: À propos de cet article de test
|
||||
tags: Tyto, tuto,
|
||||
author: echolib
|
||||
date: 2023-10-27
|
||||
|
||||
# Données unique sur UNE ligne optionnelle
|
||||
# Si non définit, le logo du domaine est utilisé
|
||||
# Ne sera affiché qu'avec _image:logo
|
||||
logo: logo.png
|
||||
|
||||
# Données multiples sur 3 lignes
|
||||
# [TAG]: Nom
|
||||
# LIEN
|
||||
# Text alternatif
|
||||
|
||||
# Reprendre dans l'article : __cliquer sur ce lien
|
||||
link: cliquer sur ce Lien
|
||||
https://
|
||||
Text alternatif
|
||||
|
||||
link: Réservez ici
|
||||
https://
|
||||
Billets
|
||||
|
||||
# Reprendre dans l'article : --télécharger ce fichier
|
||||
file: télécharger ce fichier
|
||||
@/PDFs/hello.pdf
|
||||
Un PDF !
|
||||
|
||||
# Reprendre dans l'article : _code:codetest
|
||||
code: codetest
|
||||
@RAWS/test.py
|
||||
Exemple d'un code Python
|
||||
|
||||
# Reprendre dans l'article : _image:mypic
|
||||
image: mypic
|
||||
@hello.png
|
||||
Text Alt
|
||||
|
||||
# Les abréviations :
|
||||
# 2eme ligne: Texte alternatif
|
||||
# 3ème ligne: valeur affichée dans l'article à la place du Nom
|
||||
abbr: HTML
|
||||
HuperText Markup Langage
|
||||
HTML
|
||||
|
||||
# Reprendre dans l'article : ;;css
|
||||
abbr: css
|
||||
Cascading Stylesheet
|
||||
CSS
|
||||
link: le site est prêt
|
||||
https://forge.a-lec.org
|
||||
La forge libre
|
||||
|
||||
-----
|
||||
|
||||
#=====================================================================#
|
||||
# Contenu de l'article #
|
||||
# Les classe optionnelles non renseignées deviennent celle du domaine #
|
||||
# /!\ Tout code HTML sera interprêté par le navigateur sauf si placé #
|
||||
# entre les marqueurs de block-code ou icode #
|
||||
#=====================================================================#
|
||||
|
||||
# La ligne suivante est un commentaire HTML "<!-- Commentaire -->"
|
||||
# ----------------------------------------------------------------
|
||||
;; Commentaire
|
||||
|
||||
# Ceci est une ancre avec l'ID uniq1 (ID unique)
|
||||
# ----------------------------------------------
|
||||
-> uniq1
|
||||
-> top
|
||||
|
||||
# Créer un lien vers l'ancre "uniq1"
|
||||
# ----------------------------------
|
||||
>_uniq1: Go to uniq1 anchor_<
|
||||
|
||||
# Ceci est une ligne <hr> ayant pour classe hrcss
|
||||
# -----------------------------------------------
|
||||
-- hrcss
|
||||
|
||||
# Les Titres de l'article de #1 à #5 (<h2> à <h6>)
|
||||
# ------------------------------------------------
|
||||
#1 Titre en h2
|
||||
|
||||
# Contenu dans un paragraphe entre (( ... )) ayant pour classe "mypar"
|
||||
# --------------------------------------------------------------------
|
||||
(( mypar
|
||||
Un long paragraphe...
|
||||
|
||||
# Retour à la ligne avec un <br /> de classe brcss
|
||||
# (les retours à la ligne vides ne sont pas pris en compte)
|
||||
# ---------------------------------------------------------
|
||||
| brcss
|
||||
|
||||
# Reprise du Nom pour les liens de link: et file:
|
||||
# Reprise des abréviations
|
||||
Il faut __cliquer sur ce Lien, __Réservez ici et --télécharger ce fichier
|
||||
ou encore faire une ::css pour du beau rendu ::HTML
|
||||
|
||||
# Un paragraphe dans le paragraphe ayant pour classe, celle du domaine
|
||||
# --------------------------------------------------------------------
|
||||
((
|
||||
Un /_court_/ paragraphe de :_1984_: pour de ~_vrai_~ +_faux en gras_+
|
||||
Il faut le ._souligner_. et *_Très Gras_*
|
||||
))
|
||||
|
||||
# Créer un icode (utilise la balise <code> HTML)
|
||||
# /!\ ! Doit être sur une même ligne
|
||||
# ----------------------------------------------
|
||||
{_<ol>, <ul>_}
|
||||
{_{_Afficher un icode brut_}_}
|
||||
))
|
||||
|
||||
# Un exemple de block code ayant pour classe python
|
||||
# Tout contenu entre les marqueurs "{{" et "}}" est conservé
|
||||
# ----------------------------------------------------------
|
||||
#2 Block Code
|
||||
{{ python
|
||||
# Un commentaire et du code
|
||||
def hello(world):
|
||||
world and print(world) or print("NoMore")
|
||||
}}
|
||||
|
||||
|
||||
# Écrire en gras, italique...
|
||||
# ---------------------------
|
||||
#2 Marqueurs de mots
|
||||
#1 Titre 1
|
||||
((
|
||||
Même si, il est possible d'écrire directement des balises (HTML), Tyto
|
||||
propose de les simplifier, en entourant les mots avec des marqueurs. La
|
||||
classe CSS du domaine est utilisée pour chaque marqueur.
|
||||
|
||||
{{
|
||||
*_Très Gras_* > <strong>
|
||||
+_En Gras_+ > <b>
|
||||
[_Citer un texte_] > <q>
|
||||
:_Citer une référence_: > <cite>
|
||||
~_Texte barré_~ > <del>
|
||||
._Text souligné_. > <u>
|
||||
/_En italique_/ > <em>
|
||||
;_En italique_; > <i>
|
||||
|
||||
# Marques multiples, ajouter "&"
|
||||
*_&._Très gras et souligné_.&_*
|
||||
}}
|
||||
Un peu de ::CSS et ::le site est prêt
|
||||
(( note
|
||||
Cet article est un test
|
||||
))
|
||||
))
|
||||
|
||||
|
||||
# Dans un block div [[ ... ]] (classe CSS mydiv),
|
||||
# La citation entre [" ... "] (classe CSS mycite)
|
||||
# est placée dans un paragraphe (classe CSS mycite)
|
||||
# ! Tout commentaire "# ..." dans la citation sera affiché...
|
||||
# -----------------------------------------------------------
|
||||
#2 Citation
|
||||
[[ mydiv
|
||||
[" mycite
|
||||
;; A great quote here !
|
||||
cite: Someone
|
||||
date: 2023-10-13
|
||||
book: A History
|
||||
lang: en
|
||||
("
|
||||
cite: Auteur
|
||||
date: AAAA-MM-JJ
|
||||
book: Nom du livre
|
||||
lang: fr
|
||||
link: https://...
|
||||
|
||||
(( mycite
|
||||
Here, i am
|
||||
((
|
||||
Citation complète dans un paragraphe
|
||||
))
|
||||
"]
|
||||
]]
|
||||
)"
|
||||
|
||||
#2 Code (bloc)
|
||||
{{
|
||||
# Écrire les marqueurs de mots
|
||||
# Chaque marqueur à la classe CSS de la configuration
|
||||
# Astuce : ** + ← + `` + ← + très gras
|
||||
|
||||
# Créer une liste ol/ul entre <: ... :> (classe mylist)
|
||||
# dans un paragraphe (classe du domaine)
|
||||
# "+" pour ol, "=" pour ul
|
||||
# Ajouter toujours un signe pour un sous-item ou /!\ au changement de signe
|
||||
# -------------------------------------------------------------------------
|
||||
#2 Une liste mixée {_<ol>, <ul>_}
|
||||
((
|
||||
<: mylist
|
||||
+ numeric ol item 1
|
||||
++ numeric ol sub-Item 1
|
||||
+++ numeric ol sub-sub-item 1
|
||||
==== ul item >_top: Go to Top_<
|
||||
==== ul item >_top: Another anchor_<
|
||||
:>
|
||||
))
|
||||
*`très gras`* => <strong>
|
||||
+`gras`+ => <b>
|
||||
/`italique`/ => <em>
|
||||
;`italique`; => <i>
|
||||
_`souligné`_ => <u>
|
||||
~`effacé`~ => <del>
|
||||
[`cité`] => <q> # Contenu
|
||||
:`cité`: => <cite> # auteur, nom
|
||||
|`perso`| => <span>
|
||||
|
||||
# Afficher un block code avec le contenu d'un fichier
|
||||
# Il doit avoir été configuré dans l'entête
|
||||
# -----------------------------------------
|
||||
#2 Un block code depuis un fichier
|
||||
_code:codetest
|
||||
# Code dans un texte
|
||||
# ! Les marqueurs d'ouverture et de fermeture de code sont sur la MEME LIGNE
|
||||
|
||||
# Afficher une image (1 tag par ligne)
|
||||
# ------------------------------------
|
||||
#2 Les images
|
||||
# Placer le logo de l'article
|
||||
_image:logo
|
||||
{` <li>Une entée de liste</li> `} => <code>
|
||||
|
||||
# les options du marqueur:
|
||||
# - c=CLASS < Sinon la classe est celle du domaine
|
||||
# - w=WIDTH < longueur (si pas d'unité : défaut "px")
|
||||
# - h=HEIGHT < Comme w=
|
||||
# - f=Ma légende sous l'image (ajoute <figure><figcaption>)
|
||||
# - - Recommandé d'utiliser cette option en dernier
|
||||
# ! Dans certains cas, il faut ajouter un espace après le 1er marqueur
|
||||
# et/ou avant le second. Ils seront automatiquement supprimés
|
||||
|
||||
# ! Les images dans cet exemple sont affichées horizontalement
|
||||
# Placer "|", ou mettez chaque image dans un paragraphe "((...))"
|
||||
# ou définir un style css de type display:block pour les afficher verticalement
|
||||
((
|
||||
_image:mypic
|
||||
_image:mypic c=MYCSS
|
||||
))
|
||||
*`DOMAIN/articles/ `* # évite /` : marqueur italique ouvert
|
||||
}}
|
||||
|
||||
# Une image avec légende (<figure>) (jamais dans un paragraphe)
|
||||
_image:mypic c=PIC w=60em h=30% f=echolib sur une chaise
|
||||
#2 Une liste
|
||||
# Liste. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# Une entrée de liste peut être ordonnée avec le signe "+" ou non avec "="
|
||||
# Une liste peut contenir des entrées mixées ("+" et "=")
|
||||
# mais au changement de signe, ajouter un signe !
|
||||
# Possible d'écrire une entrée sur plusieurs lignes
|
||||
|
||||
(=
|
||||
= Première entrée non ordonnée (ul)
|
||||
== Sous entrée non ordonnée
|
||||
+++ Première sous-sous entrée ordonnée (ol)
|
||||
+++ Seconde sous-sous entrée ordonnée
|
||||
= Seconde entrée non ordonnée
|
||||
= Troisième entrée ...
|
||||
... non ordonnée
|
||||
)=
|
||||
```
|
||||
|
||||
## Output HTML
|
||||
```
|
||||
<!-- Article Text: [tests d'un article] -->
|
||||
<!-- Commentaire -->
|
||||
<a id="uniq1" class="anchor_target"></a>
|
||||
<a id="top" class="anchor_target"></a>
|
||||
<a class="tyto anchor_link" href="#uniq1">Go to uniq1 anchor</a>
|
||||
<hr class="tyto">
|
||||
<h2 class="tyto">Titre en h2</h2>
|
||||
<p class="mypar">
|
||||
Un long paragraphe...
|
||||
<body>
|
||||
<div id="site_container">
|
||||
|
||||
<br class="brcss">
|
||||
<!--# include virtual="/template/header.html"-->
|
||||
<!--# include virtual="/template/navbar.html"-->
|
||||
|
||||
Il faut <a href="https://" class="tyto link" title="Text alternatif">cliquer sur ce Lien</a>, <a href="https://" class="tyto link" title="Billets">Réservez ici</a> et <a href="/files/PDFs/hello.pdf" class="tyto file" title="Un PDF !">télécharger ce fichier</a>
|
||||
ou encore faire une <abbr class="tyto" title="Cascading Stylesheet">CSS</abbr> pour du beau rendu <abbr class="tyto" title="HuperText Markup Langage">HTML</abbr>
|
||||
<main id="article_sidebar"> <!-- Contains <article> and <aside> -->
|
||||
|
||||
<p class="tyto">
|
||||
Un <em class="tyto">court</em> paragraphe de <cite class="tyto">1984</cite> pour de <del class="tyto">vrai</del> <b class="tyto">faux en gras</b>
|
||||
Il faut le <u class="tyto">souligner</u> et <strong class="tyto">Très Gras</strong>
|
||||
</p>
|
||||
<code class="tyto icode"><ol>, <ul></code>
|
||||
<code class="tyto icode">{_Afficher un icode brut_}</code>
|
||||
</p>
|
||||
<h3 class="tyto">Block Code</h3>
|
||||
<code class="python bcode">
|
||||
<p class="bcode"><span class="ln bcode">1</span><span class="line bcode"># Un commentaire et du code</span></p>
|
||||
<p class="bcode"><span class="ln bcode">2</span><span class="line bcode">def hello(world):</span></p>
|
||||
<p class="bcode"><span class="ln bcode">3</span><span class="line bcode"> world and print(world) or print("NoMore")</span></p>
|
||||
</code>
|
||||
<h3 class="tyto">Marqueurs de mots</h3>
|
||||
<p class="tyto">
|
||||
Même si, il est possible d'écrire directement des balises (HTML), Tyto
|
||||
propose de les simplifier, en entourant les mots avec des marqueurs. La
|
||||
classe CSS du domaine est utilisée pour chaque marqueur.
|
||||
|
||||
<code class="tyto bcode">
|
||||
<p class="bcode"><span class="ln bcode">1</span><span class="line bcode">*_Très Gras_* > <strong></span></p>
|
||||
<p class="bcode"><span class="ln bcode">2</span><span class="line bcode">+_En Gras_+ > <b></span></p>
|
||||
<p class="bcode"><span class="ln bcode">3</span><span class="line bcode">[_Citer un texte_] > <q></span></p>
|
||||
<p class="bcode"><span class="ln bcode">4</span><span class="line bcode">:_Citer une référence_: > <cite></span></p>
|
||||
<p class="bcode"><span class="ln bcode">5</span><span class="line bcode">~_Texte barré_~ > <del></span></p>
|
||||
<p class="bcode"><span class="ln bcode">6</span><span class="line bcode">._Text souligné_. > <u></span></p>
|
||||
<p class="bcode"><span class="ln bcode">7</span><span class="line bcode">/_En italique_/ > <em></span></p>
|
||||
<p class="bcode"><span class="ln bcode">8</span><span class="line bcode">;_En italique_; > <i></span></p>
|
||||
<p class="bcode"><span class="ln bcode">9</span><span class="line bcode"></span></p>
|
||||
<p class="bcode"><span class="ln bcode">10</span><span class="line bcode"># Marques multiples, ajouter "&"</span></p>
|
||||
<p class="bcode"><span class="ln bcode">11</span><span class="line bcode">*_&._Très gras et souligné_.&_*</span></p>
|
||||
</code>
|
||||
</p>
|
||||
<h3 class="tyto">Citation</h3>
|
||||
<div class="mydiv">
|
||||
<blockquote class="mycite" cite="https://..." lang="en" title="-- Someone - A History (2023-10-13)">
|
||||
<time datetime="2023-10-13">
|
||||
<!-- Quote -->
|
||||
<!-- A great quote here ! -->
|
||||
|
||||
<p class="mycite">
|
||||
Here, i am
|
||||
</p>
|
||||
</time>
|
||||
<footer class="quote">
|
||||
<p class="quote"><a class="tyto quote" href="https://..." target="_blank">-- Someone - <cite class="quote"> - A History</cite> (2023-10-13)</a></p>
|
||||
</footer>
|
||||
</blockquote>
|
||||
<article id="article">
|
||||
<time datetime="2023-12-27 17:45:57">
|
||||
<header id="article_header">
|
||||
<h1 id="article_title">
|
||||
<a id="article_title_link" href="https://tyto.echolib.re/test.html" title="Tests -- echolib, 28/02/2023">Tests</a>
|
||||
</h1>
|
||||
<div id="article_refs">
|
||||
echolib, 28/02/2023 [<a id="post_code" class="tyto" href="./test.tyto" title="Code source : Tests">Code source</a>]
|
||||
</div>
|
||||
<h3 class="tyto">Une liste mixée <code class="tyto icode"><ol>, <ul></code></h3>
|
||||
</header>
|
||||
<h2 id="toc_4" class="tyto">Titre 1</h2>
|
||||
<p class="tyto">
|
||||
<ol class="mylist">
|
||||
<li class="mylist">numeric ol item 1</li>
|
||||
<ol>
|
||||
<li class="mylist">numeric ol sub-Item 1</li>
|
||||
<ol>
|
||||
<li class="mylist">numeric ol sub-sub-item 1</li>
|
||||
<ul>
|
||||
<li class="mylist">ul item <a class="tyto anchor_link" href="#top">Go to Top</a></li>
|
||||
<li class="mylist">ul item <a class="tyto anchor_link" href="#top">Another anchor</a></li>
|
||||
</ul>
|
||||
</ol>
|
||||
</ol>
|
||||
Un peu de <abbr class="tyto" title="Cascading SteelSheet" lang="en">CSS</abbr> et <a class="tyto" href="https://forge.a-lec.org" title="La forge libre">le site est prêt</a>
|
||||
<p class="note">
|
||||
Cet article est un test
|
||||
</p>
|
||||
</p>
|
||||
<h3 id="toc_4" class="tyto">Citation</h3>
|
||||
<blockquote class="tyto" cite="https://..." lang="fr" title="-- Auteur, Nom du livre, AAAA-MM-JJ"><time datetime="AAAA-MM-JJ">
|
||||
<p class="tyto">
|
||||
Citation complète dans un paragraphe
|
||||
</p>
|
||||
</time><footer class="tyto"><a class="tyto" href="https://...">-- Auteur, Nom du livre, AAAA-MM-JJ</a></footer></blockquote>
|
||||
<h3 id="toc_4" class="tyto">Code (bloc)</h3>
|
||||
<pre class="bcode">
|
||||
<code class="bcode"><span class="bcode ln">1</span><span class="bcode line"># Écrire les marqueurs de mots</span></code>
|
||||
<code class="bcode"><span class="bcode ln">2</span><span class="bcode line"># Chaque marqueur à la classe CSS de la configuration</span></code>
|
||||
<code class="bcode"><span class="bcode ln">3</span><span class="bcode line"># Astuce : ** + ← + `` + ← + très gras</span></code>
|
||||
<code class="bcode"><span class="bcode ln">4</span><span class="bcode line"></span></code>
|
||||
<code class="bcode"><span class="bcode ln">5</span><span class="bcode line">*`très gras`* => <strong></span></code>
|
||||
<code class="bcode"><span class="bcode ln">6</span><span class="bcode line">+`gras`+ => <b></span></code>
|
||||
<code class="bcode"><span class="bcode ln">7</span><span class="bcode line">/`italique`/ => <em></span></code>
|
||||
<code class="bcode"><span class="bcode ln">8</span><span class="bcode line">;`italique`; => <i></span></code>
|
||||
<code class="bcode"><span class="bcode ln">9</span><span class="bcode line">_`souligné`_ => <u></span></code>
|
||||
<code class="bcode"><span class="bcode ln">10</span><span class="bcode line">~`effacé`~ => <del></span></code>
|
||||
<code class="bcode"><span class="bcode ln">11</span><span class="bcode line">[`cité`] => <q> # Contenu</span></code>
|
||||
<code class="bcode"><span class="bcode ln">12</span><span class="bcode line">:`cité`: => <cite> # auteur, nom</span></code>
|
||||
<code class="bcode"><span class="bcode ln">13</span><span class="bcode line">|`perso`| => <span></span></code>
|
||||
<code class="bcode"><span class="bcode ln">14</span><span class="bcode line"></span></code>
|
||||
<code class="bcode"><span class="bcode ln">15</span><span class="bcode line"># Code dans un texte</span></code>
|
||||
<code class="bcode"><span class="bcode ln">16</span><span class="bcode line"># ! Les marqueurs d'ouverture et de fermeture de code sont sur la MEME LIGNE</span></code>
|
||||
<code class="bcode"><span class="bcode ln">17</span><span class="bcode line"></span></code>
|
||||
<code class="bcode"><span class="bcode ln">18</span><span class="bcode line">{` <li>Une entée de liste</li> `} => <code></span></code>
|
||||
<code class="bcode"><span class="bcode ln">19</span><span class="bcode line"></span></code>
|
||||
<code class="bcode"><span class="bcode ln">20</span><span class="bcode line"># ! Dans certains cas, il faut ajouter un espace après le 1er marqueur</span></code>
|
||||
<code class="bcode"><span class="bcode ln">21</span><span class="bcode line"># et/ou avant le second. Ils seront automatiquement supprimés</span></code>
|
||||
<code class="bcode"><span class="bcode ln">22</span><span class="bcode line"></span></code>
|
||||
<code class="bcode"><span class="bcode ln">23</span><span class="bcode line">*`DOMAIN/articles/ `* # évite /` : marqueur italique ouvert</span></code>
|
||||
</pre>
|
||||
<h3 id="toc_4" class="tyto">Une liste</h3>
|
||||
<ul class="tyto">
|
||||
<li class="tyto">Première entrée non ordonnée (ul)</li>
|
||||
<ul>
|
||||
<li class="tyto">Sous entrée non ordonnée</li>
|
||||
<ol>
|
||||
<li class="tyto">Première sous-sous entrée ordonnée (ol)</li>
|
||||
<li class="tyto">Seconde sous-sous entrée ordonnée</li>
|
||||
</ol>
|
||||
</ul>
|
||||
<li class="tyto">Seconde entrée non ordonnée</li>
|
||||
<li class="tyto">Troisième entrée ... ... non ordonnée</li>
|
||||
</ul>
|
||||
</time>
|
||||
</article>
|
||||
|
||||
</p>
|
||||
<h3 class="tyto">Un block code depuis un fichier</h3>
|
||||
<code class="tyto bcode">
|
||||
<!-- Exemple d'un code Python -->
|
||||
<p class="bcode"><span class="ln bcode">1</span><span class="line bcode">#================================#</span></p>
|
||||
<p class="bcode"><span class="ln bcode">2</span><span class="line bcode"># Searching options in arguments #</span></p>
|
||||
<p class="bcode"><span class="ln bcode">3</span><span class="line bcode">#--------------------------------#</span></p>
|
||||
<p class="bcode"><span class="ln bcode">4</span><span class="line bcode">def get_options():</span></p>
|
||||
<p class="bcode"><span class="ln bcode">5</span><span class="line bcode"> global dlogs, force, erron</span></p>
|
||||
<p class="bcode"><span class="ln bcode">6</span><span class="line bcode"> </span></p>
|
||||
<p class="bcode"><span class="ln bcode">7</span><span class="line bcode"> dlogs = force = erron = False</span></p>
|
||||
<p class="bcode"><span class="ln bcode">8</span><span class="line bcode"> for arg in range(1, len(sys.argv)):</span></p>
|
||||
<p class="bcode"><span class="ln bcode">9</span><span class="line bcode"> dlogs = sys.argv[arg] in tyto.debug_options</span></p>
|
||||
<p class="bcode"><span class="ln bcode">10</span><span class="line bcode"> force = sys.argv[arg] in tyto.force_options</span></p>
|
||||
<p class="bcode"><span class="ln bcode">11</span><span class="line bcode"> erron = sys.argv[arg] in tyto.debug_errors</span></p>
|
||||
<p class="bcode"><span class="ln bcode">12</span><span class="line bcode"> </span></p>
|
||||
<p class="bcode"><span class="ln bcode">13</span><span class="line bcode"> print("<li>my 'cafe !</li>")</span></p>
|
||||
<p class="bcode"><span class="ln bcode">14</span><span class="line bcode"></span></p>
|
||||
<footer class="bcode">
|
||||
<p class="bcode">
|
||||
<a class="bcode" href="/files/RAWS/test.py" title="Exemple d'un code Python">Source</a>
|
||||
</p>
|
||||
</footer>
|
||||
</code>
|
||||
<h3 class="tyto">Les images</h3>
|
||||
<a href="logo.png" class="post_logo image" title="tests d'un article"><img src="logo.png" class="post_logo" alt="tests d'un article" title="tests d'un article" /></a>
|
||||
<p class="tyto">
|
||||
<a href="/images/hello.png" class="tyto image" title="Text Alt"><img src="/images/hello.png" class="tyto" alt="Text Alt" title="Text Alt" /></a>
|
||||
<a href="/images/hello.png" class="MYCSS image" title="Text Alt"><img src="/images/hello.png" class="MYCSS" alt="Text Alt" title="Text Alt" /></a>
|
||||
</p>
|
||||
<a href="/images/hello.png" class="PIC image" title="Text Alt"><figure class="PIC"><img src="/images/hello.png" class="PIC" alt="Text Alt" title="Text Alt" style="width:60em;height:30%;" /><figcaption class="PIC">echolib sur une chaise</figcaption></figure></a>
|
||||
<!--# include virtual="/template/sidebar.html"-->
|
||||
|
||||
</main>
|
||||
|
||||
<!--# include virtual="/template/footer.html"-->
|
||||
|
||||
</div> <!-- #site_container -->
|
||||
|
||||
</body>
|
||||
```
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Package: tyto
|
||||
Version: 1.9.39
|
||||
Version: 1.9.50
|
||||
Section: custom
|
||||
Priority: optional
|
||||
Architecture: all
|
||||
|
|
179
src/usr/bin/tyto
179
src/usr/bin/tyto
|
@ -1,6 +1,5 @@
|
|||
#!/usr/bin/env python3
|
||||
# Version: 1.9.39
|
||||
# Updated: 2023-11-11 1699742831
|
||||
# version: 1.9.50
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
@ -16,102 +15,136 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Main binary to execute.
|
||||
# Import modules and start checking/using arguments
|
||||
# Description: Main executable
|
||||
# File: /usr/bin/tyto
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# Project files :
|
||||
# Project lines :
|
||||
# Project comments :
|
||||
# Project functions:
|
||||
# Project program :
|
||||
#
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import os, sys
|
||||
|
||||
|
||||
#===============#
|
||||
# Error message #
|
||||
#---------------#
|
||||
def error_message(path):
|
||||
print("! Installation error, unused:", path)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
#======================================================#
|
||||
# A little checker to be sure, all files are installed #
|
||||
#------------------------------------------------------#
|
||||
#===================================#
|
||||
# Check Tyto directoryies and files #
|
||||
# Insert directories #
|
||||
#-----------------------------------#
|
||||
def check_install():
|
||||
os.path.exists(libs) or error_message(libs)
|
||||
os.path.exists(trfs) or error_message(trfs)
|
||||
# Settings
|
||||
error = False
|
||||
lib_tyto = "/var/lib/tyto/%s"
|
||||
|
||||
for f in prog_files:
|
||||
f = os.path.join(libs, f + ".py")
|
||||
if not os.path.exists(f):
|
||||
error_message(f)
|
||||
log_m = "! Tyto installation. Unused"
|
||||
|
||||
# Only default lang files
|
||||
for f in lang_files:
|
||||
f = os.path.join(trfs, f + ".py")
|
||||
if not os.path.exists(f):
|
||||
error_message(f)
|
||||
|
||||
|
||||
|
||||
#======#=======================================================================
|
||||
# MAIN #
|
||||
#======#
|
||||
if not __name__ == "__main__":
|
||||
print("! Error: '%s' not '%s'"%(__name__, "__main__"))
|
||||
sys.exit(1)
|
||||
|
||||
# files list in /program/
|
||||
prog_files = {
|
||||
# Files trees
|
||||
files = {
|
||||
"program" : (
|
||||
"args",
|
||||
"check",
|
||||
"debug",
|
||||
"domain",
|
||||
"forms",
|
||||
"feed",
|
||||
"form",
|
||||
"help",
|
||||
"langs",
|
||||
"modules",
|
||||
"new",
|
||||
"page",
|
||||
"post",
|
||||
"show",
|
||||
"publish",
|
||||
"sitemap",
|
||||
"tools",
|
||||
"tyto",
|
||||
"userset",
|
||||
"wip"
|
||||
}
|
||||
lang_files = {
|
||||
"logs_en",
|
||||
"wip",
|
||||
),
|
||||
"translations" : (
|
||||
"logs_fr",
|
||||
"website_en",
|
||||
"website_fr"
|
||||
"logs_en",
|
||||
"site_fr",
|
||||
"site_en",
|
||||
),
|
||||
}
|
||||
|
||||
# Set librairies to import app files
|
||||
libs = "/var/lib/tyto/program"
|
||||
trfs = "/var/lib/tyto/translations"
|
||||
for d in files:
|
||||
tyto_dir = lib_tyto%d
|
||||
if not os.path.exists(tyto_dir):
|
||||
print("%s directory:"%log_m, tyto_dir)
|
||||
error = True
|
||||
continue
|
||||
|
||||
# Insert path
|
||||
sys.path.insert(0, tyto_dir)
|
||||
|
||||
for f in files[d]:
|
||||
tyto_file = os.path.join(tyto_dir, f + ".py")
|
||||
if not os.path.exists(tyto_file):
|
||||
print("%s file:"%llog_m, tyto_file)
|
||||
error = True
|
||||
|
||||
error and sys.exit(1)
|
||||
|
||||
|
||||
#=============================================================================#
|
||||
# Main #
|
||||
#======#
|
||||
if not __name__ == "__main__":
|
||||
print("! Process error: '%s' not '%s'"%(__name__, "__main__"))
|
||||
sys.exit(1)
|
||||
|
||||
# Check installed files
|
||||
check_install()
|
||||
|
||||
sys.path.insert(0, libs)
|
||||
sys.path.insert(0, trfs)
|
||||
|
||||
# Manage arguments from command line, start process
|
||||
import args
|
||||
args.start_process()
|
||||
# Load some Tyto libs
|
||||
import langs, debug, args, domain
|
||||
|
||||
#==========#
|
||||
# Language #
|
||||
#==========#
|
||||
langs.load_logs() # Load logs language
|
||||
|
||||
|
||||
#========#
|
||||
# Domain #
|
||||
#========#
|
||||
domain.check_home() # Mainly check current directory
|
||||
|
||||
|
||||
#===========#
|
||||
# Arguments #
|
||||
#===========#
|
||||
args.get_arguments() # Get arguments from command line
|
||||
|
||||
# First starting logs
|
||||
debug.out(200, os.getlogin(), domain.user_dir, False, 0, False)
|
||||
debug.out(201, langs.logs_lang, langs.logs_uri, False, 0, False)
|
||||
if domain.in_hole:
|
||||
debug.out(4, "$PWD ?", domain.user_dir, True, 2, True)
|
||||
|
||||
if args.err_action: # [action] error (only)
|
||||
debug.out(2, "[action]", args.err_action, False, 2, False)
|
||||
|
||||
|
||||
#===============#
|
||||
# Start process #
|
||||
#===============#
|
||||
import check, help, new, wip, publish
|
||||
|
||||
# From command line [ACTION], do
|
||||
do = {
|
||||
"check" : check.manage,
|
||||
"help" : help.manage,
|
||||
"new" : new.manage,
|
||||
"publish" : publish.manage,
|
||||
"wip" : wip.manage,
|
||||
"start" : domain.manage,
|
||||
"stop" : domain.manage,
|
||||
|
||||
}
|
||||
|
||||
do[args.action]()
|
||||
"""
|
||||
try: do[args.action]()
|
||||
except KeyError: debug.out(90, args.action, "", True, 2, True)
|
||||
"""
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -14,101 +14,177 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Manage arguments from command line
|
||||
# File: /var/lib/tyto/program/args.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import sys
|
||||
import langs, tyto, debug, help, new, check, userset, show, wip
|
||||
|
||||
|
||||
#==================#
|
||||
# Action Arguments #
|
||||
#------------------#
|
||||
def get_action():
|
||||
global action
|
||||
try: action = sys.argv[1]
|
||||
except: action = ""
|
||||
#======================================================#
|
||||
# Get action at first position #
|
||||
# Set options for other arguments (no position matter) #
|
||||
#------------------------------------------------------#
|
||||
def get_arguments():
|
||||
global commands, action, err_action, set_module
|
||||
|
||||
|
||||
#==================#
|
||||
# Target arguments #
|
||||
#------------------#
|
||||
def get_target():
|
||||
global target, targets
|
||||
try: target = sys.argv[2]
|
||||
except: target = ""
|
||||
|
||||
targets = False
|
||||
if target == "all": targets = True
|
||||
|
||||
|
||||
#================================#
|
||||
# Searching options in arguments #
|
||||
# Done only once #
|
||||
#--------------------------------#
|
||||
def get_options():
|
||||
global dlogs, force, erron, set_options
|
||||
|
||||
try: set_options ; return
|
||||
except: pass
|
||||
|
||||
dlogs = force = erron = False
|
||||
for arg in range(1, len(sys.argv)):
|
||||
if sys.argv[arg] in tyto.debug_options: dlogs = True
|
||||
if sys.argv[arg] in tyto.force_options: force = True
|
||||
if sys.argv[arg] in tyto.debug_errors: erron = True
|
||||
|
||||
set_options = True
|
||||
|
||||
|
||||
#===========#
|
||||
# Show logs #
|
||||
#-----------#
|
||||
def valid_action():
|
||||
global action
|
||||
|
||||
if not action in tyto.actions:
|
||||
debug.out(1, "[action]", action, False, 2, False)
|
||||
action = "help"
|
||||
|
||||
|
||||
#==============#
|
||||
# Start action #
|
||||
#--------------#
|
||||
def start_process():
|
||||
# Set Lang logs
|
||||
langs.load_logs_lang()
|
||||
|
||||
get_options()
|
||||
get_action()
|
||||
get_target()
|
||||
valid_action()
|
||||
|
||||
do = {
|
||||
"help" : help.show,
|
||||
"check" : check.manage,
|
||||
"new" : new.manage,
|
||||
"set" : userset.manage,
|
||||
"start" : userset.manage,
|
||||
"stop" : userset.manage,
|
||||
"show" : show.manage,
|
||||
"wip" : wip.manage,
|
||||
commands = {
|
||||
"actions" : {
|
||||
"check" : False,
|
||||
"wip" : False,
|
||||
"publish" : False,
|
||||
"new" : False,
|
||||
"start" : False,
|
||||
"stop" : False,
|
||||
"help" : False,
|
||||
},
|
||||
"targets" : {
|
||||
"*.tyto" : (),
|
||||
"all" : False,
|
||||
"domain" : False,
|
||||
"sitemap" : False,
|
||||
},
|
||||
"modules" : {
|
||||
"modules" : False,
|
||||
"metas" : False,
|
||||
"header" : False,
|
||||
"navbar" : False,
|
||||
"sidebar" : False,
|
||||
"footer" : False,
|
||||
},
|
||||
"options" : {
|
||||
"-v" : False,
|
||||
"-E" : False,
|
||||
},
|
||||
}
|
||||
|
||||
do[action](action, target)
|
||||
# Arguments from command line
|
||||
# ---------------------------
|
||||
set_module = False
|
||||
for user_arg in range(2, len(sys.argv)):
|
||||
# Register articles
|
||||
if sys.argv[user_arg].endswith(".tyto"):
|
||||
commands["targets"]["*.tyto"] = \
|
||||
commands["targets"]["*.tyto"] + (sys.argv[user_arg],)
|
||||
|
||||
# Register targets
|
||||
for arg in commands["targets"]:
|
||||
if not commands["targets"][arg] \
|
||||
and sys.argv[user_arg] == arg:
|
||||
commands["targets"][arg] = True
|
||||
continue
|
||||
|
||||
# Register modules
|
||||
for arg in commands["modules"]:
|
||||
if not commands["modules"][arg] \
|
||||
and sys.argv[user_arg] == arg:
|
||||
commands["modules"][arg] = True
|
||||
set_module = True
|
||||
continue
|
||||
|
||||
# Register options
|
||||
for arg in commands["options"]:
|
||||
if sys.argv[user_arg] == arg:
|
||||
commands["options"][sys.argv[user_arg]] = True
|
||||
continue
|
||||
|
||||
# Action, the first argument
|
||||
# --------------------------
|
||||
err_action = True
|
||||
try: action = sys.argv[1]
|
||||
except: action = "help" ; err_action = False ; return
|
||||
for arg in commands["actions"]:
|
||||
if action == arg:
|
||||
commands["actions"][arg] = True
|
||||
err_action = False
|
||||
break
|
||||
|
||||
if err_action:
|
||||
err_action = action
|
||||
action = "help"
|
||||
return
|
||||
|
||||
|
||||
"""
|
||||
global err_act, action, actions, article, targets, logall, erron, force
|
||||
|
||||
hlp_actions = ("help", "-h", "--help")
|
||||
|
||||
actions = (
|
||||
"check", "wip", "publish",
|
||||
"start", "stop",
|
||||
"new", hlp_actions,
|
||||
)
|
||||
debug_opts = ("--verbose", "-v")
|
||||
erron_opts = ("--errors", "-E")
|
||||
force_opts = ("--force", "-F")
|
||||
|
||||
# Options
|
||||
err_act = article = targets = logall = erron = force = False
|
||||
|
||||
# First argument must be an action
|
||||
# --------------------------------
|
||||
try: action = sys.argv[1]
|
||||
except: action = ""
|
||||
if not action in actions or action in hlp_actions:
|
||||
err_act = action
|
||||
action = "help"
|
||||
return
|
||||
|
||||
# Set other arguments passed
|
||||
# --------------------------
|
||||
global domain, modules, metas, header, navbar, sidebar, footer, set_modules
|
||||
global sitemap
|
||||
|
||||
sitemap = False
|
||||
domain = modules = metas = header = navbar = sidebar = footer = False
|
||||
set_modules = {
|
||||
"modules" : "",
|
||||
"metas" : "",
|
||||
"header" : "",
|
||||
"navbar" : "",
|
||||
"sidebar" : "",
|
||||
"footer" : "",
|
||||
}
|
||||
|
||||
for arg in range(2, len(sys.argv)):
|
||||
# ------
|
||||
# Target
|
||||
# ------
|
||||
# Argument is a .tyto article
|
||||
if not article and sys.argv[arg].endswith(".tyto"):
|
||||
article = sys.argv[arg]
|
||||
continue
|
||||
|
||||
# Other targets
|
||||
# domain
|
||||
if not domain: domain = bool(sys.argv[arg] == "domain")
|
||||
if not sitemap: sitemap = bool(sys.argv[arg] == "sitemap")
|
||||
|
||||
# Modules
|
||||
if not modules:
|
||||
modules = set_modules["modules"] = bool(sys.argv[arg] == "modules")
|
||||
if not metas:
|
||||
metas = set_modules["metas"] = bool(sys.argv[arg] == "metas")
|
||||
if not header:
|
||||
header = set_modules["header"] = bool(sys.argv[arg] == "header")
|
||||
if not navbar:
|
||||
navbar = set_modules["navbar"] = bool(sys.argv[arg] == "navbar")
|
||||
if not sidebar:
|
||||
sidebar = set_modules["sidebar"] = bool(sys.argv[arg] == "sidebar")
|
||||
if not footer:
|
||||
footer = set_modules["footer"] = bool(sys.argv[arg] == "footer")
|
||||
|
||||
|
||||
# -------
|
||||
# Options
|
||||
# -------
|
||||
if not targets: targets = bool(sys.argv[arg] == "all")
|
||||
if not logall: logall = bool(sys.argv[arg] in debug_opts)
|
||||
if not erron: erron = bool(sys.argv[arg] in erron_opts)
|
||||
if not force: force = bool(sys.argv[arg] in force_opts)
|
||||
"""
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,95 +14,75 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Add more logs when debug is set in command line
|
||||
# Description: Show logs in console. Manage verbose mode (-v)
|
||||
# File: /var/lib/tyto/program/debug.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import sys
|
||||
import langs, args, logs
|
||||
|
||||
import args, langs, domain
|
||||
|
||||
|
||||
#===================#
|
||||
# Messages for logs #
|
||||
#-------------------#
|
||||
def set_messages():
|
||||
global messages, got_messages
|
||||
global messages, loaded_messages
|
||||
|
||||
try: got_messages ; return
|
||||
try: loaded_messages ; return
|
||||
except: pass
|
||||
|
||||
messages = \
|
||||
{
|
||||
# ERRORS (1-100)
|
||||
1 : langs.logs.err_arg,
|
||||
2 : langs.logs.err_hole,
|
||||
3 : langs.logs.err_dir,
|
||||
4 : langs.logs.err_cd,
|
||||
5 : langs.logs.err_no_file,
|
||||
6 : langs.logs.err_no_dir,
|
||||
7 : langs.logs.err_cr_file,
|
||||
8 : langs.logs.err_lang,
|
||||
9 : langs.logs.err_ini_file,
|
||||
10 : langs.logs.err_post_global,
|
||||
11 : langs.logs.err_post_not_chk,
|
||||
13 : langs.logs.err_post_not_www,
|
||||
20 : langs.logs.err_bad_uri,
|
||||
21 : langs.logs.err_post_sep,
|
||||
22 : langs.logs.err_post_head,
|
||||
23 : langs.logs.err_post_empty,
|
||||
50 : langs.logs.err_date,
|
||||
51 : langs.logs.err_post_data,
|
||||
52 : langs.logs.err_post_title,
|
||||
53 : langs.logs.err_post_paired,
|
||||
54 : langs.logs.err_post_id_yet,
|
||||
55 : langs.logs.err_post_in_tag,
|
||||
56 : langs.logs.err_post_datatag,
|
||||
# WARNINGS (100-200)
|
||||
100 : langs.logs.warn_no_dom,
|
||||
101 : langs.logs.domain_created,
|
||||
102 : langs.logs.reset_dom,
|
||||
103 : langs.logs.website_lang,
|
||||
104 : langs.logs.domains_no,
|
||||
105 : langs.logs.domain_off,
|
||||
106 : langs.logs.warn_post_chk,
|
||||
# Great (200-255)
|
||||
200 : langs.logs.load_file,
|
||||
201 : langs.logs.lang_logs_sys,
|
||||
202 : langs.logs.domain_found,
|
||||
203 : langs.logs.created_dir,
|
||||
204 : langs.logs.domain_updated,
|
||||
205 : langs.logs.domain_new,
|
||||
206 : langs.logs.created_file,
|
||||
207 : langs.logs.updated_file,
|
||||
208 : langs.logs.website_lang,
|
||||
209 : langs.logs.domain_on,
|
||||
210 : langs.logs.post_chk_yet,
|
||||
211 : langs.logs.checking_post,
|
||||
212 : langs.logs.wipping_post,
|
||||
214 : langs.logs.reading_domain,
|
||||
215 : langs.logs.processing,
|
||||
216 : langs.logs.create_sitemaps,
|
||||
250 : langs.logs.completed,
|
||||
254 : langs.logs.post_chk_ready,
|
||||
255 : langs.logs.later,
|
||||
2 : langs.logs.err_argument,
|
||||
3 : langs.logs.err_domain_name,
|
||||
4 : langs.logs.err_in_hole,
|
||||
5 : langs.logs.err_file_create,
|
||||
6 : langs.logs.err_dir_unused,
|
||||
7 : langs.logs.err_dir_create,
|
||||
8 : langs.logs.err_lang_no,
|
||||
9 : langs.logs.err_domain_dir,
|
||||
10 : langs.logs.err_dir_in,
|
||||
11 : langs.logs.err_file_no,
|
||||
12 : langs.logs.err_post_db,
|
||||
13 : langs.logs.err_post_srv_no,
|
||||
30 : langs.logs.err_post_sep,
|
||||
31 : langs.logs.err_post_header_no,
|
||||
32 : langs.logs.err_post_writer_no,
|
||||
33 : langs.logs.err_post_tag_set,
|
||||
34 : langs.logs.err_post_tag_val,
|
||||
35 : langs.logs.err_post_tag_id,
|
||||
36 : langs.logs.err_post_mark_no,
|
||||
37 : langs.logs.err_post_mark_stop,
|
||||
38 : langs.logs.err_post_mark_miss,
|
||||
39 : langs.logs.warn_post_tupic,
|
||||
90 : langs.logs.err_process,
|
||||
99 : langs.logs.err_kbd_stop,
|
||||
# WARNINGS
|
||||
100 : langs.logs.warn_domain_no,
|
||||
101 : langs.logs.warn_date_format,
|
||||
102 : langs.logs.warn_domain_conf,
|
||||
199 : langs.logs.warn_maybe_later,
|
||||
# INFOS (200-255)
|
||||
200 : langs.logs.inf_dir_user,
|
||||
201 : langs.logs.inf_lang_logs,
|
||||
202 : langs.logs.inf_domain_load,
|
||||
203 : langs.logs.inf_domain_conf,
|
||||
205 : langs.logs.inf_file_create,
|
||||
206 : langs.logs.inf_file_upd,
|
||||
207 : langs.logs.inf_dir_create,
|
||||
210 : langs.logs.inf_check_post,
|
||||
211 : langs.logs.inf_wip_process,
|
||||
212 : langs.logs.inf_mod_process,
|
||||
250 : langs.logs.inf_end_process,
|
||||
}
|
||||
|
||||
got_messages = True
|
||||
loaded_messages = True
|
||||
|
||||
|
||||
#===================================#
|
||||
|
@ -118,18 +98,13 @@ def set_messages():
|
|||
def out(nbr, var, val, show, color, stop):
|
||||
set_messages()
|
||||
|
||||
logs.add_line(nbr, messages[nbr], var, val)
|
||||
# File log printing
|
||||
# -----------------
|
||||
#logit(nbr, var, val)
|
||||
|
||||
args.get_options()
|
||||
logit = show or args.erron and color > 0 or args.dlogs
|
||||
|
||||
if args.erron:
|
||||
if color == 0:
|
||||
logit = False
|
||||
|
||||
if not logit:
|
||||
return nbr
|
||||
|
||||
# Front User Console
|
||||
# ------------------
|
||||
# COlors
|
||||
CS = '\033[0;0m' # Unset
|
||||
CL = '\033[0;2m' # Gray
|
||||
|
@ -146,6 +121,12 @@ def out(nbr, var, val, show, color, stop):
|
|||
elif color == 1: SC = CY
|
||||
elif color == 2: SC = CR
|
||||
|
||||
|
||||
if not show:
|
||||
if args.commands["options"]["-v"]: show = True
|
||||
force_show = bool(color > 0 and args.commands["options"]["-E"])
|
||||
|
||||
if show or force_show:
|
||||
# Print, acoording to parameters
|
||||
print("%s*%s %s%s%s > %s%s%s < %s%s%s"%(
|
||||
SC, CS,
|
||||
|
@ -155,7 +136,6 @@ def out(nbr, var, val, show, color, stop):
|
|||
)
|
||||
)
|
||||
|
||||
|
||||
# Exit if stop = True
|
||||
if stop:
|
||||
if nbr >= 200: nbr = 0
|
||||
|
@ -163,3 +143,11 @@ def out(nbr, var, val, show, color, stop):
|
|||
|
||||
return nbr
|
||||
|
||||
|
||||
#============#
|
||||
# Files logs #================================================================
|
||||
#------------#
|
||||
def logit(nbr, var, val):
|
||||
try: domain.name
|
||||
except: domain.name = ""
|
||||
print(": debug. domain name", domain.name)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,191 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Create RSS/feed (when publish only)
|
||||
# File: /var/lib/tyto/program/feed.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import os, configparser, datetime, glob
|
||||
import domain, args, debug, tools, langs
|
||||
|
||||
|
||||
#=========================================#
|
||||
# Create RSS/Feed file in www server only #
|
||||
# Only published articles are included #
|
||||
# Feed can be deactivated in domain conf #
|
||||
#-----------------------------------------#
|
||||
def create():
|
||||
max_item = int(domain.cf.get("WEBSITE_MODULES", "rss_items"))
|
||||
if max_item == 0:
|
||||
return
|
||||
|
||||
db_dir = domain.wrk_dirs["db"]
|
||||
|
||||
# Scan DB directory and sort files by last updated
|
||||
items = filter(os.path.isfile, glob.glob(db_dir + '*.ini'))
|
||||
items = sorted(items, key = os.path.getmtime, reverse=True)
|
||||
|
||||
nbr_item = 0
|
||||
feed_items = ""
|
||||
bld_date = tools.nowdate("feed") # General Build date
|
||||
|
||||
for db_uri in items:
|
||||
if nbr_item == max_item:
|
||||
print("MAX")
|
||||
break
|
||||
|
||||
if not check_db(db_uri):
|
||||
continue
|
||||
|
||||
nbr_item += 1
|
||||
pub_date = datetime.datetime.strptime(DB["date"], '%Y-%m-%d').date()
|
||||
pub_date = pub_date.strftime("%a, %d %b %Y")
|
||||
|
||||
feed_item = \
|
||||
feed_item_tpl%(
|
||||
nbr_item, max_item,
|
||||
DB["title"],
|
||||
DB["www_url"],
|
||||
DB["www_url"],
|
||||
pub_date,
|
||||
DB["about"],
|
||||
DB["authors"],
|
||||
DB["logo"],
|
||||
"%s (logo)"%DB["title"],
|
||||
DB["www_url"],
|
||||
DB["tags"]
|
||||
)
|
||||
|
||||
|
||||
if not feed_items: feed_items = feed_item
|
||||
else: feed_items = "%s\n%s"%(feed_items, feed_item)
|
||||
|
||||
feed = \
|
||||
feed_tpl%(
|
||||
bld_date,
|
||||
domain.web["www"] + domain.cf.get("TEMPLATE_FILENAMES", "rss"),
|
||||
domain.conf["title"],
|
||||
domain.web["www"],
|
||||
domain.conf["about"],
|
||||
domain.web["www"] + "template/" + domain.cf.get("TEMPLATE_FILENAMES", "logo"),
|
||||
"%s (logo)"%(domain.conf["title"]),
|
||||
domain.web["www"],
|
||||
domain.lang,
|
||||
domain.conf["tags"],
|
||||
bld_date,
|
||||
domain.cf.get("WEBSITE", "license"),
|
||||
domain.conf["mail"],
|
||||
feed_items
|
||||
)
|
||||
|
||||
feed_uri = domain.www + domain.cf.get("TEMPLATE_FILENAMES", "rss")
|
||||
tools.create_file(feed_uri, feed)
|
||||
|
||||
debug.out(250, "RSS/Feed", feed_uri, True, 0, False)
|
||||
|
||||
|
||||
#===============================#
|
||||
# Check/Set article DB #
|
||||
# Check if article can be added #
|
||||
#-------------------------------#
|
||||
def check_db(db_uri):
|
||||
global DB
|
||||
|
||||
cf = configparser.ConfigParser()
|
||||
cf.read(db_uri)
|
||||
|
||||
try:
|
||||
DB = {
|
||||
"uri_web" : cf.get("URIS", "web"),
|
||||
"title" : cf.get("ARTICLE", "title"),
|
||||
"about" : cf.get("ARTICLE", "about"),
|
||||
"tags" : cf.get("ARTICLE", "tags"),
|
||||
"date" : cf.get("ARTICLE", "date"),
|
||||
"authors" : cf.get("ARTICLE", "authors"),
|
||||
"logo" : cf.get("ARTICLE", "logo"),
|
||||
"www_url" : cf.get("ARTICLE", "www_url"),
|
||||
"hash_www" : cf.get("HASHES", "www"),
|
||||
"norss" : cf.getboolean("MODULES", "norss"),
|
||||
}
|
||||
except:
|
||||
return False
|
||||
|
||||
if not DB["hash_www"] or DB["norss"]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#======#
|
||||
# MAIN #=======================================================================
|
||||
#======#
|
||||
#=======================#
|
||||
# RSS/Feed xml template #
|
||||
#-----------------------#
|
||||
feed_tpl = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
|
||||
<!-- #==========================================# -->
|
||||
<!-- # RSS/Feed generated by Tyto - Littérateur # -->
|
||||
<!-- #==========================================# -->
|
||||
<!-- Creation date: %s -->
|
||||
<!-- Feed URL: %s -->
|
||||
|
||||
|
||||
<rss version="2.0">
|
||||
|
||||
<channel>
|
||||
<title>%s</title>
|
||||
<link>%s</link>
|
||||
<description>%s</description>
|
||||
<image>'
|
||||
<url>%s</url>
|
||||
<title>%s</title>
|
||||
<link>%s</link>
|
||||
</image>
|
||||
<language>%s</language>
|
||||
<category>%s</category>
|
||||
<lastBuildDate>%s</lastBuildDate>
|
||||
<copyright>%s</copyright>
|
||||
<webMaster>%s</webMaster>
|
||||
<generator>Tyto - Littérateur</generator>
|
||||
|
||||
<!-- Articles ordred by last update -->
|
||||
%s
|
||||
</channel>
|
||||
|
||||
</rss>
|
||||
"""
|
||||
|
||||
feed_item_tpl = """<!-- Item %s/%s -->
|
||||
<item>
|
||||
<title>%s</title>
|
||||
<link>%s</link>
|
||||
<guid>%s</guid>
|
||||
<pubDate>%s</pubDate>
|
||||
<description>%s</description>
|
||||
<author>%s</author>
|
||||
<image>
|
||||
<url>%s</url>
|
||||
<title>%s</title>
|
||||
<link>%s</link>
|
||||
</image>
|
||||
<category>%s</category>
|
||||
</item>"""
|
|
@ -0,0 +1,179 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Manage forms. When a question is asked.
|
||||
# File: /var/lib/tyto/program/forms.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import os, sys
|
||||
import langs, domain, debug, tools
|
||||
|
||||
|
||||
#======================================================#
|
||||
# Ask a question #
|
||||
# in yes_mod, value is from local langs.logs.ok values #
|
||||
# has a keyboad interrupt #
|
||||
#------------------------------------------------------#
|
||||
def ask(q, yes_mod, default):
|
||||
answer = expected = ""
|
||||
if yes_mod:
|
||||
expected = langs.logs.ok
|
||||
|
||||
try:
|
||||
answer = input(q)
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
debug.out(99, q, expected, False, 2, True)
|
||||
|
||||
if yes_mod:
|
||||
for ok in expected:
|
||||
if answer.lower() == ok.lower():
|
||||
return True
|
||||
debug.out(199, q, expected, True, 1, True)
|
||||
|
||||
if default and not answer: return default
|
||||
elif not answer: return False
|
||||
|
||||
return answer
|
||||
|
||||
|
||||
#=========================#
|
||||
# Confirm domain creation #
|
||||
#-------------------------#
|
||||
def ask_domain_creation():
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_domain_name, domain.name, langs.logs.q)
|
||||
|
||||
# Create domain configuration file
|
||||
if ask(q, True, ""):
|
||||
domain.cf_create()
|
||||
|
||||
|
||||
#=================================================#
|
||||
# Forms #
|
||||
# Each questions are asked from domain.user_set() #
|
||||
# In mismatch case, question is asked again #
|
||||
#-------------------------------------------------#
|
||||
#======================#
|
||||
# Ask for domain title #
|
||||
#----------------------#
|
||||
def ask_domain_title(default):
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_domain_title, default, langs.logs.q)
|
||||
|
||||
return ask(q, False, default) or ""
|
||||
|
||||
|
||||
#==============================#
|
||||
# Ask for domain creation date #
|
||||
#------------------------------#
|
||||
def ask_domain_date(default):
|
||||
default = tools.nowdate("int-short").rsplit("-")[0] # Set year only
|
||||
debug.out(101, "[YYYY[-MM][-DD]]", "", True, 0, False)
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_domain_date, default, langs.logs.q)
|
||||
|
||||
return ask(q, False, default) or ""
|
||||
|
||||
|
||||
#============================#
|
||||
# Ask for domain description #
|
||||
#----------------------------#
|
||||
def ask_domain_about(default):
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_domain_about, default, langs.logs.q)
|
||||
|
||||
return ask(q, False, default) or ""
|
||||
|
||||
|
||||
#=====================#
|
||||
# Ask for domain tags #
|
||||
#---------------------#
|
||||
def ask_domain_tags(default):
|
||||
default = domain.cf.get("DOMAIN", "title") + ","
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_domain_tags, default, langs.logs.q)
|
||||
|
||||
return ask(q, False, default) or ""
|
||||
|
||||
|
||||
#============================#
|
||||
# Ask for administrator mail #
|
||||
#----------------------------#
|
||||
def ask_domain_mail(default):
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_domain_mail, default, langs.logs.q)
|
||||
|
||||
return ask(q, False, default) or ""
|
||||
|
||||
|
||||
#=============================#
|
||||
# Ask for wzbsite language #
|
||||
# Check if translation exists #
|
||||
#-----------------------------#
|
||||
def ask_website_lang(default):
|
||||
default = langs.logs_lang
|
||||
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_website_lang, default, langs.logs.q)
|
||||
|
||||
lang = ask(q, False, default)
|
||||
if not os.path.exists(langs.lang_files["site"]["uri"]%lang):
|
||||
debug.out(8, lang, langs.lang_files["site"]["uri"]%lang, True, 2, False)
|
||||
lang = ""
|
||||
|
||||
return lang
|
||||
|
||||
|
||||
#===============================#
|
||||
# Ask for server root directory #
|
||||
# Check if directory exists #
|
||||
#-------------------------------#
|
||||
def ask_srv_root(default):
|
||||
srv_uris = (default, "/var/www/", "/srv/http/")
|
||||
for srv_uri in srv_uris:
|
||||
if os.path.exists(srv_uri):
|
||||
default = srv_uri
|
||||
break;
|
||||
|
||||
q = '- %s "%s"%s '%(
|
||||
langs.logs.ask_srv_root, default, langs.logs.q)
|
||||
|
||||
srv_uri = ask(q, False, default)
|
||||
if srv_uri:
|
||||
if not srv_uri.endswith("/"):
|
||||
srv_uri = srv_uri + "/"
|
||||
if not os.path.exists(srv_uri):
|
||||
debug.out(6, q, srv_uri, True, 2, False)
|
||||
srv_uri = ""
|
||||
|
||||
return srv_uri
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
def ask_reset_modules():
|
||||
q = "- %s%s "%(langs.logs.ask_reset_modules, langs.logs.q)
|
||||
|
||||
if ask(q, True, ""):
|
||||
return
|
||||
|
|
@ -14,30 +14,64 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Show help commands
|
||||
# Description: Show help, and manage some arguments with it
|
||||
# File: /var/lib/tyto/program/help.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
import sys
|
||||
import args, langs
|
||||
|
||||
import langs, debug
|
||||
#
|
||||
#
|
||||
#
|
||||
def manage():
|
||||
helps = {
|
||||
"new" : langs.logs.help_new,
|
||||
"check" : langs.logs.help_check,
|
||||
"wip" : langs.logs.help_wip,
|
||||
"modules" : langs.logs.help_modules,
|
||||
"list" : langs.logs.help_list,
|
||||
"cite" : langs.logs.help_cite,
|
||||
"image" : langs.logs.help_image,
|
||||
"link" : langs.logs.help_link,
|
||||
"file" : langs.logs.help_file,
|
||||
"code" : langs.logs.help_code,
|
||||
"words" : langs.logs.help_words,
|
||||
"abbr" : langs.logs.help_abbr,
|
||||
"anchor" : langs.logs.help_anc,
|
||||
"raw" : langs.logs.help_raw,
|
||||
"article" : langs.logs.help_article,
|
||||
}
|
||||
|
||||
norepeat = \
|
||||
(
|
||||
"list", "cite", "image", "link", "words", "code", "raw", "abbr", "anchor",
|
||||
"file",
|
||||
)
|
||||
|
||||
try:
|
||||
sys.argv[2]
|
||||
if not sys.argv[2] in helps: show_main = True
|
||||
else: show_main = False
|
||||
except:
|
||||
show_main = True
|
||||
|
||||
if show_main:
|
||||
print(langs.logs.help_man)
|
||||
|
||||
if args.commands["targets"]["all"]:
|
||||
for h in helps:
|
||||
if not h in norepeat:
|
||||
print(helps[h])
|
||||
return
|
||||
|
||||
for arg in range(2, len(sys.argv)):
|
||||
if sys.argv[arg] in helps:
|
||||
print(helps[sys.argv[arg]])
|
||||
|
||||
|
||||
#==========================================#
|
||||
# Show help in system langage #
|
||||
# Help Contents is in translations/logs_XX #
|
||||
#------------------------------------------#
|
||||
def show(action, target):
|
||||
print(langs.logs.help_contents)
|
||||
|
|
|
@ -14,127 +14,65 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Load lang logs file according to system language
|
||||
# Load lang site file according to domain configuration
|
||||
# Description: Set languages for logs and website
|
||||
# File: /var/lib/tyto/program/langs.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import sys, locale, os
|
||||
import args, debug, domain
|
||||
import locale
|
||||
import domain
|
||||
|
||||
|
||||
trfs = "/var/lib/tyto/translations/"
|
||||
# Settings files
|
||||
def set_lang_files():
|
||||
global lang_files, files_set
|
||||
|
||||
#==================================#
|
||||
# Check if translation file exists #
|
||||
# module: #
|
||||
# - "logs": logs_xx #
|
||||
# - "website": website_xx #
|
||||
# lang: 2 chars language #
|
||||
# out: exit if True
|
||||
# return True or False #
|
||||
#----------------------------------#
|
||||
def translation_exists(module, lang, out):
|
||||
global tr_file
|
||||
lang_files = \
|
||||
{
|
||||
"logs" : {
|
||||
"name" : "logs_%s",
|
||||
"uri" : "/var/lib/titi/translations/logs_%s.py",
|
||||
},
|
||||
"site" : {
|
||||
"name" : "site_%s",
|
||||
"uri" : "/var/lib/titi/translations/site_%s.py",
|
||||
},
|
||||
}
|
||||
|
||||
modules = ("logs", "website")
|
||||
# in case of internal typo error
|
||||
if not module in modules:
|
||||
print("! langs: internal error: 'logs', 'website'")
|
||||
sys.exit(254)
|
||||
|
||||
tr_file = "%s%s_%s.py"%(trfs, module, lang)
|
||||
if not os.path.exists(tr_file):
|
||||
debug.out(5, lang, tr_file, True, 2, False)
|
||||
return False
|
||||
|
||||
return True
|
||||
files_set = True
|
||||
|
||||
|
||||
#=============================================================================#
|
||||
# LOGS | #
|
||||
# Set and import file | #
|
||||
#=============================================================================#
|
||||
#=============================#
|
||||
# Get system Lang to set logs #
|
||||
#-----------------------------#
|
||||
def get_sys_lang():
|
||||
global lang, tr_logs_uri
|
||||
# Use logs from system language or default "en"
|
||||
def load_logs():
|
||||
global logs, logs_lang, logs_uri
|
||||
|
||||
tr_logs_uri = "%slogs_%s.py"
|
||||
|
||||
try: lang = locale.getdefaultlocale()[0].rsplit("_")[0]
|
||||
except: lang = "en"
|
||||
|
||||
if not translation_exists("logs", lang, False):
|
||||
lang = "en"
|
||||
|
||||
tr_logs_uri = tr_logs_uri%(trfs, lang)
|
||||
|
||||
return lang
|
||||
|
||||
|
||||
#===============================#
|
||||
# Import logs lang file in logs #
|
||||
#-------------------------------#
|
||||
def load_logs_lang():
|
||||
global logs, lang, set_logs
|
||||
set_lang_files()
|
||||
|
||||
try:
|
||||
set_logs
|
||||
logs_lang = locale.getdefaultlocale()[0].rsplit("_")[0]
|
||||
except:
|
||||
logs = __import__("logs_%s"%get_sys_lang())
|
||||
debug.out(201, lang, tr_logs_uri, False, 0, False)
|
||||
set_logs = True
|
||||
logs_lang = "en"
|
||||
|
||||
# Load language file
|
||||
logs_name = lang_files["logs"]["name"]%logs_lang
|
||||
logs_uri = lang_files["logs"]["uri"]%logs_lang
|
||||
logs = __import__(logs_name)
|
||||
|
||||
|
||||
#=============================================================================#
|
||||
# WEBSITE | #
|
||||
# Get/Set and import file | #
|
||||
#=============================================================================#
|
||||
#=======================================#
|
||||
# Get website lang from cf to set site #
|
||||
#---------------------------------------#
|
||||
def get_website_lang():
|
||||
global site_lang, tr_website_uri
|
||||
# loan language website values
|
||||
def load_site():
|
||||
global site
|
||||
|
||||
tr_website_uri = "%swebsite_%s.py"
|
||||
try: site_lang = domain.cf.get("WEBSITE", "lang")
|
||||
except: site_lang = get_sys_lang()
|
||||
try: files_set
|
||||
except: set_lang_files()
|
||||
|
||||
if not translation_exists("website", site_lang, False):
|
||||
site_lang = get_sys_lang() # or default "en"
|
||||
try: site_lang = domain.lang
|
||||
except: site_lang = "en"
|
||||
|
||||
tr_website_uri = tr_website_uri%(trfs, site_lang)
|
||||
|
||||
return site_lang
|
||||
|
||||
|
||||
#==================================#
|
||||
# Import website lang file in site #
|
||||
#----------------------------------#
|
||||
def load_website_lang():
|
||||
global site, site_lang, set_site
|
||||
|
||||
site = __import__("website_%s"%get_website_lang())
|
||||
|
||||
try:
|
||||
set_site
|
||||
except:
|
||||
debug.out(208, site_lang, tr_website_uri, False, 0, False)
|
||||
set_site = True
|
||||
try: site = __import__(lang_files["site"]["name"]%site_lang)
|
||||
except: site = __import__(lang_files["site"]["name"]%"en")
|
||||
|
||||
|
|
|
@ -0,0 +1,601 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Manage modules creations (metas, to footer called by nginx)
|
||||
# File: /var/lib/tyto/program/modules.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import os, ast, configparser
|
||||
import args, domain, langs, tools, debug, form
|
||||
|
||||
|
||||
#=================================================#
|
||||
# Manage modules creations #
|
||||
# metas, header, navbar, sidebar, footer #
|
||||
# - User must configure: navbar, sidebar #
|
||||
# - Default contents: metas, header, footer #
|
||||
# From [module].raw, create [module].html #
|
||||
# All are called from file with nginx in web page #
|
||||
#-------------------------------------------------#
|
||||
def manage(module):
|
||||
global files, wrk_dir, asked, mod_write, wip_dir
|
||||
|
||||
# Set directories
|
||||
wrk_dir = domain.wrk_dirs["modules"]
|
||||
wip_dir = domain.wip_dirs["template"]
|
||||
www_dir = domain.www_dirs["template"]
|
||||
|
||||
debug.out(212, module, wrk_dir, False, 0, False)
|
||||
|
||||
files = {
|
||||
"metas" : {
|
||||
"wrk" : wrk_dir + "metas.raw",
|
||||
"wip" : wip_dir + "metas.html",
|
||||
"www" : www_dir + "metas.html",
|
||||
"set" : set_metas_raw,
|
||||
},
|
||||
"header" : {
|
||||
"wrk" : wrk_dir + "header.raw",
|
||||
"wip" : wip_dir + "header.html",
|
||||
"www" : www_dir + "header.html",
|
||||
"set" : set_header_raw,
|
||||
},
|
||||
"navbar" : {
|
||||
"wrk" : wrk_dir + "navbar.raw",
|
||||
"wip" : wip_dir + "navbar.html",
|
||||
"www" : www_dir + "navbar.html",
|
||||
"set" : set_navbar_raw,
|
||||
},
|
||||
"sidebar" : {
|
||||
"wrk" : wrk_dir + "sidebar.raw",
|
||||
"wip" : wip_dir + "sidebar.html",
|
||||
"www" : www_dir + "sidebar.html",
|
||||
"set" : set_sidebar_raw,
|
||||
},
|
||||
"footer" : {
|
||||
"wrk" : wrk_dir + "footer.raw",
|
||||
"wip" : wip_dir + "footer.html",
|
||||
"www" : www_dir + "footer.html",
|
||||
"set" : set_footer_raw,
|
||||
},
|
||||
}
|
||||
|
||||
# Load/Create new modules in DB file
|
||||
cf_mod_load()
|
||||
mod_write = False
|
||||
|
||||
# Check/Set raw files in modules/
|
||||
for mod in files:
|
||||
# For all modules to reset, confirm once
|
||||
if os.path.exists(files[mod]["wrk"]):
|
||||
if module == "all":
|
||||
try: asked
|
||||
except: form.ask_reset_modules() ; asked = True
|
||||
|
||||
elif mod != module:
|
||||
continue
|
||||
|
||||
mod_write = True
|
||||
files[mod]["set"](mod)
|
||||
tools.create_file(files[mod]["wrk"], files[mod]["usr"])
|
||||
cid = tools.get_HID(files[mod]["wrk"], True)
|
||||
cf_mod_set("RAWS", mod, cid)
|
||||
|
||||
cf_mod_write()
|
||||
if args.action == "new":
|
||||
debug.out(250, module, wrk_dir, True, 0, False)
|
||||
|
||||
# When an article is "wip"
|
||||
# - create html modules
|
||||
# - - if not already exists
|
||||
# - - if raw module has changed
|
||||
if module == "wip":
|
||||
for mod in files:
|
||||
if os.path.exists(files[mod]["wip"]):
|
||||
raw_cid = tools.get_HID(files[mod]["wrk"], True)
|
||||
try: db_id = cf_mod.get("RAWS", mod)
|
||||
except: db_id = ""
|
||||
if raw_cid == db_id:
|
||||
continue
|
||||
else:
|
||||
cf_mod_set("RAWS", mod, raw_cid)
|
||||
mod_write = True
|
||||
|
||||
create_htmls(mod)
|
||||
|
||||
cf_mod_write()
|
||||
|
||||
# When user wants to force update HTML modules
|
||||
# using wip [MODULE] ; called in wip.py
|
||||
elif module == "update":
|
||||
# Create again ALL modules in wip/template
|
||||
if args.commands["modules"]["modules"]:
|
||||
for mod in files:
|
||||
if os.path.exists(files[mod]["wip"]):
|
||||
create_htmls(mod)
|
||||
# Create again specific module from command line
|
||||
else:
|
||||
for mod in args.commands["modules"]:
|
||||
if args.commands["modules"][mod]:
|
||||
if os.path.exists(files[mod]["wip"]):
|
||||
create_htmls(mod)
|
||||
|
||||
|
||||
#=======================================#
|
||||
# Manage modules configuration ini file #======================================
|
||||
#---------------------------------------#
|
||||
#================================#
|
||||
# Create new modules DB ini file #
|
||||
#--------------------------------#
|
||||
def cf_mod_load():
|
||||
global cf_mod_uri, cf_mod
|
||||
|
||||
cf_mod_uri = wrk_dir + "modules.ini"
|
||||
|
||||
if not os.path.exists(cf_mod_uri):
|
||||
tools.create_file(cf_mod_uri, "")
|
||||
|
||||
cf_mod = False
|
||||
cf_mod = configparser.ConfigParser()
|
||||
cf_mod.read(cf_mod_uri)
|
||||
|
||||
|
||||
#============================#
|
||||
# Set datas to cf_mod ini DB #
|
||||
#----------------------------#
|
||||
def cf_mod_set(section, key, value):
|
||||
global cf_mod
|
||||
|
||||
# Add section if not exists
|
||||
try: cf_mod.add_section(section)
|
||||
except: pass
|
||||
|
||||
cf_mod.set(section, key, value)
|
||||
|
||||
|
||||
#==================================#
|
||||
# Write to cf_mod ini DB if needed #
|
||||
#----------------------------------#
|
||||
def cf_mod_write():
|
||||
if mod_write:
|
||||
with open(cf_mod_uri, "w") as f:
|
||||
cf_mod.write(f)
|
||||
|
||||
|
||||
#==================================================#
|
||||
# Create default raw modules in modules/ directory #===========================
|
||||
#--------------------------------------------------#
|
||||
#=====================================#
|
||||
# Set metas.raw with default contents #
|
||||
#-------------------------------------#
|
||||
def set_metas_raw(mod):
|
||||
global files
|
||||
|
||||
files["metas"]["usr"] = langs.logs.metas_raw%(
|
||||
domain.conf["title"],
|
||||
domain.wrk_dirs["articles"],
|
||||
files[mod]["wrk"],
|
||||
files[mod]["wip"],
|
||||
files[mod]["www"],
|
||||
) + metas_raw
|
||||
|
||||
|
||||
#======================================#
|
||||
# Set header.raw with default contents #
|
||||
#--------------------------------------#
|
||||
def set_header_raw(mod):
|
||||
global files, header_raw
|
||||
|
||||
# ----------------------------------- #
|
||||
# Fille values for generic header_raw #
|
||||
# ----------------------------------- #
|
||||
header_raw = \
|
||||
header_raw%(
|
||||
"%s %s"%(langs.site.home, domain.conf["title"]),
|
||||
"/template/%s"%domain.cf.get("TEMPLATE_FILENAMES", "logo"),
|
||||
"logo: %s"%domain.conf["title"],
|
||||
domain.conf["title"],
|
||||
domain.conf["about"]
|
||||
)
|
||||
|
||||
files["header"]["usr"] = langs.logs.header_raw%(
|
||||
domain.conf["title"],
|
||||
domain.wrk_dirs["articles"],
|
||||
files[mod]["wrk"],
|
||||
files[mod]["wip"],
|
||||
files[mod]["www"],
|
||||
) + header_raw
|
||||
|
||||
#===============================#
|
||||
# Set navbar.raw with help only #
|
||||
#-------------------------------#
|
||||
def set_navbar_raw(mod):
|
||||
global files
|
||||
|
||||
files["navbar"]["usr"] = langs.logs.metas_raw%(
|
||||
domain.conf["title"],
|
||||
domain.wrk_dirs["articles"],
|
||||
files[mod]["wrk"],
|
||||
files[mod]["wip"],
|
||||
files[mod]["www"],
|
||||
)
|
||||
|
||||
|
||||
#================================#
|
||||
# Set sidebar.raw with help only #
|
||||
#--------------------------------#
|
||||
def set_sidebar_raw(mod):
|
||||
global files
|
||||
|
||||
files["sidebar"]["usr"] = langs.logs.sidebar_raw%(
|
||||
domain.conf["title"],
|
||||
domain.wrk_dirs["articles"],
|
||||
files[mod]["wrk"],
|
||||
files[mod]["wip"],
|
||||
files[mod]["www"],
|
||||
)
|
||||
|
||||
#======================================#
|
||||
# Set footer.raw with default contents #
|
||||
#--------------------------------------#
|
||||
def set_footer_raw(mod):
|
||||
global files, footer_raw
|
||||
|
||||
# ---------------------------------- #
|
||||
# Fill values for generic footer_raw #
|
||||
# ---------------------------------- "
|
||||
footer_menu = "<!-- Links from domain configuration [WEBSITE_FOOTER] -->"
|
||||
footer_link = \
|
||||
'\n<li class="footer_item"><a href="%s" title="%s %s">%s</a></li>'
|
||||
|
||||
for key, value in domain.cf.items("WEBSITE_FOOTER"):
|
||||
try:
|
||||
tupvalues = ast.literal_eval(value)
|
||||
footer_menu = footer_menu + \
|
||||
footer_link%(tupvalues[1], tupvalues[2], "", tupvalues[0])
|
||||
except:
|
||||
debug.out(102, "%s = %s"%(key, value), domain.cf_uri, True, 1, False)
|
||||
|
||||
if domain.conf["sitemaps"]:
|
||||
footer_menu = footer_menu + \
|
||||
footer_link%(
|
||||
"/sitemap.html",
|
||||
langs.site.sitemap, domain.conf["title"],langs.site.sitemap
|
||||
)
|
||||
|
||||
footer_menu = footer_menu + \
|
||||
footer_link%(
|
||||
"/" + domain.cf.get("TEMPLATE_FILENAMES", "rss"),
|
||||
langs.site.feed_rss, domain.conf["title"], langs.site.feed_rss
|
||||
)
|
||||
|
||||
# Copyright link
|
||||
cur_date = tools.nowdate("year")
|
||||
if domain.conf["date"][:4] != cur_date:
|
||||
cur_date = "%s - %s"%(domain.conf["date"][:4], cur_date)
|
||||
footer_copy = "Copyright © %s %s"%(cur_date, domain.conf["title"])
|
||||
|
||||
# Tyto credit links
|
||||
tyto_site_link = "https://tyto.echolib.re/"
|
||||
tyto_code_link = "https://forge.a-lec.org/echolib/tyto-litterateur"
|
||||
footer_tyto = \
|
||||
'%s <a class="footer_item_link" href="%s" title="%s">'%(
|
||||
langs.site.tyto_credit, tyto_site_link, langs.site.off_website) + \
|
||||
'Tyto - Littérateur' + \
|
||||
'</a> [<a href="%s" title="Tyto - Littérateur">'%tyto_code_link + \
|
||||
'%s'%langs.site.source_code + \
|
||||
'</a>]'
|
||||
|
||||
# Create full footer_raw contents
|
||||
footer_raw = footer_raw%(
|
||||
# <h2>
|
||||
langs.site.about, domain.conf["title"],
|
||||
# About
|
||||
domain.conf["about"],
|
||||
# Menu list items
|
||||
footer_menu,
|
||||
# Copyright and Tyto credit
|
||||
footer_copy,
|
||||
footer_tyto,
|
||||
)
|
||||
|
||||
files["footer"]["usr"] = langs.logs.footer_raw%(
|
||||
domain.conf["title"],
|
||||
domain.wrk_dirs["articles"],
|
||||
files[mod]["wrk"],
|
||||
files[mod]["wip"],
|
||||
files[mod]["www"],
|
||||
) + footer_raw
|
||||
|
||||
|
||||
#===================================================#
|
||||
# Create HTML modules files in template/ wip only #============================
|
||||
# At publish process, files are copied, not created #
|
||||
#---------------------------------------------------#
|
||||
#============================#
|
||||
# Create [module].html files #
|
||||
#----------------------------#
|
||||
def create_htmls(mod):
|
||||
html_file = "<!-- %s from user file configuration: %s.raw -->"%(mod, mod)
|
||||
|
||||
if mod == "navbar":
|
||||
html_file = create_navbar_html(html_file)
|
||||
|
||||
elif mod == "sidebar":
|
||||
html_file = create_sidebar_html(html_file)
|
||||
|
||||
else:
|
||||
with open(files[mod]["wrk"], "r") as f:
|
||||
for line in f.read().rsplit("\n"):
|
||||
if not line or line.isspace() or line.lstrip().startswith("#"):
|
||||
continue
|
||||
|
||||
html_file = "%s\n%s"%(html_file, line)
|
||||
|
||||
tools.create_file(files[mod]["wip"], html_file)
|
||||
debug.out(250, mod, wip_dir, True, 0, False)
|
||||
|
||||
|
||||
#==============================================#
|
||||
# Create HTML navbar contents, from navbar.raw #
|
||||
#----------------------------------------------#
|
||||
def create_navbar_html(html_file):
|
||||
menu_links = ""
|
||||
with open(files["navbar"]["wrk"], "r") as f:
|
||||
for ln, line in enumerate(f.read().rsplit("\n"), 1):
|
||||
line = line.lstrip()
|
||||
if not line or line.isspace() or line.startswith("#"):
|
||||
continue
|
||||
|
||||
# Item has a "title" set with # as separator
|
||||
set_dir = line.rstrip()
|
||||
|
||||
|
||||
# Set_dir begins with "/" ; apply correction
|
||||
if set_dir.startswith("/"): set_dir = set_dir[1:]
|
||||
if set_dir.endswith("/"): set_dir = set_dir[:-1]
|
||||
if not set_dir: # No home / in navbar menu
|
||||
continue
|
||||
|
||||
dir_uri = domain.wrk_dirs["articles"] + set_dir
|
||||
|
||||
# Set_dir must exists
|
||||
if not os.path.exists(dir_uri) or \
|
||||
not os.path.isdir(dir_uri):
|
||||
debug.out(6, "%s. navbar '%s'"%(
|
||||
ln, set_dir
|
||||
), files["navbar"]["wrk"], True, 1, False)
|
||||
continue
|
||||
|
||||
# Check for index.tyto, load DB if exists, get title
|
||||
if cf_load(ln, set_dir + "/index.tyto", "navbar"):
|
||||
try: set_title = cf.get("ARTICLE", "title")
|
||||
except: continue
|
||||
|
||||
# Check and inform if not index.html exists
|
||||
srv_index_html = domain.wip + "/index.html"
|
||||
if not os.path.exists(srv_index_html):
|
||||
debug.out(11, "%s. navbar (404) wip/%s/index.html"%(
|
||||
ln, set_dir
|
||||
), files["navbar"]["wrk"], True, 1, False)
|
||||
|
||||
# Create menu links
|
||||
if not menu_links:
|
||||
menu_links = navbar_link%(
|
||||
"/" + set_dir, set_title, os.path.basename(set_dir)
|
||||
)
|
||||
else:
|
||||
menu_links = "%s\n%s"%(
|
||||
menu_links,
|
||||
navbar_link%(
|
||||
"/" + set_dir, set_title, os.path.basename(set_dir)
|
||||
)
|
||||
)
|
||||
|
||||
if menu_links:
|
||||
html_file = html_file + navbar_html%menu_links
|
||||
|
||||
return html_file
|
||||
|
||||
|
||||
#================================================#
|
||||
# Create HTML sidebar contents, from sidebar.raw #
|
||||
#------------------------------------------------#
|
||||
def create_sidebar_html(html_file):
|
||||
# Set from config file max links. Return if 0
|
||||
max_items = int(domain.cf.get("WEBSITE_MODULES", "sidebar_items"))
|
||||
sidebar_title = domain.cf.get("WEBSITE_MODULES", "sidebar_title")
|
||||
if max_items == 0:
|
||||
return html_file
|
||||
|
||||
html_items = ""
|
||||
items = 0
|
||||
with open(files["sidebar"]["wrk"], "r") as f:
|
||||
for ln, line in enumerate(f.read().rsplit("\n"), 1):
|
||||
if items == max_items:
|
||||
break
|
||||
|
||||
line = line.lstrip()
|
||||
if not line or \
|
||||
line.isspace() or \
|
||||
line.startswith("#") or \
|
||||
not line.endswith(".tyto"):
|
||||
continue
|
||||
|
||||
# Target begins with "/"... Remove it
|
||||
if line.startswith("/"): line = line[1:]
|
||||
|
||||
# check/load article files
|
||||
if not cf_load(ln, line, "sidebar"):
|
||||
continue
|
||||
|
||||
items += 1
|
||||
print("> -",items, cf.get("ARTICLE", "title"))
|
||||
|
||||
if not html_items:
|
||||
html_items = sidebar_item%(
|
||||
# <h3>
|
||||
cf.get("URIS", "web"),
|
||||
cf.get("ARTICLE", "title"),
|
||||
# <p title="">
|
||||
cf.get("ARTICLE", "title"),
|
||||
cf.get("ARTICLE", "authors"),
|
||||
cf.get("ARTICLE", "local_date"),
|
||||
# Show about
|
||||
cf.get("ARTICLE", "about")
|
||||
)
|
||||
else:
|
||||
html_items = "%s\n%s"%(html_items, sidebar_item%(
|
||||
cf.get("ARTICLE", "title"),
|
||||
cf.get("ARTICLE", "about")
|
||||
)
|
||||
)
|
||||
|
||||
if html_items:
|
||||
html_file = html_file + sidebar_html%(sidebar_title, html_items)
|
||||
|
||||
return html_file
|
||||
|
||||
|
||||
#==========================================#
|
||||
# Get DB post from URI, and load if exists #
|
||||
#------------------------------------------#
|
||||
def cf_load(ln, line, modname):
|
||||
global cf
|
||||
|
||||
uri = domain.wrk_dirs["articles"] + line
|
||||
if not os.path.exists(uri):
|
||||
debug.out(11, "%s. %s '%s'"%(
|
||||
ln, modname, line
|
||||
), files[modname]["wrk"], True, 1, False)
|
||||
return False
|
||||
|
||||
db_uri = domain.wrk_dirs["db"] + tools.get_HID(uri, False) + ".ini"
|
||||
if not os.path.exists(db_uri):
|
||||
debug.out(12, "%s. %s '%s'"%(
|
||||
ln, modname, line
|
||||
), files[modname]["wrk"], True, 1, False)
|
||||
return False
|
||||
|
||||
cf = configparser.ConfigParser()
|
||||
cf.read(db_uri)
|
||||
|
||||
try: srv_uri = cf.get("URIS", "wip")
|
||||
except: srv_uri = ""
|
||||
if not srv_uri or not os.path.exists(srv_uri):
|
||||
debug.out(13, "%s. %s '%s'"%(
|
||||
ln, modname, line
|
||||
), files[modname]["wrk"], True, 1, False)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#===============#
|
||||
# MAIN settings #==============================================================
|
||||
#---------------#
|
||||
# ---------------------------- #
|
||||
# Default raw modules contents #
|
||||
# ---------------------------- #
|
||||
#-------#
|
||||
# Metas #
|
||||
#-------#
|
||||
metas_raw = """
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="all">
|
||||
<meta name="medium" content="website">
|
||||
<meta name="revisit-after" content="3 days">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
"""
|
||||
|
||||
#--------#
|
||||
# Header #
|
||||
#--------#
|
||||
header_raw = """
|
||||
<a id="site_link" href="/" title="%s">
|
||||
<header id="header">
|
||||
<div id="header_logo">
|
||||
<img id="header_logo_image" src="%s" alt="%s">
|
||||
</div>
|
||||
<div id="header_abouts">
|
||||
<p id="header_title">%s</p>
|
||||
<p id="header_about">%s</p>
|
||||
</div<
|
||||
</header>
|
||||
</a>
|
||||
"""
|
||||
|
||||
#--------#
|
||||
# Navbar #
|
||||
#--------#
|
||||
navbar_html = """
|
||||
<nav id="menu" aria-labelledby="navigation-1">
|
||||
<menu id="menu_items">
|
||||
%s
|
||||
</menu>
|
||||
</nav>
|
||||
"""
|
||||
navbar_link = '<li class="menu_item">' + \
|
||||
'<a class="menu_link" href="%s" title="%s">%s</a>' + \
|
||||
'</li>'
|
||||
|
||||
#---------#
|
||||
# Sidebar #
|
||||
#---------#
|
||||
sidebar_html = """
|
||||
<aside id="sidebar">
|
||||
<h2 id="sidebar_title">%s</h2>
|
||||
<nav id="sidebar_menu" aria-labelledby="navigation-2">
|
||||
<ul id="sidebar_items">
|
||||
%s
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
"""
|
||||
sidebar_item = """<li class="sidebar_item">
|
||||
<h3 class="sidebar_post_title"><a class="sidebar_post_link" href="%s">%s</a></h3>
|
||||
<div class="sidebar_post_about">
|
||||
<p title="%s -- %s, %s">%s</p>
|
||||
</div>
|
||||
</li>"""
|
||||
|
||||
#--------#
|
||||
# Footer #
|
||||
#--------#
|
||||
footer_raw = """
|
||||
<footer id="footer">
|
||||
<h2 id="footer_title">%s %s</h2>
|
||||
<div id="footer_about_menu">
|
||||
<div id="footer_about">
|
||||
<p id="footer_about">%s</p>
|
||||
</div>
|
||||
<nav id="footer_menu" aria-labelledby="navigation-3">
|
||||
<ul id="footer_items">
|
||||
%s
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div id="footer_credit">
|
||||
<p id="footer_copyright">%s</p>
|
||||
<p id="footer_tyto">%s</p>
|
||||
</div>
|
||||
</footer>
|
||||
"""
|
|
@ -14,60 +14,37 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: When user wants to create something new
|
||||
# Description: When something new must be created (domain, modules...)
|
||||
# File: /var/lib/tyto/program/new.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
import args, domain, form, modules, sitemap
|
||||
|
||||
import os
|
||||
import args, domain, debug, sitemaps
|
||||
def manage():
|
||||
if args.commands["targets"]["domain"]:
|
||||
domain.set_name()
|
||||
|
||||
if not domain.cf_exists():
|
||||
form.ask_domain_creation()
|
||||
|
||||
#====================================#
|
||||
# Manage arguments from command line #
|
||||
# Specific to action "new" #
|
||||
#------------------------------------#
|
||||
def manage(action, target):
|
||||
do = {
|
||||
"domain" : create_domain,
|
||||
"sitemaps" : sitemaps.manage,
|
||||
}
|
||||
|
||||
do[target]()
|
||||
|
||||
|
||||
|
||||
#===================================#
|
||||
# From command line "new domain" #
|
||||
# Create and set only if not exists #
|
||||
# or if user "force" option
|
||||
#-----------------------------------#
|
||||
def create_domain():
|
||||
# Check if in a domain set yet
|
||||
d_uri = "/"
|
||||
dirs = domain.user_dir.rsplit("/")
|
||||
for d in dirs:
|
||||
if not d:
|
||||
continue
|
||||
|
||||
d_uri = d_uri + d + "/"
|
||||
if os.path.exists(d_uri + "tyto_domain.ini"):
|
||||
debug.out(202, d, d_uri, True, 2, True)
|
||||
|
||||
domain.cf_create()
|
||||
domain.cf_load()
|
||||
domain.cf_update()
|
||||
return
|
||||
|
||||
domain.is_ready()
|
||||
if args.commands["modules"]["modules"]:
|
||||
modules.manage("all")
|
||||
return
|
||||
|
||||
args.commands["modules"]["metas"] and modules.manage("metas")
|
||||
args.commands["modules"]["header"] and modules.manage("header")
|
||||
args.commands["modules"]["navbar"] and modules.manage("navbar")
|
||||
args.commands["modules"]["sidebar"] and modules.manage("sidebar")
|
||||
args.commands["modules"]["footer"] and modules.manage("footer")
|
||||
|
||||
args.commands["modules"]["sitemap"] and sitemap.create()
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Create full HTML page
|
||||
# File: /var/lib/tyto/program/page.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import domain, post, wip, langs, tools
|
||||
|
||||
|
||||
#========================================#
|
||||
# Main function to create Full HTML Page #
|
||||
#----------------------------------------#
|
||||
def create():
|
||||
global pub_date, article, local_date
|
||||
|
||||
pub_date = tools.nowdate("int-full")
|
||||
local_date = tools.local_date(post.needed_tags["date"])
|
||||
|
||||
# Create specific article metas tags
|
||||
post_metas = article_metas()
|
||||
|
||||
# Create references in div
|
||||
post_refs = article_refs()
|
||||
|
||||
# Create full HTML page
|
||||
article = template%(
|
||||
# First line comment
|
||||
post.needed_tags["title"], domain.conf["title"],
|
||||
# lang=""
|
||||
domain.lang,
|
||||
# nginx metas
|
||||
nginx_mods%"metas",
|
||||
# metas
|
||||
post_metas,
|
||||
# nginx header, navbar
|
||||
nginx_mods%"header",
|
||||
nginx_mods%"navbar",
|
||||
# <time>
|
||||
pub_date,
|
||||
# h1 Main Title link
|
||||
post.datas["www_url"],
|
||||
post.needed_tags["title"], post.needed_tags["authors"], local_date,
|
||||
post.needed_tags["title"],
|
||||
# article references
|
||||
post_refs,
|
||||
# Article contents
|
||||
wip.html_article,
|
||||
# nginx sidebar
|
||||
nginx_mods%"sidebar",
|
||||
# nginx footer
|
||||
nginx_mods%"footer",
|
||||
)
|
||||
|
||||
|
||||
#======================================#
|
||||
# Create all '<meta...' and '<link...' #
|
||||
#--------------------------------------#
|
||||
def article_metas():
|
||||
post_metas = \
|
||||
template_metas%(
|
||||
# From domain
|
||||
domain.web["www"],
|
||||
domain.web["lang"],
|
||||
domain.conf["mail"],
|
||||
domain.web["license"],
|
||||
# From article
|
||||
post.needed_tags["title"],
|
||||
post.needed_tags["authors"],
|
||||
post.needed_tags["about"],
|
||||
post.needed_tags["tags"],
|
||||
# Canonical, template
|
||||
post.datas["www_url"],
|
||||
post.datas["rpa"], domain.cf.get("TEMPLATE_FILENAMES", "styles"),
|
||||
os.path.splitext(
|
||||
domain.cf.get("TEMPLATE_FILENAMES", "favicon")
|
||||
)[1].rsplit(".")[1],
|
||||
post.datas["rpa"], domain.cf.get("TEMPLATE_FILENAMES", "favicon"),
|
||||
post.datas["rpa"], domain.cf.get("TEMPLATE_FILENAMES", "rss"),
|
||||
domain.conf["title"],
|
||||
# Open Graph
|
||||
domain.conf["title"],
|
||||
post.needed_tags["title"],
|
||||
post.datas["www_url"],
|
||||
post.needed_tags["about"],
|
||||
post.needed_tags["logo"],
|
||||
# Date, <title>
|
||||
pub_date,
|
||||
post.needed_tags["title"],
|
||||
post.needed_tags["authors"],
|
||||
domain.cf.get("WEBSITE", "separator"),
|
||||
domain.conf["title"]
|
||||
)
|
||||
|
||||
return post_metas
|
||||
|
||||
|
||||
#========================================#
|
||||
# Create div inclding article references #
|
||||
# In template, is put under main title #
|
||||
#----------------------------------------#
|
||||
def article_refs():
|
||||
link_post_code = ""
|
||||
if domain.conf["post_code"]:
|
||||
link_post_code = \
|
||||
' [<a id="post_code" class="%s" href="./%s" title="%s%s %s">%s</a>]'%(
|
||||
domain.web["css"], post.datas["src_file"],
|
||||
langs.site.source_code, langs.logs.pp, post.needed_tags["title"],
|
||||
langs.site.source_code
|
||||
)
|
||||
|
||||
post_refs = template_refs%(
|
||||
post.needed_tags["authors"], local_date, link_post_code
|
||||
)
|
||||
|
||||
return post_refs
|
||||
|
||||
|
||||
#===============#
|
||||
# MAIN settings #==============================================================
|
||||
#---------------#
|
||||
nginx_mods = '<!--# include virtual="/template/%s.html"-->'
|
||||
|
||||
template = """<!-- %s - %s (page generated by Tyto - Littérateur) -->
|
||||
<!DocType html>
|
||||
<html lang="%s">
|
||||
<head>
|
||||
%s
|
||||
%s
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="site_container">
|
||||
|
||||
%s
|
||||
%s
|
||||
|
||||
<main id="article_sidebar"> <!-- Contains <article> and <aside> -->
|
||||
|
||||
<article id="article">
|
||||
<time datetime="%s">
|
||||
<header id="article_header">
|
||||
<h1 id="article_title">
|
||||
<a id="article_title_link" href="%s" title="%s -- %s, %s">%s</a>
|
||||
</h1>
|
||||
%s
|
||||
</header>
|
||||
%s
|
||||
</time>
|
||||
</article>
|
||||
|
||||
%s
|
||||
|
||||
</main>
|
||||
|
||||
%s
|
||||
|
||||
</div> <!-- #site_container -->
|
||||
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
template_metas = """<!-- Metas/Links from domain and article -->
|
||||
<meta name="generator" content="Tyto - Littérateur">
|
||||
|
||||
<!-- metas generated from domain -->
|
||||
<meta name="url" content="%s">
|
||||
<meta name="language" content="%s">
|
||||
<meta name="reply-to" content="%s">
|
||||
<meta name="copyright" content="%s">
|
||||
|
||||
<!-- metas generated from article -->
|
||||
<meta name="title" content="%s">
|
||||
<meta name="author" content="%s">
|
||||
<meta name="description" content="%s">
|
||||
<meta name="keywords" content="%s">
|
||||
|
||||
<!-- metas links to template files -->
|
||||
<link rel="canonical" href="%s">
|
||||
<link rel="stylesheet" href="%stemplate/%s">
|
||||
<link rel="shortcut icon" type="image/%s" href="%stemplate/%s">
|
||||
<link rel="alternate" type="application/rss+xml" href="%s%s" title="RSS 2.0 %s">
|
||||
|
||||
<!-- Open Graph data -->
|
||||
<meta property="og:site_name" content="%s">
|
||||
<meta property="og:title" content="%s">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:url" content="%s">
|
||||
<meta property="og:description" content="%s">
|
||||
<meta property="og:image" content="%s">
|
||||
|
||||
<!-- Publication date and title -->
|
||||
<meta itemprop="datePublished" content="%s" id="date">
|
||||
<title>%s (%s) %s %s</title>"""
|
||||
|
||||
# Article referencies (author, date, source code)
|
||||
template_refs = """<div id="article_refs">
|
||||
%s, %s%s
|
||||
</div>"""
|
|
@ -14,581 +14,266 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: About post (from target) database, uri...
|
||||
# File: /var/lib/tyto/program/new.py
|
||||
# Description: Manage datas and DB from/for article
|
||||
# File: /var/lib/tyto/program/post.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import os, sys, configparser
|
||||
import args, domain, debug, tools, tyto, check
|
||||
import os, configparser
|
||||
import args, domain, debug, tools
|
||||
|
||||
|
||||
error = 0
|
||||
write = False # When updating database in cf_set(), cf_write()
|
||||
#=============================================================#
|
||||
# Set full article file URI from current directory and target #
|
||||
#-------------------------------------------------------------#
|
||||
def set_uri(target):
|
||||
global uri, uid, db, db_uri
|
||||
|
||||
if target == "sitemap.tyto" or args.commands["targets"]["all"]:
|
||||
domain.user_dir = domain.wrk_dirs["articles"]
|
||||
|
||||
uri = domain.user_dir + target
|
||||
uid = tools.get_HID(uri, False)
|
||||
|
||||
# DB exists ?
|
||||
db_uri = domain.wrk_dirs["db"] + uid + ".ini"
|
||||
db = bool(os.path.exists(db_uri))
|
||||
|
||||
|
||||
#============================================#
|
||||
# Check if current directory is in articles/ #
|
||||
# Check if article from target exists #
|
||||
# Set post configuration file database #
|
||||
# load database #
|
||||
#--------------------------------------------#
|
||||
def is_article(target):
|
||||
global error
|
||||
|
||||
debug.out(211, '"%s"'%target, "", False, 0, False)
|
||||
|
||||
# User MUST be in articles/
|
||||
domain.user_dir.startswith(domain.wrk_articles) or \
|
||||
debug.out(2, "-> articles/", domain.wrk_articles, True, 2, True)
|
||||
|
||||
# Target URI most be from legacy directory or not begins with
|
||||
if target.startswith(tyto.notarget):
|
||||
error = debug.out(20, "./, ../", target, True, 2, False)
|
||||
return False
|
||||
|
||||
# Article exists
|
||||
global uri
|
||||
if args.targets: cur_dir = domain.wrk_articles
|
||||
else: cur_dir = domain.user_dir
|
||||
uri = os.path.join(cur_dir, target)
|
||||
if not os.path.exists(uri):
|
||||
error = debug.out(5, "False", uri, True, 2, False)
|
||||
return False
|
||||
|
||||
# Article is a Tyto format and not empty (exit on errors)
|
||||
if not is_tyto_format():
|
||||
return False
|
||||
|
||||
global uri_id, wrk_id, cf_uri, wrk_target, web_target
|
||||
# Set post ID from...
|
||||
uri_id = tools.get_filesum(uri, False) # ...URI
|
||||
wrk_id = tools.get_filesum(uri, True) # ...CONTENTS
|
||||
|
||||
# Set post configuration file database
|
||||
cf_uri = os.path.join(domain.wrk_db, uri_id + ".ini")
|
||||
|
||||
# Set target from articles/
|
||||
wrk_target = uri.rsplit(domain.wrk_articles)[1]
|
||||
|
||||
# Set web target, replace last .tyto with .html
|
||||
web_target = wrk_target[:-4] + "html"
|
||||
|
||||
# Load Database, get and compare values
|
||||
cf_load()
|
||||
cf_datas()
|
||||
compare_datas()
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#=========================================#
|
||||
# Article is in Tyto format and not empty #
|
||||
# Return True or False #
|
||||
#-----------------------------------------#
|
||||
def is_tyto_format():
|
||||
global head_contents, text_contents, contents
|
||||
global head_lines, text_lines, lines
|
||||
|
||||
head_contents = text_contents = ""
|
||||
separator = False
|
||||
|
||||
with open(uri, "r") as contents:
|
||||
contents = contents.read()
|
||||
for line in contents.rsplit("\n"):
|
||||
if not line:
|
||||
line = " "
|
||||
|
||||
if line.startswith(sep):
|
||||
separator = True
|
||||
continue
|
||||
|
||||
if separator:
|
||||
if not text_contents: text_contents = line
|
||||
else: text_contents = "%s\n%s"%(text_contents, line)
|
||||
else:
|
||||
if not head_contents: head_contents = line
|
||||
else: head_contents = "%s\n%s"%(head_contents, line)
|
||||
|
||||
|
||||
if not separator:
|
||||
error = debug.out(21, sep, uri, True, 2, False)
|
||||
return False
|
||||
|
||||
if not head_contents:
|
||||
error = debug.out(22, "?", uri, True, 2, False)
|
||||
return False
|
||||
|
||||
if not text_contents:
|
||||
error = debug.out(23, "?", uri, True, 2, False)
|
||||
return False
|
||||
|
||||
head_lines = len(head_contents.splitlines()) + 1 # Count with sep line
|
||||
text_lines = len(text_contents.splitlines())
|
||||
lines = head_lines + text_lines
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#=======================================#
|
||||
# Load post database #
|
||||
# return True, or False if unused (yet) #
|
||||
#---------------------------------------#
|
||||
def cf_load():
|
||||
global cf, not_chk
|
||||
cf = not_chk = False
|
||||
|
||||
|
||||
if not os.path.exists(cf_uri):
|
||||
not_chk = True
|
||||
tools.create_file(cf_uri, ini_template)
|
||||
|
||||
cf = configparser.ConfigParser()
|
||||
cf.read(cf_uri)
|
||||
debug.out(200, uri_id, cf_uri, False, 0, False)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#======================================#
|
||||
# Load another post configuration file #
|
||||
# Used by modules: navbar, sidebar #
|
||||
#--------------------------------------#
|
||||
def tmp_load(module, wrk_post, wrk_post_uri):
|
||||
global error
|
||||
|
||||
db_uri = os.path.join(
|
||||
domain.wrk_db,
|
||||
tools.get_filesum(wrk_post_uri, False) + ".ini"
|
||||
)
|
||||
|
||||
if not os.path.exists(db_uri):
|
||||
error = \
|
||||
debug.out(11, '%s. "%s"'%(module, wrk_post), db_uri, True, 2, False)
|
||||
return False
|
||||
|
||||
global tmp_cf
|
||||
tmp_cf = ""
|
||||
tmp_cf = configparser.ConfigParser()
|
||||
tmp_cf.read(db_uri)
|
||||
debug.out(200, '%s. "%s"'%(module, wrk_post), db_uri, False, 0, False)
|
||||
|
||||
if tmp_cf.getboolean("CHECK", "errors"):
|
||||
error = \
|
||||
debug.out(10, "check: %s"%langs.logs.error, db_uri, True, 2, False)
|
||||
return False
|
||||
|
||||
global tmp_title, tmp_about, tmp_logo
|
||||
try:
|
||||
tmp_title = tmp_cf.get("HEADERS", "title")
|
||||
except:
|
||||
error = \
|
||||
debug.out(51, "title:", wrk_post_uri, True, 2, False)
|
||||
return False
|
||||
|
||||
try:
|
||||
tmp_about = tmp_cf.get("HEADERS", "about")
|
||||
except:
|
||||
error = \
|
||||
debug.out(51, "about:", wrk_post_uri, True, 2, False)
|
||||
return False
|
||||
|
||||
try:
|
||||
tmp_logo = tmp_cf.get("HEADERS", "logo")
|
||||
except:
|
||||
error = \
|
||||
debug.out(51, "logo:", wrk_post_uri, True, 2, False)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#=======================================#
|
||||
# Load in tmp mode db post for sitemaps #
|
||||
#---------------------------------------#
|
||||
def tmp_load_db(article_uri):
|
||||
global tmp_db, tmp_db_error
|
||||
tmp_db_error = False
|
||||
|
||||
target = article_uri.rsplit(domain.wrk_articles)[1]
|
||||
db_uri = domain.wrk_db + tools.get_filesum(article_uri, False) + ".ini"
|
||||
if not os.path.exists(db_uri):
|
||||
debug.out(11, 'Sitemap. "%s"'%target, db_uri, False, 0, False)
|
||||
return False
|
||||
|
||||
tmp_db = ""
|
||||
tmp_db = configparser.ConfigParser()
|
||||
tmp_db.read(db_uri)
|
||||
debug.out(200, 'Sitemap. "%s"'%target, db_uri, False, 0, False)
|
||||
|
||||
if not tmp_db_item("HEADERS", "sitemap", True):
|
||||
tmp_db_error = True
|
||||
return True
|
||||
|
||||
# Must be published to be included in sitemap
|
||||
www_uri = tmp_db_item("WWW", "uri", False)
|
||||
if not tmp_db_item("WWW", "hash", False):
|
||||
tmp_db_error = True
|
||||
debug.out(13, 'Sitemap. "%s"'%target, www_uri, False, 1, False)
|
||||
return True
|
||||
|
||||
# Article is not in www server
|
||||
if not os.path.exists(www_uri):
|
||||
debug.out(5, 'Sitemap. "www/"', www_uri, False, 1, False)
|
||||
tmp_db_error = True
|
||||
|
||||
return True
|
||||
|
||||
#===============================================#
|
||||
# Get DB value (for sitemap, with tmp_load_db() #
|
||||
#-----------------------------------------------#
|
||||
def tmp_db_item(section, key, boolean):
|
||||
if boolean:
|
||||
try: return tmp_db.getboolean(section, key)
|
||||
except: return False
|
||||
|
||||
try: return tmp_db.get(section, key)
|
||||
except: return ""
|
||||
|
||||
#=====================================#
|
||||
# Exit if article file does not exist #
|
||||
#-------------------------------------#
|
||||
def exists(target):
|
||||
found = bool(os.path.exists(uri))
|
||||
found or debug.out(11, "!?", uri, True, 2, True)
|
||||
|
||||
|
||||
#================================#
|
||||
# Return value from section, key #
|
||||
# Create datas from article file #
|
||||
#--------------------------------#
|
||||
def cf_get(section, key, boolean):
|
||||
if boolean:
|
||||
try: return cf.getboolean(section, key)
|
||||
except: return False
|
||||
def set_datas():
|
||||
global datas
|
||||
|
||||
try: return cf.get(section, key)
|
||||
except: return ""
|
||||
src_target = uri.rsplit(domain.wrk_dirs["articles"])[1]
|
||||
srv_target = src_target[:-4] + "html"
|
||||
src_file = os.path.basename(uri)
|
||||
dir_target = src_target.replace(src_file, "")
|
||||
|
||||
|
||||
#=============================================#
|
||||
# Get and prepare new vars from post database #
|
||||
#---------------------------------------------#
|
||||
def cf_datas():
|
||||
# [CHECK]
|
||||
# -------
|
||||
global chk_hash, chk_date, chk_static, chk_errors
|
||||
chk_hash = cf_get("CHECK", "hash", False)
|
||||
chk_date = cf_get("CHECK", "date", False)
|
||||
chk_static = cf_get("CHECK", "static", True)
|
||||
chk_errors = cf_get("CHECK", "errors", True)
|
||||
|
||||
# [WIP]
|
||||
# -----
|
||||
global wip_hash, wip_date, wip_uri, wip_static
|
||||
wip_hash = cf_get("WIP", "hash", False)
|
||||
wip_date = cf_get("WIP", "date", False)
|
||||
wip_uri = cf_get("WIP", "uri", False)
|
||||
wip_static = cf_get("WIP", "static", True)
|
||||
|
||||
# [WIP]
|
||||
# -----
|
||||
global www_hash, www_date, www_uri, www_static
|
||||
www_hash = cf_get("WWW", "hash", False)
|
||||
www_date = cf_get("WWW", "date", False)
|
||||
www_uri = cf_get("WWW", "uri", False)
|
||||
www_static = cf_get("WWW", "static", True)
|
||||
|
||||
global set_title, set_about, set_date, set_tags, set_author
|
||||
set_title = cf_get("HEADERS", "title", False)
|
||||
set_about = cf_get("HEADERS", "about", False)
|
||||
set_date = cf_get("HEADERS", "date", False)
|
||||
set_tags = cf_get("HEADERS", "tags", False)
|
||||
set_author = cf_get("HEADERS", "authors", False)
|
||||
|
||||
global sub_uri, www_logo
|
||||
sub_uri = cf_get("FILE", "sub_uri", False)
|
||||
www_logo = cf_get("HEADERS", "logo", False)
|
||||
|
||||
|
||||
#===============================#
|
||||
# Do some datas comparisons #
|
||||
# after post cf_datas() setup #
|
||||
# Used to do processes (mainly) #
|
||||
#-------------------------------#
|
||||
def compare_datas():
|
||||
global do_chk, do_wip, has_changed
|
||||
|
||||
# check can be done ?
|
||||
has_changed = False
|
||||
if wrk_id != chk_hash:
|
||||
has_changed = True
|
||||
|
||||
do_chk = False
|
||||
if chk_errors or \
|
||||
chk_static != domain.static or \
|
||||
args.force == True:
|
||||
do_chk = True
|
||||
else:
|
||||
do_chk = tools.compare_values(wrk_id, chk_hash)
|
||||
|
||||
|
||||
# wip can be done
|
||||
do_wip = False
|
||||
if wip_static != domain.static or \
|
||||
args.force:
|
||||
do_wip = True
|
||||
else:
|
||||
do_wip = tools.compare_values(chk_hash, wip_hash)
|
||||
|
||||
|
||||
#===============================#
|
||||
# Set a value in post database #
|
||||
# only if changed value #
|
||||
# check for [section] in file #
|
||||
# or create it with key and val #
|
||||
# config file must be loaded #
|
||||
#-------------------------------#
|
||||
def cf_set(section, key, value):
|
||||
global write
|
||||
|
||||
try: cf
|
||||
except: cf_load()
|
||||
|
||||
if not cf.has_section(section):
|
||||
cf.add_section(section)
|
||||
|
||||
try: curval = cf.get(section, key)
|
||||
except: curval = ""
|
||||
|
||||
if not curval or curval != value:
|
||||
cf.set(section, key, value)
|
||||
write = True
|
||||
|
||||
|
||||
#=====================#
|
||||
# Write post database #
|
||||
# if new value is set #
|
||||
#---------------------#
|
||||
def cf_write():
|
||||
global write
|
||||
|
||||
if write:
|
||||
with open(cf_uri, "w") as f:
|
||||
cf.write(f)
|
||||
debug.out(207, uri_id, cf_uri, False, 0, False)
|
||||
|
||||
write = False
|
||||
|
||||
|
||||
#====================================================#
|
||||
# Search and return .tyto file in domain root folder #
|
||||
#----------------------------------------------------#
|
||||
def find_tyto_article():
|
||||
nothere = (domain.wrk_files, domain.wrk_images)
|
||||
os.chdir(domain.wrk_articles)
|
||||
|
||||
for root, dirs, files in os.walk(domain.wrk_articles):
|
||||
if root.startswith(nothere):
|
||||
continue
|
||||
|
||||
for f in files:
|
||||
if f.endswith(".tyto"):
|
||||
f_uri = os.path.join(root, f)
|
||||
target = f_uri.rsplit(domain.wrk_articles)[1]
|
||||
|
||||
args.action == "check" and check.is_article(target)
|
||||
|
||||
|
||||
|
||||
|
||||
#======#
|
||||
# MAIN #=======================================================================
|
||||
#======#
|
||||
# Statistics
|
||||
# ==========
|
||||
stats_bcodes_lines = 0
|
||||
|
||||
stats_bcodes = 0
|
||||
stats_quotes = 0
|
||||
stats_parags = 0
|
||||
stats_lists = 0
|
||||
stats_divs = 0
|
||||
|
||||
stats_links = 0
|
||||
stats_images = 0
|
||||
stats_files = 0
|
||||
stats_raws = 0
|
||||
stats_codes = 0
|
||||
stats_abbrs = 0
|
||||
|
||||
stats_text_links = 0
|
||||
stats_text_files = 0
|
||||
stats_text_images = 0
|
||||
stats_text_abbrs = 0
|
||||
stats_text_codes = 0
|
||||
stats_text_raws = 0
|
||||
|
||||
|
||||
# head_contents
|
||||
#==============
|
||||
# Optional Tags
|
||||
nositemap = "! NoSitemap" # Article will not be included in sitemap
|
||||
|
||||
# One Line needed
|
||||
sep = "-----" # Splitter between header and article texts
|
||||
|
||||
# Will replace "False" with data value (check process)
|
||||
title = ("title:", False)
|
||||
about = ("about:", False)
|
||||
date = ("date:", False)
|
||||
tags = ("tags:", False)
|
||||
author = ("author:", False)
|
||||
logo = ("logo:", False) # optional
|
||||
|
||||
# Multiple lines (3) markers
|
||||
ml_tags = (
|
||||
"link:",
|
||||
"image:",
|
||||
"file:",
|
||||
"raw:",
|
||||
"code:",
|
||||
"abbr:"
|
||||
)
|
||||
ml_tags_marks = {
|
||||
ml_tags[0] : "__",
|
||||
ml_tags[2] : "--",
|
||||
ml_tags[1] : "_image:",
|
||||
ml_tags[5] : "::",
|
||||
ml_tags[3] : "_raw:",
|
||||
ml_tags[4] : "_code:"
|
||||
}
|
||||
ml_tags_stats = {
|
||||
ml_tags[0] : stats_links,
|
||||
ml_tags[2] : stats_files,
|
||||
ml_tags[1] : stats_images,
|
||||
ml_tags[5] : stats_abbrs,
|
||||
ml_tags[3] : stats_raws,
|
||||
ml_tags[4] : stats_codes,
|
||||
# Settings
|
||||
datas = \
|
||||
{
|
||||
"cid" : tools.get_HID(uri, True),
|
||||
"src_target" : src_target,
|
||||
"srv_target" : srv_target,
|
||||
"src_file" : src_file,
|
||||
"src_rpa" : "/" + src_target,
|
||||
"web_rpa" : "/" + srv_target,
|
||||
"www_url" : domain.web["www"] + src_target[:-4] + "html",
|
||||
"dir_target" : dir_target,
|
||||
"rpa" : get_rpa(),
|
||||
# URIS format, "files" : {f_nbr : (full_uri, web_uri)}
|
||||
"files" : {},
|
||||
}
|
||||
|
||||
# Markers with uri in value2
|
||||
value2s_uri = (ml_tags[1], ml_tags[2], ml_tags[3], ml_tags[4])
|
||||
value2s_ext_uris = ("http", "ftp")
|
||||
|
||||
# text_contents
|
||||
# =============
|
||||
# Paired markers
|
||||
ptags = (
|
||||
("{{", "}}", "bcodes"),
|
||||
('["', '"]', "quotes"),
|
||||
("((", "))", "parags", '<p class="%s">', "</p>"),
|
||||
("<:", ":>", "lists", "=", "+"),
|
||||
("[[", "]]", "divs", '<div class="%s">', "</div>")
|
||||
)
|
||||
#=====================================================#
|
||||
# Return relative path for files from root, like "./" #
|
||||
#-----------------------------------------------------#
|
||||
def get_rpa():
|
||||
src_link = "/" + uri.rsplit(domain.wrk_dirs["articles"])[1]
|
||||
rpa = src_link.count("/")
|
||||
|
||||
ptags_stats = {
|
||||
ptags[0][2] : stats_bcodes,
|
||||
ptags[1][2] : stats_quotes,
|
||||
ptags[2][2] : stats_parags,
|
||||
ptags[3][2] : stats_lists,
|
||||
ptags[4][2] : stats_divs,
|
||||
}
|
||||
if rpa > 1: rpa = rpa -1 ; rpa = rpa * "../"
|
||||
else: rpa = "./"
|
||||
|
||||
# Tyto Titles #1 = <h2>
|
||||
tyto_titles = ("#1", "#2", "#3", "#4", "#5")
|
||||
html_titles = {
|
||||
"#1" : '<h2 class="%s">%s</h2>',
|
||||
"#2" : '<h3 class="%s">%s</h3>',
|
||||
"#3" : '<h4 class="%s">%s</h4>',
|
||||
"#4" : '<h5 class="%s">%s</h5>',
|
||||
"#5" : '<h6 class="%s">%s</h6>',
|
||||
}
|
||||
|
||||
html_brline = ("|", '<br class="%s">')
|
||||
html_hrline = ("--", '<hr class="%s">')
|
||||
text_comments = (";;", "<!--")
|
||||
anchor_target = ("->", '<a id="%s" class="anchor_target"></a>')
|
||||
anchor_link = (">_", "_<")
|
||||
anchor_set = (">_%s_<", '<a class="%s anchor_link" href="#%s">%s</a>')
|
||||
quote_metas = ("cite:", "date:", "book:", "lang:", "link:")
|
||||
|
||||
# Words tags
|
||||
words_tags = (
|
||||
("*_", "_*", "strongs", '<strong class="%s">', '</strong>'),
|
||||
("+_", "_+", "bolds", '<b class="%s">', '</b>'),
|
||||
("[_", "_]", "cites", '<q class="%s">', '</q>'),
|
||||
(":_", "_:", "refs", '<cite class="%s">', '</cite>'),
|
||||
("~_", "_~", "dels", '<del class="%s">', '</del>'),
|
||||
("._", "_.", "underlines", '<u class="%s">', '</u>'),
|
||||
("/_", "_/", "emphasis", '<em class="%s">', '</em>'),
|
||||
(";_", "_;", "italics", '<i class="%s">', '</i>'),
|
||||
)
|
||||
|
||||
words_ml_tag = "&"
|
||||
|
||||
# Specifics convertion
|
||||
words_markers = \
|
||||
(
|
||||
("{_{_", "_}_}", '<code class="%s icode">{_', '_}</code>', "IC21", "IC22"),
|
||||
("{_", "_}", '<code class="%s icode">', '</code>', "IC11", "IC12"),
|
||||
)
|
||||
return rpa
|
||||
|
||||
|
||||
#=============================#
|
||||
# articles configuration file #
|
||||
# Read article DB (if exists) #
|
||||
#-----------------------------#
|
||||
ini_template = """[DOMAIN]
|
||||
def cf_load():
|
||||
global cf
|
||||
|
||||
[FILE]
|
||||
cf = configparser.ConfigParser()
|
||||
cf.read(db_uri)
|
||||
|
||||
[HEADERS]
|
||||
|
||||
[TEXTS]
|
||||
#==============================================#
|
||||
# Create sections, keys, values for article DB #
|
||||
# Called after wip, published #
|
||||
#----------------------------------------------#
|
||||
def cf_set(section, key, value):
|
||||
global cf
|
||||
|
||||
[CHECK]
|
||||
# Add section if not exists
|
||||
try: cf.add_section(section)
|
||||
except: pass
|
||||
|
||||
[WIP]
|
||||
cf.set(section, key, value)
|
||||
|
||||
[WWW]
|
||||
|
||||
[COMMENTS]
|
||||
#
|
||||
#
|
||||
#
|
||||
def cf_read():
|
||||
global hash_www, date_www
|
||||
|
||||
[TITLES]
|
||||
try: hash_www = cf.get("HASHES", "www")
|
||||
except: hash_www = ""
|
||||
try: date_www = cf.get("DATES", "www")
|
||||
except: date_www = ""
|
||||
|
||||
[ANCHORS]
|
||||
# Remove to create a new DB
|
||||
try: os.remove(db_uri)
|
||||
except: return
|
||||
|
||||
[LINKS]
|
||||
#
|
||||
# Write new Article DB
|
||||
#
|
||||
def cf_write():
|
||||
with open(db_uri, "w") as f:
|
||||
cf.write(f)
|
||||
|
||||
[FILES]
|
||||
|
||||
[IMAGES]
|
||||
#==============================#
|
||||
# Create new article DB file #
|
||||
#------------------------------#
|
||||
def cf_create():
|
||||
# Create new DB
|
||||
tools.create_file(db_uri, "")
|
||||
cf_load()
|
||||
|
||||
[BCODES]
|
||||
cf_set("URIS", "wrk", uri)
|
||||
cf_set("URIS", "wip", domain.wip + datas["srv_target"])
|
||||
cf_set("URIS", "www", domain.www + datas["srv_target"])
|
||||
cf_set("URIS", "web", datas["web_rpa"].replace("index.html", ""))
|
||||
cf_set("HASHES", "www", hash_www)
|
||||
cf_set("DATES", "www", date_www)
|
||||
for tag in needed_tags:
|
||||
cf_set("ARTICLE", tag, needed_tags[tag])
|
||||
|
||||
[QUOTES]
|
||||
cf_set("ARTICLE", "local_date", tools.local_date(needed_tags["date"]))
|
||||
cf_set("ARTICLE", "www_url", datas["www_url"])
|
||||
cf_set("MODULES", "nomap", str(options_marks["! NOMAP"]))
|
||||
cf_set("MODULES", "norss", str(options_marks["! NORSS"]))
|
||||
cf_set("MODULES", "toc", str(options_marks["! TOC"]))
|
||||
|
||||
[LISTS]
|
||||
cf_write()
|
||||
|
||||
[RAWS]
|
||||
|
||||
[CODES]
|
||||
#
|
||||
#
|
||||
#
|
||||
def set_default_vars():
|
||||
global anchors, block_tags, icodes, options_marks
|
||||
global needed_tags, option_tags, titles
|
||||
|
||||
[ABBRS]
|
||||
# form NBR : (source, html)
|
||||
anchors = {}
|
||||
|
||||
[ICODES]
|
||||
# Put in blocks source lines
|
||||
block_tags = \
|
||||
{
|
||||
"bcodes" : {
|
||||
"marks" : ("{{", "}}"),
|
||||
"sources" : {}, # {} : {NBR : ("SOURCE", "B64")}
|
||||
},
|
||||
"bquotes" : {
|
||||
"marks" : ('("', ')"'),
|
||||
"sources" : {}, # {} : {NBR : ("SOURCE", "B64")}
|
||||
},
|
||||
"lists" : {
|
||||
"marks" : ("(=", ")=", "=", "+"),
|
||||
"sources" : {}, # {} : {NBR : ("SOURCE", "B64")}
|
||||
},
|
||||
}
|
||||
|
||||
[SOURCE_FILES]
|
||||
# Inline codes
|
||||
icodes = {
|
||||
"sources" : {}, # {} : {NBR : ("SOURCE", "B64")}
|
||||
}
|
||||
|
||||
[STATS_FILE]
|
||||
|
||||
[STATS_HEADERS]
|
||||
# Marks to cinfigure article
|
||||
options_marks = {
|
||||
"! NOMAP" : False,
|
||||
"! NORSS" : False,
|
||||
"! TOC" : False,
|
||||
}
|
||||
|
||||
# Tags that must be set in header
|
||||
needed_tags = {
|
||||
"title" : "",
|
||||
"about" : "",
|
||||
"date" : "",
|
||||
"tags" : "",
|
||||
"authors" : "",
|
||||
"logo" : "",
|
||||
}
|
||||
|
||||
# Tags on 3 lines and optional
|
||||
# Format for each to set "..." : {NBR : ("F1", "F2", "F3", "HTML")}
|
||||
option_tags = {
|
||||
"link" : {},
|
||||
"file" : {},
|
||||
"image" : {},
|
||||
"code" : {},
|
||||
"raw" : {},
|
||||
"abbr" : {},
|
||||
}
|
||||
|
||||
titles = ()
|
||||
|
||||
|
||||
#===============#
|
||||
# MAIN settings #==============================================================
|
||||
#---------------#
|
||||
# --------------------------- #
|
||||
# markers and tags in article #
|
||||
# --------------------------- #
|
||||
# Delimitor for header and writer contents
|
||||
separator = "-----"
|
||||
|
||||
# 2nd line tag is not an URI file to check
|
||||
nofile_tags = ("link", "abbr")
|
||||
|
||||
|
||||
# Markers used in article writer for optional tags
|
||||
# HTML
|
||||
marker_tags = "::%s"
|
||||
|
||||
html_comments = ";;"
|
||||
|
||||
indep_tags = {
|
||||
"hrs" : "--",
|
||||
"brs" : "|",
|
||||
"anchors" : "->",
|
||||
}
|
||||
|
||||
# Starting line and paired tags
|
||||
sl_ptags = {
|
||||
"divs" : ("[[", "]]"),
|
||||
"paragraphs" : ("((", "))"),
|
||||
}
|
||||
|
||||
words_tags = {
|
||||
"strongs" : ("*`", "`*"),
|
||||
"bolds" : ("+`", "`+"),
|
||||
"underlines" : ("_`", "`_"),
|
||||
"emphasis" : ("/`", "`/"),
|
||||
"italics" : (";`", "`;"),
|
||||
"quotes" : ("[`", "`]"),
|
||||
"cites" : (":`", "`:"),
|
||||
"dels" : ("~`", "`~"),
|
||||
"customs" : ("|`", "`|"),
|
||||
"icodes" : ("{`", "`}"),
|
||||
"anc_links" : (">`", "`<"),
|
||||
}
|
||||
|
||||
title_marks = ("#1", "#2", "#3", "#4", "#5") # h2 to h6
|
||||
|
||||
[STATS_TEXTS]
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Manage publishing
|
||||
# (mainly copies from wip server)
|
||||
# Launch feed and sitemap creation
|
||||
# File: /var/lib/tyto/program/publish.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import domain, args, wip, post, debug, tools, sitemap, feed
|
||||
|
||||
|
||||
#========================================================#
|
||||
# From command "publish", copy wip article to www server #
|
||||
#--------------------------------------------------------#
|
||||
def manage():
|
||||
domain.is_ready()
|
||||
|
||||
global out
|
||||
if args.article:
|
||||
wip.in_dir_articles()
|
||||
|
||||
# Multiple targets ("all"): out is False
|
||||
# (out to exit on error at single target)
|
||||
out = not(args.targets)
|
||||
article()
|
||||
|
||||
# Copy sitemap if activated and exists
|
||||
if domain.conf["sitemaps"]:
|
||||
sitemap.create()
|
||||
args.article == "sitemap.tyto"
|
||||
article()
|
||||
|
||||
feed.create()
|
||||
tools.copy_template_dir("www")
|
||||
|
||||
|
||||
#==============================#
|
||||
# Set DB, check and copy files #
|
||||
#------------------------------#
|
||||
def article():
|
||||
post.set_uri(args.article)
|
||||
post.exists(args.article)
|
||||
db_uri = domain.wrk_dirs["db"] + post.uid + ".ini"
|
||||
if not bool(os.path.exists(db_uri)):
|
||||
debug.out(12, "wip %s"%args.article, post.uid, True, 2, out)
|
||||
|
||||
post.cf_load()
|
||||
if not check_db():
|
||||
debug.out(12, "wip %s"%args.article, post.uri, True, 2, out)
|
||||
|
||||
copy_wip_to_www()
|
||||
post.cf_set("HASHES", "www", DB["hash_wip"])
|
||||
post.cf_set("DATES", "www", pub_date)
|
||||
post.cf_write()
|
||||
debug.out(250, DB["article_title"], DB["uri_www"], True, 0, False)
|
||||
|
||||
|
||||
#===========================
|
||||
# Check needed Datas in DB #
|
||||
# Return True or False #
|
||||
#--------------------------#
|
||||
def check_db():
|
||||
global DB
|
||||
|
||||
try:
|
||||
DB = {
|
||||
"uri_wrk" : post.cf.get("URIS", "wrk"),
|
||||
"uri_wip" : post.cf.get("URIS", "wip"),
|
||||
"uri_www" : post.cf.get("URIS", "www"),
|
||||
"uri_web" : post.cf.get("URIS", "web"),
|
||||
"article_title" : post.cf.get("ARTICLE", "title"),
|
||||
"hash_wip" : post.cf.get("HASHES", "wip"),
|
||||
}
|
||||
except:
|
||||
return False
|
||||
|
||||
for item in DB:
|
||||
if not DB[item]:
|
||||
return False
|
||||
|
||||
if not os.path.exists(DB["uri_wip"]):
|
||||
debug.out(11, "!?", db["uri_wip", True, 2, out])
|
||||
|
||||
# Check if files exists in wip directory
|
||||
try:
|
||||
error = False
|
||||
for key, value in post.cf.items("FILES"):
|
||||
if not os.path.exists(domain.wip + value):
|
||||
debug.out(11, "!?", domain.wip + value, True, 2, False)
|
||||
error = True
|
||||
except:
|
||||
error = False
|
||||
|
||||
if error:
|
||||
return False
|
||||
|
||||
# Ensure Article source code is in wip directory if set in config domain
|
||||
if domain.conf["post_code"]:
|
||||
global wip_post_src
|
||||
|
||||
wip_post_src = \
|
||||
DB["uri_wrk"].replace(domain.wrk_dirs["articles"], domain.wip)
|
||||
if not os.path.exists(wip_post_src):
|
||||
debug.out(11, "!?", wip_post_src, True, 2, out)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#===============================================#
|
||||
# Update article contents with new publish date #
|
||||
# Laucn from copu_wip_to_www, before file copy #
|
||||
#-----------------------------------------------#
|
||||
def update_article():
|
||||
global pub_date
|
||||
|
||||
pub_date = tools.nowdate("int-full")
|
||||
meta_date = '<meta itemprop="datePublished" content="%s" id="date">'%pub_date
|
||||
time_date = '<time datetime="%s">'%pub_date
|
||||
|
||||
with open(DB["uri_wip"], "r") as f:
|
||||
www_article = f.read().rsplit("\n")
|
||||
for ln, line in enumerate(www_article):
|
||||
if line.lstrip().startswith('<meta itemprop="datePublished"'):
|
||||
www_article[ln] = meta_date
|
||||
elif line.startswith('<time datetime="'):
|
||||
www_article[ln] = time_date
|
||||
# <time datetime is the last item to change
|
||||
break
|
||||
|
||||
with open(DB["uri_www"], 'w') as f:
|
||||
for line in www_article:
|
||||
# write each item on a new line
|
||||
f.write("%s\n"%line)
|
||||
|
||||
|
||||
#=============================================#
|
||||
# Copy all needed article files to www server #
|
||||
#---------------------------------------------#
|
||||
def copy_wip_to_www():
|
||||
# Copy needed files used by article
|
||||
try:
|
||||
for key, value in post.cf.items("FILES"):
|
||||
# Extract directories and create them
|
||||
tools.create_dirs(domain.www + value.rsplit(os.path.basename(value))[0])
|
||||
tools.copy_files(domain.wip + value, domain.www + value)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Create article contents file to server
|
||||
tools.create_dirs(DB["uri_www"].rsplit(os.path.basename(DB["uri_www"]))[0])
|
||||
update_article()
|
||||
|
||||
# Copy Article source code in wip directory, if set in domain configuration
|
||||
if domain.conf["post_code"]:
|
||||
www_post_src = \
|
||||
DB["uri_wrk"].replace(domain.wrk_dirs["articles"], domain.www)
|
||||
tools.copy_files(wip_post_src, www_post_src)
|
|
@ -0,0 +1,136 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
#
|
||||
# Description: Create sitemap
|
||||
# File: /var/lib/tyto/program/sitemap.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
import os, configparser, glob
|
||||
import args, domain, tools, langs, wip
|
||||
|
||||
|
||||
#======================================#
|
||||
# Loop from all articles DB #
|
||||
# Check if article is ready to include #
|
||||
#--------------------------------------#
|
||||
def create():
|
||||
if not domain.conf["sitemaps"]:
|
||||
return
|
||||
|
||||
os.chdir(domain.wrk_dirs["articles"])
|
||||
db_dir = domain.wrk_dirs["db"]
|
||||
|
||||
# Scan DB directory and sort files by last updated
|
||||
items = filter(os.path.isfile, glob.glob(db_dir + '*.ini'))
|
||||
items = sorted(items, key = os.path.getmtime, reverse=True)
|
||||
|
||||
list_items = ""
|
||||
nbr = 0
|
||||
for db_uri in items:
|
||||
if not check_db(db_uri):
|
||||
continue
|
||||
|
||||
nbr += 1
|
||||
ol_item = link%(
|
||||
domain.web["css"],
|
||||
DB["uri_web"],
|
||||
# title=""
|
||||
DB["about"], DB["authors"], DB["date"],
|
||||
# Content link
|
||||
DB["title"]
|
||||
)
|
||||
|
||||
if not list_items: list_items = "%s"%ol_item
|
||||
else: list_items = "%s\n%s"%(list_items, ol_item)
|
||||
|
||||
if not list_items:
|
||||
list_items = " = %s"%langs.site.sitemap_empty
|
||||
|
||||
sitemap_tyto = \
|
||||
sitemap_post%(
|
||||
langs.site.sitemap,
|
||||
langs.site.sitemap_gen,
|
||||
langs.site.sitemap,
|
||||
tools.nowdate("int-short"),
|
||||
langs.site.posts_list, nbr,
|
||||
list_items
|
||||
)
|
||||
|
||||
tools.create_file(domain.wrk_dirs["articles"] + "sitemap.tyto", sitemap_tyto)
|
||||
args.article = "sitemap.tyto"
|
||||
wip.article()
|
||||
|
||||
|
||||
#===============================#
|
||||
# Check/Set article DB #
|
||||
# Check if article can be added #
|
||||
#-------------------------------#
|
||||
def check_db(db_uri):
|
||||
global DB
|
||||
|
||||
cf = configparser.ConfigParser()
|
||||
cf.read(db_uri)
|
||||
|
||||
try:
|
||||
DB = {
|
||||
"uri_web" : cf.get("URIS", "web"),
|
||||
"title" : cf.get("ARTICLE", "title"),
|
||||
"about" : cf.get("ARTICLE", "about"),
|
||||
"date" : cf.get("ARTICLE", "local_date"),
|
||||
"authors" : cf.get("ARTICLE", "authors"),
|
||||
"hash_www" : cf.get("HASHES", "www"),
|
||||
"nomap" : cf.getboolean("MODULES", "nomap"),
|
||||
}
|
||||
except:
|
||||
return False
|
||||
|
||||
if not DB["hash_www"] or DB["nomap"]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
#======#
|
||||
# Main #=======================================================================
|
||||
#======#
|
||||
# Template sitemap.tyto with lists (pages links, posts links)
|
||||
sitemap_post = """# Tyto - Littérateur
|
||||
! NOMAP
|
||||
! NORSS
|
||||
|
||||
title: %s
|
||||
about: %s Tyto - Littérateur
|
||||
tags: %s
|
||||
authors: Tyto
|
||||
date: %s
|
||||
|
||||
-----
|
||||
#1 %s (%s)
|
||||
|
||||
(( sitemap
|
||||
(= sitemap_items
|
||||
%s
|
||||
)=
|
||||
))
|
||||
"""
|
||||
|
||||
# Generic list item with HTML link for sitemap
|
||||
link = ' + <a class="%s sitemap" href="%s" title="%s -- %s, %s">%s</a>'
|
|
@ -14,95 +14,77 @@
|
|||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib > im@echolib.re
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Tools used by Tyto - Littérateur
|
||||
# Description: Some tools
|
||||
# File: /var/lib/tyto/program/tools.py
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
#-------------------------
|
||||
# Funny Stats Project
|
||||
#-------------------------
|
||||
# file lines :
|
||||
# file comments :
|
||||
# file functions:
|
||||
# file program :
|
||||
#--------------------------
|
||||
|
||||
import os, datetime, shutil, glob
|
||||
from hashlib import blake2b
|
||||
import sys, os, configparser, datetime, time, base64, shutil
|
||||
import args, langs, debug, domain, post
|
||||
|
||||
|
||||
#=========================================#
|
||||
# Write to post database, error was found #
|
||||
# Return if error found (multi articles) #
|
||||
# Exit if error found (single article) #
|
||||
#-----------------------------------------#
|
||||
def exit(targets, error):
|
||||
post.cf_set("CHECK", "errors", "True")
|
||||
post.cf_write()
|
||||
|
||||
if targets:
|
||||
return
|
||||
|
||||
sys.exit(error)
|
||||
import args, debug, domain, post, wip
|
||||
|
||||
|
||||
#==============================#
|
||||
# Set and return date and time #
|
||||
# short: True > Y-m-d
|
||||
#------------------------------#
|
||||
def nowdate():
|
||||
now = datetime.datetime.now()
|
||||
return(now.strftime('%Y-%m-%d %H:%M:%S'))
|
||||
|
||||
|
||||
#
|
||||
# convert int date to local date
|
||||
# Return date (only year) for post database
|
||||
#
|
||||
def local_date(date):
|
||||
date = date.rsplit(" ")[0] # if nowdate()
|
||||
|
||||
year = date.rsplit("-")[0]
|
||||
month = date.rsplit("-")[1]
|
||||
day = date.rsplit("-")[2]
|
||||
|
||||
dates = {
|
||||
"fr" : "%s/%s/%s"%(day, month, year),
|
||||
"en" : date,
|
||||
def nowdate(fmt):
|
||||
formats = {
|
||||
"int-full" : "%Y-%m-%d %H:%M:%S",
|
||||
"int-short" : "%Y-%m-%d",
|
||||
"year" : "%Y",
|
||||
"feed" : "%a, %d %b %Y %H:%M:%S",
|
||||
}
|
||||
|
||||
return dates[domain.lang]
|
||||
try: formats[fmt]
|
||||
except: fmt = "int-full"
|
||||
|
||||
now = datetime.datetime.now()
|
||||
return(now.strftime(formats[fmt]))
|
||||
|
||||
|
||||
#========================#
|
||||
#==========================#
|
||||
# Return local date format #
|
||||
#--------------------------#
|
||||
def local_date(date):
|
||||
if domain.lang == "en":
|
||||
return date
|
||||
|
||||
local_dates = {
|
||||
"fr" : "%s/%s/%s",
|
||||
}
|
||||
|
||||
y = date.rsplit("-")[0]
|
||||
m = date.rsplit("-")[1]
|
||||
d = date.rsplit("-")[2]
|
||||
|
||||
return local_dates[domain.lang]%(d,m,y)
|
||||
|
||||
|
||||
#=================================#
|
||||
# Return sum of src file #
|
||||
# src: True = Content #
|
||||
# False = URI #
|
||||
#------------------------#
|
||||
def get_filesum(path, src):
|
||||
file_sum = blake2b(digest_size=4)
|
||||
# file: True = Contents file ID #
|
||||
# False = string ID #
|
||||
#---------------------------------#
|
||||
def get_HID(string, file):
|
||||
HID = blake2b(digest_size=4)
|
||||
|
||||
if src: file_sum.update(open(path, 'rb').read())
|
||||
else: file_sum.update(path.encode())
|
||||
if file: HID.update(open(string, 'rb').read())
|
||||
else: HID.update(string.encode())
|
||||
|
||||
return file_sum.hexdigest()
|
||||
return HID.hexdigest()
|
||||
|
||||
|
||||
#========================================#
|
||||
# Check directory: exit if out and log #
|
||||
# Mainly used to check domain server dir #
|
||||
#----------------------------------------#
|
||||
def dir_exists(dir_path, out):
|
||||
if not bool(os.path.exists(dir_path)):
|
||||
debug.out(6, "False", dir_path, out, 2, out)
|
||||
return False
|
||||
|
||||
return True
|
||||
#================================#
|
||||
# 2 values generic comparison #
|
||||
# return True if values are same #
|
||||
#--------------------------------#
|
||||
def same_values(a, b):
|
||||
return bool(a == b)
|
||||
|
||||
|
||||
#====================#
|
||||
|
@ -112,93 +94,28 @@ def create_dirs(path):
|
|||
if not os.path.exists(path):
|
||||
try:
|
||||
os.makedirs(path, exist_ok=True)
|
||||
debug.out(203, langs.logs.success, path, True, 0, False)
|
||||
debug.out(207, "Ok", path, False, 0, False)
|
||||
except:
|
||||
# Exit if not created
|
||||
debug.out(6, langs.logs.error, path, True, 2, True)
|
||||
debug.out(7, "!?", path, False, 2, True)
|
||||
|
||||
|
||||
#============================#
|
||||
# Create a new file and logs #
|
||||
#----------------------------#
|
||||
def create_file(file_path, contents):
|
||||
up = bool(os.path.exists(file_path))
|
||||
#==============================#
|
||||
# Create a new file and log it #
|
||||
#------------------------------#
|
||||
def create_file(path, contents):
|
||||
up = bool(os.path.exists(path))
|
||||
|
||||
try:
|
||||
with open(file_path, "w") as f:
|
||||
with open(path, "w") as f:
|
||||
f.write(contents)
|
||||
except:
|
||||
# Exit if not created
|
||||
debug.out(7, langs.logs.error, file_path, True, 2, True)
|
||||
debug.out(5, "!?", path, True, 2, True)
|
||||
|
||||
# log "update" or "new"
|
||||
file_name = os.path.basename(file_path)
|
||||
if up: debug.out(207, file_name, file_path, False, 0, False)
|
||||
else: debug.out(206, file_name, file_path, True, 0, False)
|
||||
|
||||
|
||||
#============#
|
||||
# Copy files #
|
||||
#------------#
|
||||
def copy_files(src, dst):
|
||||
# Copy file, check if dst exists
|
||||
up = bool(os.path.exists(dst))
|
||||
try:
|
||||
shutil.copy2(src, dst, follow_symlinks=False)
|
||||
except:
|
||||
debug.out(7, langs.logs.copy, dst, True, 2, False)
|
||||
return
|
||||
|
||||
# log "update" or "new"
|
||||
file_name = os.path.basename(src)
|
||||
if up: debug.out(207, file_name, dst, False, 0, False)
|
||||
else: debug.out(206, file_name, dst, True, 0, False)
|
||||
|
||||
|
||||
#===========================================#
|
||||
# Update ini file, replacing existing value #
|
||||
#-------------------------------------------#
|
||||
def update_ini_file(file_path, section, key, val):
|
||||
# Exit if no file
|
||||
os.path.exists(file_path) or debug.out(5, "False", file_path, True, 2, True)
|
||||
|
||||
# Load ini file
|
||||
config = configparser.ConfigParser()
|
||||
config.read(file_path)
|
||||
|
||||
# New value is same as registred
|
||||
try:
|
||||
if config.get(section, key) == val:
|
||||
return
|
||||
except:
|
||||
config.add_section(section)
|
||||
|
||||
# Update file with new value
|
||||
config.set(section, key, val)
|
||||
with open(file_path, "w") as f:
|
||||
config.write(f)
|
||||
|
||||
|
||||
#====================#
|
||||
# Base64 Convertions #
|
||||
#--------------------#
|
||||
def b64_convert(action, content):
|
||||
if action == 'encode':
|
||||
global b64_content
|
||||
|
||||
b64_base64 = ''
|
||||
content_bytes = content.encode("utf8")
|
||||
base64_bytes = base64.b64encode(content_bytes)
|
||||
b64_content = base64_bytes.decode("utf8")
|
||||
return b64_content
|
||||
|
||||
elif action == 'decode':
|
||||
global src_content
|
||||
|
||||
src_content = ''
|
||||
content_bytes = content.encode("utf8")
|
||||
base64_bytes = base64.b64decode(content_bytes)
|
||||
src_content = base64_bytes.decode("utf8")
|
||||
return src_content
|
||||
file_name = os.path.basename(path)
|
||||
if up: debug.out(206, file_name, path, False, 0, False)
|
||||
else: debug.out(205, file_name, path, False, 0, False)
|
||||
|
||||
|
||||
#================================#
|
||||
|
@ -218,36 +135,104 @@ def convert_html_signs(string):
|
|||
#==========================#
|
||||
# Get CSS value after mark #
|
||||
# Only take the first name #
|
||||
# Exit all process if _... #
|
||||
#--------------------------#
|
||||
def get_css(line, mark, ln):
|
||||
css = line.rsplit(mark)[1].lstrip().rsplit(" ")[0]
|
||||
css = css or domain.css
|
||||
|
||||
# Tyto use _abc as markers
|
||||
if "_" in css:
|
||||
post.error = \
|
||||
debug.out(56, '%s) (CSS) "_" : "%s"'%(ln, css), post.uri, True, 2, False)
|
||||
return "NameError"
|
||||
def get_css(line, mark):
|
||||
css = line.rsplit(mark)[1].lstrip().rsplit(" ")[0] or domain.web["css"]
|
||||
|
||||
return css
|
||||
|
||||
|
||||
#==========================================#
|
||||
# Compare 2 values #
|
||||
# used for hashes and more... #
|
||||
# return True if not same values #
|
||||
# ex: do_chk = True #
|
||||
# (as chk_hash and wip_hash are different) #
|
||||
#------------------------------------------#
|
||||
def compare_values(val1, val2):
|
||||
# Mainly for check comparison values
|
||||
if args.action == "check":
|
||||
if val1 != val2:
|
||||
return True
|
||||
#================================================#
|
||||
# At wip process, only, copy files to wip server #
|
||||
# At publish, files are copied, not generated #
|
||||
#------------------------------------------------#
|
||||
def copy_to_srv(article):
|
||||
# Copy needed files used by article
|
||||
try:
|
||||
for key, value in post.cf.items("FILES"):
|
||||
# Extract directories and create them
|
||||
dirs = domain.wip + value.rsplit(os.path.basename(value))[0]
|
||||
create_dirs(dirs)
|
||||
copy_files(
|
||||
domain.wrk_dirs["articles"] + value,
|
||||
domain.wip + value
|
||||
)
|
||||
except:
|
||||
pass
|
||||
|
||||
# Others, like wip, publish
|
||||
else:
|
||||
if val1 == val2: return True
|
||||
# Create article contents file to server
|
||||
wip_uri = post.cf.get("URIS", "wip")
|
||||
dirs = wip_uri.rsplit(os.path.basename(wip_uri))[0]
|
||||
create_dirs(dirs)
|
||||
create_file(post.cf.get("URIS", "wip"), article)
|
||||
|
||||
# Copy Article source code if set in domain configuration
|
||||
if domain.conf["post_code"]:
|
||||
copy_files(
|
||||
post.uri,
|
||||
post.uri.replace(domain.wrk_dirs["articles"], domain.wip)
|
||||
)
|
||||
|
||||
|
||||
#====================#
|
||||
# Copy file with log #
|
||||
#--------------------#
|
||||
def copy_files(src, dst):
|
||||
try:
|
||||
shutil.copy2(src, dst)
|
||||
debug.out(205, os.path.basename(src), dst, False, 0, False)
|
||||
except:
|
||||
debug.out(5, os.path.basename(src), dst, True, 2, True)
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
def copy_template_dir(process):
|
||||
src_dirs = {
|
||||
"wip" : domain.wrk_dirs["template"],
|
||||
"www" : domain.wip_dirs["template"],
|
||||
}
|
||||
dst_dirs = {
|
||||
"wip" : domain.wip_dirs["template"],
|
||||
"www" : domain.www_dirs["template"],
|
||||
}
|
||||
|
||||
create_dirs(dst_dirs[process])
|
||||
shutil.copytree(src_dirs[process], dst_dirs[process], dirs_exist_ok=True)
|
||||
|
||||
|
||||
|
||||
#====================================================#
|
||||
# Sorte dict by length name #
|
||||
# To avoid a bug with replace for similar tags names #
|
||||
# Mostly used with wip processes #
|
||||
# codes, raws, images #
|
||||
# Return new sorted dict #
|
||||
#----------------------------------------------------#
|
||||
def sort_dict(d):
|
||||
set_dict = {}
|
||||
|
||||
for nbr in d:
|
||||
set_dict[d[nbr][0]] = d[nbr]
|
||||
|
||||
list_dict = list(set_dict)
|
||||
return(set_dict, sorted(list_dict, reverse=True))
|
||||
|
||||
|
||||
#============================#
|
||||
# With "all" in command line #
|
||||
# Search for all .tyto files #
|
||||
# in work domain articles/ #
|
||||
# start wip process for each #
|
||||
#----------------------------#
|
||||
def get_articles():
|
||||
root_dir = domain.wrk_dirs["articles"]
|
||||
files = filter(os.path.isfile,
|
||||
glob.glob(root_dir + '**/*.tyto', recursive=True)
|
||||
)
|
||||
|
||||
for uri in files:
|
||||
args.article = uri.rsplit(root_dir)[1]
|
||||
wip.article()
|
||||
|
||||
return False
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -36,121 +36,73 @@ ok = ("yes", "y")
|
|||
# Form
|
||||
q = "?"
|
||||
pp = ":"
|
||||
error = "Error"
|
||||
success = "Success"
|
||||
configure_domain = "Configure domain"
|
||||
domain = "Domain"
|
||||
domain_title = "Domain title"
|
||||
domain_date = "Creation date"
|
||||
domain_about = "Domain description"
|
||||
domain_mail = "Admin mail"
|
||||
domain_tags = "Domain tags [1,2,3]"
|
||||
domain_lang = "Website lang"
|
||||
domain_srv = "Server URI"
|
||||
copy = "Copy"
|
||||
create_sitemaps = "Creating sitemaps"
|
||||
completed = "Completed"
|
||||
|
||||
# Misc
|
||||
anchor_title = "Anchor title"
|
||||
error = "Error"
|
||||
|
||||
# logs for debug
|
||||
#---------------
|
||||
# Errors
|
||||
err_arg = "Argument error"
|
||||
err_hole = "Current directory error"
|
||||
err_date = "Date error"
|
||||
err_lang = "Lang error"
|
||||
err_dir = "Directory error"
|
||||
err_no_dir = "Directory unused"
|
||||
err_cd = "Directory not created"
|
||||
err_no_file = "File unused"
|
||||
err_cr_file = "File not created"
|
||||
err_bad_uri = "URI error"
|
||||
err_post_sep = "Separator unused"
|
||||
err_post_head = "Header is empty"
|
||||
err_post_empty = "Article is empty"
|
||||
err_ini_file = "Configuration error"
|
||||
err_post_data = "Data unused"
|
||||
err_post_title = "Title error"
|
||||
err_post_paired = "Markers not paired"
|
||||
err_post_in_tag = "Markers without contents"
|
||||
err_post_datatag = "Data reserved"
|
||||
err_post_id_yet = "ID used yet"
|
||||
err_post_global = "Article Error"
|
||||
err_post_not_chk = "Article not checked"
|
||||
err_post_not_www = "Article not published"
|
||||
err_in_hole = "Current directory deleted"
|
||||
err_process = "Process error"
|
||||
err_argument = "Argument error"
|
||||
err_domain_name = "Domain name error"
|
||||
err_domain_dir = "Domain name directory error"
|
||||
err_kbd_stop = "Keyboard interrupt"
|
||||
err_file_create = "File not created"
|
||||
err_file_no = "Unused file"
|
||||
err_dir_create = "Directory not created"
|
||||
err_dir_unused = "Unused Directory"
|
||||
err_dir_in = "Not in needed directory"
|
||||
err_lang_no = "Unavailable language"
|
||||
err_post_sep = "Unused separator"
|
||||
err_post_header_no = "Empty header"
|
||||
err_post_writer_no = "Empty article"
|
||||
err_post_tag_set = "Unused datas"
|
||||
err_post_tag_val = "Data error"
|
||||
err_post_tag_id = "Identity set yet"
|
||||
err_post_mark_no = "Mark not found"
|
||||
err_post_mark_stop = "Mark not closed"
|
||||
err_post_mark_miss = "Missing Mark?"
|
||||
err_post_db = "Article not configured"
|
||||
err_post_srv_no = "Article not in server"
|
||||
|
||||
# Warnings
|
||||
warn_no_dom = "Domain not configured"
|
||||
domain_off = "Domain deactivated"
|
||||
reset_dom = "RESET domain"
|
||||
warn_post_chk = "Article changed"
|
||||
warn_domain_no = "Domain not configured"
|
||||
warn_domain_conf = "Bad domain configuration"
|
||||
warn_date_format = "Date format"
|
||||
warn_post_tupic = "Parameters format"
|
||||
warn_maybe_later = "Maybe later..."
|
||||
|
||||
# infos
|
||||
load_file = "File loaded"
|
||||
lang_logs_sys = "Logs lang"
|
||||
website_lang = "Website lang"
|
||||
domains_no = "Domain not found"
|
||||
domain_found = "Domain exists"
|
||||
domain_on = "Domain activated"
|
||||
domain_created = "Domain updated yet"
|
||||
domain_updated = "Domain updated"
|
||||
domain_new = "Domain created"
|
||||
created_dir = "Directory created"
|
||||
created_file = "File created"
|
||||
updated_file = "File Updated"
|
||||
reading_domain = "Preparing domain"
|
||||
processing = "Process"
|
||||
checking_post = "Checking article"
|
||||
wipping_post = "Converting article"
|
||||
post_chk_yet = "Article checked yet"
|
||||
post_chk_ready = "Article checked"
|
||||
later = "Maybe later..."
|
||||
inf_dir_user = "Starting Tyto"
|
||||
inf_lang_logs = "Logs language"
|
||||
inf_domain_load = "Domain loaded"
|
||||
inf_domain_conf = "Configuring domain"
|
||||
inf_file_upd = "File updated"
|
||||
inf_file_create = "File created"
|
||||
inf_dir_create = "Directory created"
|
||||
inf_check_post = "Checking article"
|
||||
inf_wip_process = "Converting"
|
||||
inf_mod_process = "Checking modules"
|
||||
inf_end_process = "Tyto!"
|
||||
|
||||
#
|
||||
# Show HELP
|
||||
#
|
||||
help_contents = """
|
||||
tyto [action] [target] [options]
|
||||
[action]
|
||||
new : create new domain (reset with -F)
|
||||
set : [server, date, title, mail, footer, header, ...]
|
||||
start : activate domain (default "no" when created)
|
||||
stop : deactivate domain
|
||||
show : [domains, metas]
|
||||
check : [domain, wip, www, [name].tyto]
|
||||
wip : [name].tyto: create HTML page in "wip/" server
|
||||
publish :
|
||||
# Form
|
||||
ask_domain_name = "Configure domain"
|
||||
ask_domain_title = "Domain title"
|
||||
ask_domain_date = "Domain creation date"
|
||||
ask_domain_about = "Domain description"
|
||||
ask_domain_tags = "Domain global tags"
|
||||
ask_domain_mail = "Administrator mail"
|
||||
ask_website_lang = "Website language"
|
||||
ask_srv_root = "Server root directory"
|
||||
ask_reset_modules = "Reset all modules"
|
||||
|
||||
[target]
|
||||
domain : all about current domain home
|
||||
domains : list all registred domains
|
||||
title : [set]: domain title
|
||||
date : [set]: domain creation date
|
||||
about : [set]: domain description
|
||||
mail : [set]: domain admin mail
|
||||
tags : [set]: domain tags (added to all articles)
|
||||
lang : [set]: Website language
|
||||
server : [set]: server local URI
|
||||
footer : [set]: Create default module (also header...)
|
||||
wip : [check] Directories and files
|
||||
www : [check] Directories and files
|
||||
|
||||
[options] ; multi-set
|
||||
--force, -F : force doing things...
|
||||
--debug, -D : show more logs
|
||||
--errors, -E : Show mainly warnings and errors logs
|
||||
"""
|
||||
|
||||
#
|
||||
# Modules (metas, navbar, sidebar...)
|
||||
#
|
||||
metas_header = """#
|
||||
# Modules
|
||||
metas_raw = """
|
||||
#=========================================================#
|
||||
# HTML Metas cnfiguration file used by Tyto - Littérateur #
|
||||
#---------------------------------------------------------#
|
||||
#
|
||||
|
||||
# Domain Name : %s
|
||||
# Domain URI : %s
|
||||
|
@ -167,18 +119,31 @@ metas_header = """#
|
|||
# ? Type "tyto show metas" to show all others to be added
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="all">
|
||||
<meta name="medium" content="website">
|
||||
<meta name="revisit-after" content="3 days">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
"""
|
||||
|
||||
navbar_header = """#
|
||||
header_raw = """
|
||||
#======================================================#
|
||||
# Header configuration file used by Tyto - Littérateur #
|
||||
#------------------------------------------------------#
|
||||
|
||||
# Domain Name : %s
|
||||
# Domain URI : %s
|
||||
|
||||
# WRK : %s
|
||||
# WIP : %s
|
||||
# WWW : %s
|
||||
|
||||
# How to configure this file:
|
||||
# - Edit, replace HTML code
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
navbar_raw = """
|
||||
#=====================================================#
|
||||
# Navbar cnfiguration file used by Tyto - Littérateur #
|
||||
#-----------------------------------------------------#
|
||||
#
|
||||
|
||||
# Domain Name : %s
|
||||
# Domain URI : %s
|
||||
|
||||
|
@ -189,32 +154,29 @@ navbar_header = """#
|
|||
# How to configure this file:
|
||||
# - Add one directory URI per line
|
||||
# - - URI is from domain directory articles/
|
||||
# ! Must contains an article "index.tyto" ready
|
||||
# Option:
|
||||
# - Default link name : directory
|
||||
# - Add "# Link Name" to change it
|
||||
# ! Server directory must contains an article "index.html"
|
||||
|
||||
# Examples:
|
||||
# news !
|
||||
# news
|
||||
# about/website
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
sidebar_header = """#
|
||||
#========================================================================#
|
||||
# Fichier de config de la barre latérale utilisée par Tyto - Littérateur #
|
||||
#------------------------------------------------------------------------#
|
||||
#
|
||||
# Nom du domaine : %s
|
||||
# URI du domaine : %s
|
||||
sidebar_raw = """
|
||||
#=======================================================#
|
||||
# Sidebar configuration file used by Tyto - Littérateur #
|
||||
#-------------------------------------------------------#
|
||||
|
||||
# Domain Name : %s
|
||||
# Domain URI : %s
|
||||
|
||||
# WRK : %s
|
||||
# WIP : %s
|
||||
# WWW : %s
|
||||
|
||||
# How to configure this file:
|
||||
# - Add one article file URI per line
|
||||
# - Add 1 article file URI (.tyto) per line
|
||||
# - - URI is from domain directory articles/
|
||||
|
||||
# Examples:
|
||||
|
@ -223,3 +185,488 @@ sidebar_header = """#
|
|||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
footer_raw = """
|
||||
#======================================================#
|
||||
# Footer configuration file used by Tyto - Littérateur #
|
||||
#------------------------------------------------------#
|
||||
|
||||
# Domain Name : %s
|
||||
# Domain URI : %s
|
||||
|
||||
# WRK : %s
|
||||
# WIP : %s
|
||||
# WWW : %s
|
||||
|
||||
# How to configure this file:
|
||||
# - Edit, replace HTML code
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
help_man = """
|
||||
tyto [ACTION] [ARGUMENTS]
|
||||
|
||||
- [ACTION] : main argument
|
||||
help * > this help * see [help]
|
||||
new ? add a domain / reset a module
|
||||
start > activate current domain
|
||||
stop > deactivate current domain
|
||||
check ? + [domain] : check current domain
|
||||
wip ? create HTML in "wip/" server
|
||||
publish ? publish in "www/" server
|
||||
|
||||
- [ARGUMENTS] : multiples (random order)
|
||||
domain > create new/check domain
|
||||
[abc].tyto > target [abc].tyto (multiples)
|
||||
all > [wip] : target all .tyto files in current domain
|
||||
|
||||
[MODULES] : (Useless with [publish])
|
||||
metas > target metas module
|
||||
header > target header module
|
||||
navbar > target navbar module
|
||||
sidebar > target sidebar module
|
||||
footer > target footer module
|
||||
modules > target all modules (metas,...,footer)
|
||||
|
||||
[DIVERS]
|
||||
-v > show all logs
|
||||
-E > show warns and errors logs only
|
||||
|
||||
- [help] * : * multiples. Documentation
|
||||
"?" > see argument name before "?"
|
||||
all > show all helps
|
||||
modules > use modules
|
||||
article > write .tyto article
|
||||
list > write a list
|
||||
cite > write a blockquote
|
||||
image > show image
|
||||
link > write a link
|
||||
file > write a link to a file
|
||||
words > write in strong, emphasis...
|
||||
abbr > write abbr
|
||||
anchor > set and link to anchor
|
||||
code > show code from content file
|
||||
raw > paste content file
|
||||
"""
|
||||
|
||||
help_new = """
|
||||
: [new]
|
||||
- [new domain]
|
||||
Add a new domain in current directory. Directory name must be at least
|
||||
abc.tld format. Forms must be answered. Domain is deactivated by default.
|
||||
CHECK first datas in configuration file tyto_domain.ini.
|
||||
Activate/Deacvtivate with [tyto start] and [tyto stop], or change to
|
||||
"False"/"True" the "activated" key in [DOMAIN] section
|
||||
|
||||
- [new sitemap]
|
||||
Create a new sitemap.html in "www/" server. Can be usefull if some header
|
||||
datas in an article were changed, but, the sitemap is generated at each
|
||||
[publish] command
|
||||
|
||||
- [new [MODULES]]
|
||||
see [help modules]
|
||||
"""
|
||||
|
||||
help_check = """
|
||||
: [check]
|
||||
- [check domain]
|
||||
Ask Tyto to check the current domain configuration. Show configuration
|
||||
file contents. Works everywhere from root domain directory.
|
||||
Configuration file is named "tyto_domain.ini".
|
||||
Process is also done if the configuration file has changed.
|
||||
"""
|
||||
|
||||
help_wip = """
|
||||
: [wip]
|
||||
- [wip [abc].tyto]
|
||||
Check article and create HTML article. Create then, full HTML page in
|
||||
"wip/" server. Copy all needed by article files. Also copy all files
|
||||
from /template/ domain to /wip/template/ server.
|
||||
|
||||
- [wip [MODULES]]
|
||||
voir [help modules]
|
||||
"""
|
||||
|
||||
help_modules = """
|
||||
: [MODULES] (metas...footer, modules)
|
||||
- [new modules]
|
||||
La première création des fichiers de configuration des modules est
|
||||
automatique dans le dossier du domaine "/modules/". Cette commande
|
||||
demande de réinitialiser TOUS les modules, ce qui videra les entrées
|
||||
de dossiers dans le fichier navbar.raw, et les entrées d'articles dans
|
||||
le fichier sidebar.raw. Les autres modules (metas, header, footer)
|
||||
auront leur contenus par défaut. Si vous modifiez le fichier de
|
||||
configuration du domaine, et notamment les valeurs dans la section
|
||||
[WEBSITE_FOOTER], il faudra réinitialiser le module footer.
|
||||
|
||||
- [new [MODULE]]
|
||||
Réinitialiser uniquement le [MODULE] concerné.
|
||||
|
||||
- [wip modules]
|
||||
Cette action force la (re)génération HTML de TOUS les modules
|
||||
dans le serveur "wip/template/". Peut être utile, notamment
|
||||
pour les modules navbar et sidebar lorsque le titre ou la
|
||||
descrtiption d'un article se trouvant dedans a été modifié.
|
||||
|
||||
- [wip [MODULE]]
|
||||
(re)générer uniquement le [MODULE] concerné
|
||||
|
||||
! Pour que ces modules puissent être affichés dans les pages du site, il
|
||||
faut ajouter dans le fichier de configuration du serveur nginx
|
||||
(/etc/nginx/sites-available/DOMAINE.TLD) :
|
||||
|
||||
...
|
||||
ssi on;
|
||||
ssi_last_modified on;
|
||||
absolute_redirect off;
|
||||
...
|
||||
"""
|
||||
|
||||
# --------- #
|
||||
# Help list #
|
||||
# --------- #
|
||||
help_list = """
|
||||
# Liste. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# Une entrée de liste peut être ordonnée avec le signe "+" ou non avec "="
|
||||
# Une liste peut contenir des entrées mixées ("+" et "=")
|
||||
# mais au changement de signe, ajouter un signe !
|
||||
# Possible d'écrire une entrée sur plusieurs lignes
|
||||
|
||||
(=
|
||||
= Première entrée non ordonnée (ul)
|
||||
== Sous entrée non ordonnée
|
||||
+++ Première sous-sous entrée ordonnée (ol)
|
||||
+++ Seconde sous-sous entrée ordonnée
|
||||
= Seconde entrée non ordonnée
|
||||
= Troisième entrée ...
|
||||
... non ordonnée
|
||||
)=
|
||||
"""
|
||||
|
||||
# --------- #
|
||||
# Help cite #
|
||||
# --------- #
|
||||
help_cite = """
|
||||
# Citation (bloc). Classe CSS possible (défaut : celle dans la configuration)
|
||||
# Les métadonnées d'une citation sont toutes optionnelles.
|
||||
# (Vous pouvez mettre que cite: et book:)
|
||||
|
||||
("
|
||||
cite: Auteur
|
||||
date: AAAA-MM-JJ
|
||||
book: Nom du livre
|
||||
lang: fr
|
||||
link: https://...
|
||||
|
||||
((
|
||||
Citation complète dans un paragraphe
|
||||
))
|
||||
)"
|
||||
"""
|
||||
|
||||
help_3lines = """# Ces marqueurs multiples doivent toujours être configurés sur 3 lignes
|
||||
# Les noms doivent tous être uniques et reportés dans le contenu
|
||||
# rédactionnel avec "::" devant le nom"""
|
||||
|
||||
# ---------- #
|
||||
# Help image #
|
||||
# ---------- #
|
||||
help_image_header = """
|
||||
image: Image001
|
||||
URI
|
||||
Texte alternatif
|
||||
"""
|
||||
|
||||
help_image_writer = """
|
||||
# Images. (Nom reporté de l'entête)
|
||||
# Options possibles devant respecter le format :
|
||||
# ::Nom "c=ClassCSS", "w=WIDTH", "h=HEIGHT", "f=Légende de l'image"
|
||||
# ! Une seule option termine par ","
|
||||
|
||||
::Image001
|
||||
::Image001 "f=Une légende",
|
||||
"""
|
||||
|
||||
help_image = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_image_header,
|
||||
help_image_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help link #
|
||||
# --------- #
|
||||
help_link_header = """
|
||||
link: Nom du lien
|
||||
URL / uri (non vérifié)
|
||||
Texte alternatif
|
||||
"""
|
||||
|
||||
help_link_writer = """
|
||||
# Écrire un lien (Nom reporté de l'entête)
|
||||
|
||||
::Nom du lien
|
||||
"""
|
||||
|
||||
help_link = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s"""%(
|
||||
help_3lines,
|
||||
help_link_header,
|
||||
help_link_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help Code #
|
||||
# --------- #
|
||||
help_code_header = \
|
||||
"""code: CodePython001
|
||||
URI
|
||||
Description placée en commentaire HTML"""
|
||||
|
||||
help_code_writer = """
|
||||
# Afficher le code source d'un fichier
|
||||
# Code. (Nom reporté de l'entête)
|
||||
|
||||
::CodePython001
|
||||
"""
|
||||
|
||||
help_code = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_code_header,
|
||||
help_code_writer,
|
||||
)
|
||||
|
||||
# -------- #
|
||||
# Help Raw #
|
||||
# -------- #
|
||||
help_raw_header = """
|
||||
raw: CodeHTML001
|
||||
URI
|
||||
Description placée en commentaire HTML
|
||||
"""
|
||||
|
||||
help_raw_writer = """
|
||||
# Coller le contenu du fichier brut (exécuté par le navigateur)
|
||||
# Raw. (Nom reporté de l'entête)
|
||||
|
||||
::CodeHTML001
|
||||
"""
|
||||
|
||||
help_raw = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_raw_header,
|
||||
help_raw_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help ABBR #
|
||||
# --------- #
|
||||
help_abbr_header = """
|
||||
abbr: CSS
|
||||
Cascading SteelSheet
|
||||
lang (en, fr, es...)
|
||||
"""
|
||||
|
||||
help_abbr_writer = """
|
||||
# Abréviations. (Nom reporté de l'entête)
|
||||
|
||||
::CSS
|
||||
"""
|
||||
|
||||
help_abbr = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_abbr_header,
|
||||
help_abbr_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help ABBR #
|
||||
# --------- #
|
||||
help_anc_header = """
|
||||
# Définir une ancre
|
||||
# ! Chaque ancre doit avoir une ID unique
|
||||
# (et ne pas commencer par "toc_")
|
||||
|
||||
-> top
|
||||
"""
|
||||
|
||||
help_anc_writer = """
|
||||
# Lien vers une ancre définie
|
||||
# format : >`ID: Message à afficher`<
|
||||
|
||||
>`top:Aller en haut`<
|
||||
"""
|
||||
|
||||
help_anc = """%s%s
|
||||
"""%(
|
||||
help_anc_header,
|
||||
help_anc_writer,
|
||||
)
|
||||
|
||||
|
||||
# ---------- #
|
||||
# Words tags #
|
||||
# ---------- #
|
||||
help_words = """
|
||||
# Écrire les marqueurs de mots
|
||||
# Chaque marqueur à la classe CSS de la configuration
|
||||
# Astuce : ** + ← + `` + ← + très gras
|
||||
|
||||
*`très gras`* => <strong>
|
||||
+`gras`+ => <b>
|
||||
/`italique`/ => <em>
|
||||
;`italique`; => <i>
|
||||
_`souligné`_ => <u>
|
||||
~`effacé`~ => <del>
|
||||
[`cité`] => <q> # Contenu
|
||||
:`cité`: => <cite> # auteur, nom
|
||||
|`perso`| => <span>
|
||||
|
||||
# Code dans un texte
|
||||
# ! Les marqueurs d'ouverture et de fermeture de code sont sur la MEME LIGNE
|
||||
|
||||
{` <li>Une entée de liste</li> `} => <code>
|
||||
|
||||
# ! Dans certains cas, il faut ajouter un espace après le 1er marqueur
|
||||
# et/ou avant le second. Ils seront automatiquement supprimés
|
||||
|
||||
*`DOMAIN/articles/ `* # évite /` : marqueur italique ouvert
|
||||
"""
|
||||
|
||||
# ------------ #
|
||||
# Full article #
|
||||
# ------------ #
|
||||
help_article = """
|
||||
: [.tyto]
|
||||
Un fichier-article .tyto est séparé en 2 par au moins 5 tirets
|
||||
"-----" pour définir l'entête (les métadonnées), et le contenu
|
||||
rédactionnel. Voici le contenu d'un fichier-article .tyto avec
|
||||
tous les marqueurs possibles. Les lignes commençant par "#" sont
|
||||
des commentaires (que vous pouvez aussi utiliser dans vos articles)
|
||||
|
||||
# Début du fichier
|
||||
# ----------------
|
||||
|
||||
# Ces 5 marqueurs sont obligatoires
|
||||
# ----------
|
||||
title: Titre <h1> de l'article
|
||||
about: Description de l'article
|
||||
tags: étiquette1,étiquette longue,étiquette3
|
||||
date: AAAA-MM-JJ
|
||||
authors: auteur1,auteur2
|
||||
|
||||
# Tous les marqueurs suivants sont optionnels
|
||||
# ----------
|
||||
# Si non renseigné, le logo de l'article sera celui du site
|
||||
logo: URI
|
||||
|
||||
%s
|
||||
%s%s%s%s%s%s
|
||||
# URI
|
||||
# - Commence par @ :
|
||||
# - - le fichier est dans articles/images/ pour les marqueurs logo: et image:
|
||||
# - - le fichier est dans articles/files/ pour les autres marqueurs
|
||||
# - Commence par / :
|
||||
# - - le fichier est depuis la racine articles/ du domaine
|
||||
# - Commence pas par @ ou / :
|
||||
# - - le fichier est depuis le dossier où se trouve le fichier-article .tyto
|
||||
|
||||
# Marqueur pour NE PAS inclure l'article dans le sitemap
|
||||
! NOMAP
|
||||
|
||||
# Marqueur pour NE PAS inclure l'article dans le flux RSS
|
||||
! NORSS
|
||||
|
||||
# Séparateur
|
||||
-----
|
||||
|
||||
%s
|
||||
# Marqueur pour créer la table des matières en fonction des titres
|
||||
! TOC
|
||||
|
||||
# Les titres (#1 à #5, équivalents de <h2> à <h6>)
|
||||
#1 Titre 1
|
||||
#2 Sous-titre 1
|
||||
|
||||
# Paragraphe. Classe CSS possible (défaut : celle dans la configuration)
|
||||
((
|
||||
Un paragraphe
|
||||
(( note
|
||||
Un sous-paragraphe ayant la classe CSS "note"
|
||||
))
|
||||
))
|
||||
|
||||
# Block-Code. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# ! Le marqueur d'ouverture est à la même position que le marqueur de fermeture
|
||||
{{ PyCode
|
||||
...
|
||||
...
|
||||
}}
|
||||
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
|
||||
# Retour à la ligne. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# La ligne commence par le symbôle "|" (<br>)
|
||||
::Image001
|
||||
|
|
||||
::Image001 "c=Maclasse",
|
||||
|
||||
# Tirer un trait. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# La ligne contient juste "--" (<hr>)
|
||||
--
|
||||
%s
|
||||
|
||||
# --------------
|
||||
# Fin du fichier
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_link_header,
|
||||
help_file_header,
|
||||
help_image_header,
|
||||
help_code_header,
|
||||
help_raw_header,
|
||||
help_abbr_header,
|
||||
help_anc_header,
|
||||
help_list,
|
||||
help_cite,
|
||||
help_image_writer,
|
||||
help_raw_writer,
|
||||
help_code_writer,
|
||||
help_link_writer,
|
||||
help_file_writer,
|
||||
help_words,
|
||||
help_abbr_writer,
|
||||
help_anc_writer,
|
||||
)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
# - Copier ce contenu dedans, et traduire les variables
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# Rappel: Fichier au format python
|
||||
# Note : fichier python
|
||||
|
||||
# Réponses valides (! NON sensible à la case : oui = OUI, Oui...)
|
||||
ok = ("oui", "o")
|
||||
|
@ -36,122 +36,74 @@ ok = ("oui", "o")
|
|||
# Form
|
||||
q = " ?"
|
||||
pp = " :"
|
||||
error = "Erreur"
|
||||
success = "Succès"
|
||||
configure_domain = "Configurer le domaine"
|
||||
domain = "Domaine"
|
||||
domain_title = "Titre du domaine"
|
||||
domain_date = "Date de création"
|
||||
domain_about = "Description du domaine"
|
||||
domain_mail = "Courriel de l'administration"
|
||||
domain_tags = "Mots-clés du domaine [1,2,3]"
|
||||
domain_lang = "Langue du site web"
|
||||
domain_srv = "URI du serveur"
|
||||
copy = "Copie"
|
||||
create_sitemaps = "Création des plans du site"
|
||||
completed = "Terminé"
|
||||
|
||||
# Misc
|
||||
anchor_title = "Titre de l'ancre"
|
||||
error = "Erreur"
|
||||
|
||||
# logs for debug
|
||||
#---------------
|
||||
# Errors
|
||||
err_arg = "Argument invalide"
|
||||
err_hole = "Dossier courant invalide"
|
||||
err_date = "Date invalide"
|
||||
err_lang = "Format de langue invalide"
|
||||
err_dir = "Dossier non compatible"
|
||||
err_no_dir = "Dossier inexistant"
|
||||
err_cd = "Dossier non créé"
|
||||
err_no_file = "Fichier manquant"
|
||||
err_cr_file = "Fichier non créé"
|
||||
err_bad_uri = "URI non compatible"
|
||||
err_in_hole = "Dossier courant supprimé"
|
||||
err_process = "Processus invalide"
|
||||
err_argument = "Argument non valide"
|
||||
err_domain_name = "Nom de domaine non valide"
|
||||
err_domain_dir = "Dossier de domaine non valide"
|
||||
err_kbd_stop = "Interruption clavier"
|
||||
err_file_create = "Fichier non créé"
|
||||
err_file_no = "Fichier manquant"
|
||||
err_dir_create = "Dossier non créé"
|
||||
err_dir_unused = "Dossier manquant"
|
||||
err_dir_in = "Pas dans le bon dossier"
|
||||
err_lang_no = "Langue non disponible"
|
||||
err_post_sep = "Séparateur manquant"
|
||||
err_post_head = "Entête vide"
|
||||
err_post_empty = "Article vide"
|
||||
err_ini_file = "Configuration invalide"
|
||||
err_post_data = "Donnée manquante"
|
||||
err_post_title = "Titre invalide"
|
||||
err_post_paired = "Marqueurs non apairés"
|
||||
err_post_in_tag = "Marqueurs sans contenu"
|
||||
err_post_datatag = "Donnée réservée"
|
||||
err_post_id_yet = "Identité déjà utilisée"
|
||||
err_post_global = "Article erronné"
|
||||
err_post_not_chk = "Article non vérifié"
|
||||
err_post_not_www = "Article non publié"
|
||||
err_post_header_no = "Entête vide"
|
||||
err_post_writer_no = "Article vide"
|
||||
err_post_tag_set = "Données manquantes"
|
||||
err_post_tag_val = "Donnée non valide"
|
||||
err_post_tag_id = "Identité déjà utilisée"
|
||||
err_post_mark_no = "Marqueur non trouvé"
|
||||
err_post_mark_stop = "Marqueur non fermé"
|
||||
err_post_mark_miss = "Marqueur manquant ?"
|
||||
err_post_db = "Article non configuré"
|
||||
err_post_srv_no = "Article manquant sur le serveur"
|
||||
|
||||
# Warnings
|
||||
warn_no_dom = "Domaine non configuré"
|
||||
domain_off = "Domaine désactivé"
|
||||
reset_dom = "RÉINITIALISE le domaine"
|
||||
warn_post_chk = "Article modifié"
|
||||
warn_domain_no = "Domaine non configuré"
|
||||
warn_domain_conf = "Domaine mal configuré"
|
||||
warn_date_format = "format de date"
|
||||
warn_post_tupic = "Format de paramètres"
|
||||
warn_maybe_later = "Peut-être plus tard..."
|
||||
|
||||
# infos
|
||||
load_file = "Fichier chargé"
|
||||
lang_logs_sys = "Langue des logs"
|
||||
website_lang = "Langue du site web"
|
||||
domains_no = "Aucun domaine trouvé"
|
||||
domain_found = "Domaine présent"
|
||||
domain_on = "Domaine activé"
|
||||
domain_created = "Domaine déjà créé"
|
||||
domain_updated = "Domaine mis à jour"
|
||||
domain_new = "Domaine créé"
|
||||
created_dir = "Dossier créé"
|
||||
created_file = "Fichier créé"
|
||||
updated_file = "Fichier mis à jour"
|
||||
reading_domain = "Préparation du domaine"
|
||||
processing = "Process"
|
||||
checking_post = "Vérification de l'article"
|
||||
wipping_post = "Convertion de l'article"
|
||||
post_chk_yet = "Article déjà vérifié"
|
||||
post_chk_ready = "Article vérifié"
|
||||
later = "Peut-être plus tard..."
|
||||
inf_dir_user = "Démarrage de Tyto"
|
||||
inf_lang_logs = "Langue des logs"
|
||||
inf_domain_load = "Domaine chargé"
|
||||
inf_domain_conf = "Configuration du domaine"
|
||||
inf_file_upd = "Fichier mis à jour"
|
||||
inf_file_create = "Fichier créé"
|
||||
inf_dir_create = "Dossier créé"
|
||||
inf_check_post = "Vérification de l'article"
|
||||
inf_wip_process = "Conversion"
|
||||
inf_mod_process = "Vérification des modules"
|
||||
inf_end_process = "Tyto!"
|
||||
|
||||
#
|
||||
# Show HELP
|
||||
#
|
||||
help_contents = """
|
||||
tyto [action] [target] [options]
|
||||
[action]
|
||||
new : créer un nouveau domaine (réinitialisé avec -F)
|
||||
set : [server, date, title, mail, footer, header, ...]
|
||||
start : activer le domaine (défaut "no" à la création)
|
||||
stop : désactiver le domaine
|
||||
show : [domains, metas]
|
||||
check : [domain, wip, www, [name].tyto]
|
||||
wip : [name].tyto: crée la page HTML dans le serveur "wip/"
|
||||
publish :
|
||||
# Form
|
||||
ask_domain_name = "Configurer le domaine"
|
||||
ask_domain_title = "Titre du domaine"
|
||||
ask_domain_date = "Date de création du domaine"
|
||||
ask_domain_about = "Description du domaine"
|
||||
ask_domain_tags = "Étiquettes globales du domaine"
|
||||
ask_domain_mail = "Courriel de l'administrateur"
|
||||
ask_website_lang = "Langue du site web"
|
||||
ask_srv_root = "Dossier du serveur root"
|
||||
ask_reset_modules = "Réinitialiser tous les modules"
|
||||
|
||||
[target]
|
||||
domain : pour tout ce qui concerne un domaine
|
||||
domains : montre tous les domaines enregistrés
|
||||
title : [set]: titre du domaine
|
||||
date : [set]: date de création du domaine
|
||||
about : [set]: description du domaine
|
||||
mail : [set]: courriel de l'administrateur
|
||||
tags : [set]: étiquettes du domaine (ajoutées aux articles)
|
||||
lang : [set]
|
||||
server : [set]: URI du serveur local
|
||||
footer : [set]: Crée le module par défaut (aussi header...)
|
||||
wip : [check] dossiers et fichiers
|
||||
www : [check] dossiers et fichiers
|
||||
|
||||
[options] ; multiples
|
||||
--force, -F : forcer à faire quelque chose...
|
||||
--debug, -D : montrer plus de logs
|
||||
--errors, -E : montrer surtout les avertissements et erreurs
|
||||
"""
|
||||
|
||||
#
|
||||
# Modules (metas, navbar, sidebar...)
|
||||
#
|
||||
|
||||
metas_header = """#
|
||||
# Modules
|
||||
metas_raw = """
|
||||
#========================================================================#
|
||||
# Fichier de configuration des metas HTML utilisé par Tyto - Littérateur #
|
||||
#------------------------------------------------------------------------#
|
||||
#
|
||||
|
||||
# Nom du domaine : %s
|
||||
# URI du domaine : %s
|
||||
|
||||
|
@ -167,18 +119,31 @@ metas_header = """#
|
|||
# ? Taper "tyto show metas" pour voir toutes celles ajoutées
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
<meta charset="UTF-8">
|
||||
<meta name="robots" content="all">
|
||||
<meta name="medium" content="website">
|
||||
<meta name="revisit-after" content="3 days">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
"""
|
||||
|
||||
navbar_header = """#
|
||||
header_raw = """
|
||||
#=====================================================================#
|
||||
# Fichier de configuration de l'entête utilisé par Tyto - Littérateur #
|
||||
#---------------------------------------------------------------------#
|
||||
|
||||
# Nom du domaine : %s
|
||||
# URI du domaine : %s
|
||||
|
||||
# WRK : %s
|
||||
# WIP : %s
|
||||
# WWW : %s
|
||||
|
||||
# Comment configurer ce fichier :
|
||||
# - Modifier, remplacer le code HTML
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
navbar_raw = """
|
||||
#======================================================================#
|
||||
# Fichier de config de la barre de menu utilisé par Tyto - Littérateur #
|
||||
#----------------------------------------------------------------------#
|
||||
#
|
||||
|
||||
# Nom du domaine : %s
|
||||
# URI du domaine : %s
|
||||
|
||||
|
@ -189,10 +154,7 @@ navbar_header = """#
|
|||
# Comment configurer ce fichier :
|
||||
# - Ajouter un URI de dossier par ligne
|
||||
# - - URI depuis le dossier articles/ du domaine
|
||||
# ! Doit contenir un article "index.tyto" prêt
|
||||
# Option :
|
||||
# - Nom du lien par défaut : directory
|
||||
# - Ajouter "# Nom du Lien" pour le changer
|
||||
# ! Le dossier serveur doit contenir un article "index.html"
|
||||
|
||||
# Exemples:
|
||||
# news
|
||||
|
@ -201,11 +163,11 @@ navbar_header = """#
|
|||
|
||||
"""
|
||||
|
||||
sidebar_header = """#
|
||||
#========================================================================#
|
||||
# Fichier de config de la barre latérale utilisée par Tyto - Littérateur #
|
||||
#------------------------------------------------------------------------#
|
||||
#
|
||||
sidebar_raw = """
|
||||
#=======================================================================#
|
||||
# Fichier de config de la barre latérale utilisé par Tyto - Littérateur #
|
||||
#-----------------------------------------------------------------------#
|
||||
|
||||
# Nom du domaine : %s
|
||||
# URI du domaine : %s
|
||||
|
||||
|
@ -214,7 +176,7 @@ sidebar_header = """#
|
|||
# WWW : %s
|
||||
|
||||
# Comment configurer ce fichier :
|
||||
# - Ajouter un URI d'article par ligne
|
||||
# - Ajouter 1 URI d'article (.tyto) par ligne
|
||||
# - - URI depuis le dossier articles/ du domaine
|
||||
|
||||
# Exemples :
|
||||
|
@ -223,3 +185,518 @@ sidebar_header = """#
|
|||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
footer_raw = """
|
||||
#=========================================================================#
|
||||
# Fichier de configuration du pied de page utilisé par Tyto - Littérateur #
|
||||
#-------------------------------------------------------------------------#
|
||||
|
||||
# Nom du domaine : %s
|
||||
# URI du domaine : %s
|
||||
|
||||
# WRK : %s
|
||||
# WIP : %s
|
||||
# WWW : %s
|
||||
|
||||
# Comment configurer ce fichier :
|
||||
# - Modifier, remplacer le code HTML
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
"""
|
||||
|
||||
help_man = """
|
||||
tyto [ACTION] [ARGUMENTS]
|
||||
|
||||
- [ACTION] : argument principal
|
||||
help * > cette aide * voir [help]
|
||||
new ? ajouter un domaine / réinitialiser un module
|
||||
start > activer le domain actuel
|
||||
stop > désactiver le domaine actuel
|
||||
check ? + [domain] : vérifier le domaine actuel
|
||||
wip ? créer de l'HTML dans le serveur "wip/"
|
||||
publish ? publier dans le serveur "www/"
|
||||
|
||||
- [ARGUMENTS] : multiples (ordre aléatoire)
|
||||
domain > créer/vérifier un domaine
|
||||
[nom].tyto > cible le fichier [nom].tyto (plusieurs possibles)
|
||||
all > [wip] : cible tous les fichiers .tyto du domaine courant
|
||||
|
||||
[MODULES] : (inutiles avec [publish])
|
||||
metas > cible le module metas
|
||||
header > cible le module header
|
||||
navbar > cible le module navbar
|
||||
sidebar > cible le module sidebar
|
||||
footer > cible le module footer
|
||||
modules > cible tous les modules (metas,...,footer)
|
||||
|
||||
[DIVERS]
|
||||
-v > montrer tous les logs
|
||||
-E > ne montrer que les erreurs et avertissements
|
||||
|
||||
- [help] * : * multiples. Documentation
|
||||
"?" > voir le nom de l'argument avant le signe "?"
|
||||
all > montre toutes les informations d'aides
|
||||
modules > utiliser les modules
|
||||
article > écrire un article .tyto
|
||||
list > écrire une liste
|
||||
cite > écrire une citation
|
||||
image > afficher une image
|
||||
link > écrire un lien
|
||||
file > écrire un lien vers un fichier
|
||||
words > écrire en gras, italique...
|
||||
abbr > écrire une abréviation
|
||||
anchor > définir, lier une ancre
|
||||
code > afficher un bloc de code d'un fichier
|
||||
raw > coller le contenu d'un fichier
|
||||
"""
|
||||
|
||||
help_new = """
|
||||
: [new]
|
||||
- [new domain]
|
||||
Ajouter un nouveau domaine dans le dossier courant. Le nom du dossier
|
||||
courant doit être au moins au format nom.tld. Un formulaire devra être
|
||||
rempli. Le domaine est désactivé par défaut. VÉRIFIEZ d'abord les données
|
||||
dans le fichier tyto_domain.ini, avant de l'activer.
|
||||
Pour activer/désactiver le domaine, utiliser [tyto start] et [tyto stop]
|
||||
ou, changer la valeur "False"/"True" de la clé "activated" dans la
|
||||
section [DOMAIN]
|
||||
|
||||
- [new sitemap]
|
||||
Créer un nouveau sitemap.html dans le serveur "www/". Peut-être utile en
|
||||
cas de changements de données dans l'entête d'un article, mais le sitemap
|
||||
est généré automatiquement à chaque commande [publish].
|
||||
|
||||
- [new [MODULES]]
|
||||
voir [help modules]
|
||||
"""
|
||||
|
||||
help_check = """
|
||||
: [check]
|
||||
- [check domain]
|
||||
Demander à Tyto de vérifier le domaine actuellement configuré.
|
||||
Montre le contenu du fichier de configuration. Il faut être dans
|
||||
l'arborescence du dossier de travail du domaine. Le fichier de
|
||||
configuration est nommé "tyto_domain.ini". Ce processus est également
|
||||
fait automatiquement lorsque le fichier de configuration a changé.
|
||||
"""
|
||||
|
||||
help_wip = """
|
||||
: [wip]
|
||||
- [wip [NOM].tyto]
|
||||
Vérifie le format de l'article et le transforme en contenu HTML. Crée
|
||||
ensuite la page HTML complète dans le serveur "wip/" et copie les
|
||||
fichiers utilisés par l'article. Copie les fichiers de /template/ du
|
||||
domaine vers le serveur /wip/template/.
|
||||
|
||||
- [wip [MODULES]]
|
||||
voir [help modules]
|
||||
"""
|
||||
|
||||
help_modules = """
|
||||
: [MODULES] (metas...footer, modules)
|
||||
- [new modules]
|
||||
La première création des fichiers de configuration des modules est
|
||||
automatique dans le dossier du domaine "/modules/". Cette commande
|
||||
demande de réinitialiser TOUS les modules. Les fichier sidebar.raw et
|
||||
navbar.raw seront vidés. Les autres modules (metas, header, footer)
|
||||
auront leur contenus par défaut.
|
||||
Si vous modifiez le fichier de configuration du domaine, et notamment les valeurs dans la section
|
||||
[WEBSITE_FOOTER], il faudra réinitialiser le module footer.
|
||||
|
||||
- [new [MODULE]]
|
||||
Réinitialiser uniquement le [MODULE] concerné.
|
||||
|
||||
- [wip modules]
|
||||
Cette action force la (re)génération HTML de TOUS les modules
|
||||
dans le serveur "wip/template/". Peut être utile, notamment
|
||||
pour les modules navbar et sidebar lorsque le titre ou la
|
||||
descrtiption d'un article se trouvant dedans a été modifié.
|
||||
|
||||
- [wip [MODULE]]
|
||||
(re)générer uniquement le [MODULE] concerné
|
||||
|
||||
! Pour que ces modules puissent être affichés dans les pages du site, il
|
||||
faut ajouter dans le fichier de configuration du serveur nginx
|
||||
(/etc/nginx/sites-available/DOMAINE.TLD) :
|
||||
|
||||
...
|
||||
ssi on;
|
||||
ssi_last_modified on;
|
||||
absolute_redirect off;
|
||||
...
|
||||
"""
|
||||
|
||||
# --------- #
|
||||
# Help list #
|
||||
# --------- #
|
||||
help_list = """
|
||||
# Liste. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# Une entrée de liste peut être ordonnée avec le signe "+" ou non avec "="
|
||||
# Une liste peut contenir des entrées mixées ("+" et "=")
|
||||
# mais au changement de signe, ajouter un signe !
|
||||
# Possible d'écrire une entrée sur plusieurs lignes
|
||||
|
||||
(=
|
||||
= Première entrée non ordonnée (ul)
|
||||
== Sous entrée non ordonnée
|
||||
+++ Première sous-sous entrée ordonnée (ol)
|
||||
+++ Seconde sous-sous entrée ordonnée
|
||||
= Seconde entrée non ordonnée
|
||||
= Troisième entrée ...
|
||||
... non ordonnée
|
||||
)=
|
||||
"""
|
||||
|
||||
# --------- #
|
||||
# Help cite #
|
||||
# --------- #
|
||||
help_cite = """
|
||||
# Citation (bloc). Classe CSS possible (défaut : celle dans la configuration)
|
||||
# Les métadonnées d'une citation sont toutes optionnelles.
|
||||
# (Vous pouvez mettre que cite: et book:)
|
||||
|
||||
("
|
||||
cite: Auteur
|
||||
date: AAAA-MM-JJ
|
||||
book: Nom du livre
|
||||
lang: fr
|
||||
link: https://...
|
||||
|
||||
((
|
||||
Citation complète dans un paragraphe
|
||||
))
|
||||
)"
|
||||
"""
|
||||
|
||||
help_3lines = """# Ces marqueurs multiples doivent toujours être configurés sur 3 lignes
|
||||
# Les noms doivent tous être uniques et reportés dans le contenu
|
||||
# rédactionnel avec "::" devant le nom"""
|
||||
|
||||
# ---------- #
|
||||
# Help image #
|
||||
# ---------- #
|
||||
help_image_header = """
|
||||
image: Image001
|
||||
URI
|
||||
Texte alternatif
|
||||
"""
|
||||
|
||||
help_image_writer = """
|
||||
# Images. (Nom reporté de l'entête)
|
||||
# Options possibles devant respecter le format :
|
||||
# ::Nom "c=ClassCSS", "w=WIDTH", "h=HEIGHT", "f=Légende de l'image"
|
||||
# ! Une seule option termine par ","
|
||||
|
||||
::Image001
|
||||
::Image001 "f=Une légende",
|
||||
"""
|
||||
|
||||
help_image = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_image_header,
|
||||
help_image_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help link #
|
||||
# --------- #
|
||||
help_link_header = """
|
||||
link: Nom du lien
|
||||
URL / uri (non vérifié)
|
||||
Texte alternatif
|
||||
"""
|
||||
|
||||
help_link_writer = """
|
||||
# Écrire un lien (Nom reporté de l'entête)
|
||||
|
||||
::Nom du lien
|
||||
"""
|
||||
|
||||
help_link = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s"""%(
|
||||
help_3lines,
|
||||
help_link_header,
|
||||
help_link_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help link #
|
||||
# --------- #
|
||||
help_file_header = """
|
||||
file: ce fichier
|
||||
URI
|
||||
Texte alternatif
|
||||
"""
|
||||
|
||||
help_file_writer = """
|
||||
# Écrire un lien vers un fichier (Nom reporté de l'entête)
|
||||
|
||||
::ce fichier
|
||||
"""
|
||||
|
||||
help_file = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s"""%(
|
||||
help_3lines,
|
||||
help_file_header,
|
||||
help_file_writer,
|
||||
)
|
||||
|
||||
|
||||
# --------- #
|
||||
# Help Code #
|
||||
# --------- #
|
||||
help_code_header = """
|
||||
code: CodePython001
|
||||
URI
|
||||
Description placée en commentaire HTML
|
||||
"""
|
||||
|
||||
help_code_writer = """
|
||||
# Afficher le code source d'un fichier
|
||||
# Code. (Nom reporté de l'entête)
|
||||
|
||||
::CodePython001
|
||||
"""
|
||||
|
||||
help_code = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_code_header,
|
||||
help_code_writer,
|
||||
)
|
||||
|
||||
# -------- #
|
||||
# Help Raw #
|
||||
# -------- #
|
||||
help_raw_header = """
|
||||
raw: CodeHTML001
|
||||
URI
|
||||
Description placée en commentaire HTML
|
||||
"""
|
||||
|
||||
help_raw_writer = """
|
||||
# Coller le contenu du fichier brut (exécuté par le navigateur)
|
||||
# Raw. (Nom reporté de l'entête)
|
||||
|
||||
::CodeHTML001
|
||||
"""
|
||||
|
||||
help_raw = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_raw_header,
|
||||
help_raw_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help ABBR #
|
||||
# --------- #
|
||||
help_abbr_header = """
|
||||
abbr: CSS
|
||||
Cascading SteelSheet
|
||||
lang (en, fr, es...)
|
||||
"""
|
||||
|
||||
help_abbr_writer = """
|
||||
# Abréviations. (Nom reporté de l'entête)
|
||||
|
||||
::CSS
|
||||
"""
|
||||
|
||||
help_abbr = """
|
||||
%s
|
||||
%s
|
||||
-----
|
||||
%s
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_abbr_header,
|
||||
help_abbr_writer,
|
||||
)
|
||||
|
||||
# --------- #
|
||||
# Help ABBR #
|
||||
# --------- #
|
||||
help_anc_header = """
|
||||
# Définir une ancre
|
||||
# ! Chaque ancre doit avoir une ID unique
|
||||
# (et ne pas commencer par "toc_")
|
||||
|
||||
-> top
|
||||
"""
|
||||
|
||||
help_anc_writer = """
|
||||
# Lien vers une ancre définie
|
||||
# format : >`ID: Message à afficher`<
|
||||
|
||||
>`top:Aller en haut`<
|
||||
"""
|
||||
|
||||
help_anc = """%s%s
|
||||
"""%(
|
||||
help_anc_header,
|
||||
help_anc_writer,
|
||||
)
|
||||
|
||||
|
||||
# ---------- #
|
||||
# Words tags #
|
||||
# ---------- #
|
||||
help_words = """
|
||||
# Écrire les marqueurs de mots
|
||||
# Chaque marqueur à la classe CSS de la configuration
|
||||
# Astuce : ** + ← + `` + ← + très gras
|
||||
|
||||
*`très gras`* => <strong>
|
||||
+`gras`+ => <b>
|
||||
/`italique`/ => <em>
|
||||
;`italique`; => <i>
|
||||
_`souligné`_ => <u>
|
||||
~`effacé`~ => <del>
|
||||
[`cité`] => <q> # Contenu
|
||||
:`cité`: => <cite> # auteur, nom
|
||||
|`perso`| => <span>
|
||||
|
||||
# Code dans un texte
|
||||
# ! Les marqueurs d'ouverture et de fermeture de code sont sur la MEME LIGNE
|
||||
|
||||
{` <li>Une entée de liste</li> `} => <code>
|
||||
|
||||
# ! Dans certains cas, il faut ajouter un espace après le 1er marqueur
|
||||
# et/ou avant le second. Ils seront automatiquement supprimés
|
||||
|
||||
*`DOMAIN/articles/ `* # évite /` : marqueur italique ouvert
|
||||
"""
|
||||
|
||||
# ------------ #
|
||||
# Full article #
|
||||
# ------------ #
|
||||
help_article = """
|
||||
: [.tyto]
|
||||
Un fichier-article .tyto est séparé en 2 par au moins 5 tirets
|
||||
"-----" pour définir l'entête (les métadonnées), et le contenu
|
||||
rédactionnel. Voici le contenu d'un fichier-article .tyto avec
|
||||
tous les marqueurs possibles. Les lignes commençant par "#" sont
|
||||
des commentaires (que vous pouvez aussi utiliser dans vos articles)
|
||||
|
||||
# Début du fichier
|
||||
# ----------------
|
||||
|
||||
# Ces 5 marqueurs sont obligatoires
|
||||
# ----------
|
||||
title: Titre <h1> de l'article
|
||||
about: Description de l'article
|
||||
tags: étiquette1,étiquette longue,étiquette3
|
||||
date: AAAA-MM-JJ
|
||||
authors: auteur1,auteur2
|
||||
|
||||
# Tous les marqueurs suivants sont optionnels
|
||||
# ----------
|
||||
# Si non renseigné, le logo de l'article sera celui du site
|
||||
logo: URI
|
||||
|
||||
%s
|
||||
%s%s%s%s%s%s
|
||||
# URI
|
||||
# - Commence par @ :
|
||||
# - - le fichier est dans articles/images/ pour les marqueurs logo: et image:
|
||||
# - - le fichier est dans articles/files/ pour les autres marqueurs
|
||||
# - Commence par / :
|
||||
# - - le fichier est depuis la racine articles/ du domaine
|
||||
# - Commence pas par @ ou / :
|
||||
# - - le fichier est depuis le dossier où se trouve le fichier-article .tyto
|
||||
|
||||
# Marqueur pour NE PAS inclure l'article dans le sitemap
|
||||
! NOMAP
|
||||
|
||||
# Marqueur pour NE PAS inclure l'article dans le flux RSS
|
||||
! NORSS
|
||||
|
||||
# Séparateur
|
||||
-----
|
||||
|
||||
%s
|
||||
# Marqueur pour créer la table des matières en fonction des titres
|
||||
! TOC
|
||||
|
||||
# Les titres (#1 à #5, équivalents de <h2> à <h6>)
|
||||
#1 Titre 1
|
||||
#2 Sous-titre 1
|
||||
|
||||
# Paragraphe. Classe CSS possible (défaut : celle dans la configuration)
|
||||
((
|
||||
Un paragraphe
|
||||
(( note
|
||||
Un sous-paragraphe ayant la classe CSS "note"
|
||||
))
|
||||
))
|
||||
|
||||
# Block-Code. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# ! Le marqueur d'ouverture est à la même position que le marqueur de fermeture
|
||||
{{ PyCode
|
||||
...
|
||||
...
|
||||
}}
|
||||
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
%s
|
||||
|
||||
# Retour à la ligne. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# La ligne commence par le symbôle "|" (<br>)
|
||||
::Image001
|
||||
|
|
||||
::Image001 "c=Maclasse",
|
||||
|
||||
# Tirer un trait. Classe CSS possible (défaut : celle dans la configuration)
|
||||
# La ligne contient juste "--" (<hr>)
|
||||
--
|
||||
%s
|
||||
|
||||
# --------------
|
||||
# Fin du fichier
|
||||
"""%(
|
||||
help_3lines,
|
||||
help_link_header,
|
||||
help_file_header,
|
||||
help_image_header,
|
||||
help_code_header,
|
||||
help_raw_header,
|
||||
help_abbr_header,
|
||||
help_anc_header,
|
||||
help_list,
|
||||
help_cite,
|
||||
help_image_writer,
|
||||
help_raw_writer,
|
||||
help_code_writer,
|
||||
help_link_writer,
|
||||
help_file_writer,
|
||||
help_words,
|
||||
help_abbr_writer,
|
||||
help_anc_writer,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: English website translation file
|
||||
# File: /var/lib/tyto/translations/site_en.py
|
||||
#
|
||||
# How to translate:
|
||||
# - create filename "site_xx.py" in /var/lib/tyto/translations/
|
||||
# where xx are 2 first lang letters (es, for spanish...)
|
||||
# - copy its contents and translate values
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# Note: python file
|
||||
|
||||
sidebar_title = "Featured posts"
|
||||
|
||||
home = "Home"
|
||||
directory = "Directory"
|
||||
sitemap = "Sitemap"
|
||||
toc = "Table of Contents"
|
||||
sitemap_gen = "%s generated by"
|
||||
sitemap_empty = "Nothing to show yet"
|
||||
posts_list = "Articles list"
|
||||
source_code = "Source code"
|
||||
permalink = "Permalink"
|
||||
|
||||
license = "License"
|
||||
license_title = "Website %s of"%license
|
||||
legals = "Legal Mentions"
|
||||
legals_title = "%s of"%legals
|
||||
terms = "Terms of Service"
|
||||
terms_title = "%s of"%terms
|
||||
bylaws = "Bylaws"
|
||||
bylaws_title = "%s of"%bylaws
|
||||
feed_rss = "RSS feed 2.0"
|
||||
generated_by = "Generated by"
|
||||
off_website = "Official website"
|
||||
about = "About"
|
||||
tyto_credit = "Website %s"%generated_by
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python3
|
||||
# Tyto - Littérateur
|
||||
|
||||
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>..
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# XMPP: echolib (im@echolib.re)
|
||||
#
|
||||
# Description: Fichier français de traduction des sites web
|
||||
# File: /var/lib/tyto/translations/site_fr.py
|
||||
#
|
||||
# Comment traduire :
|
||||
# - créer un fichier nommé "site_xx.py" dans /var/lib/tyto/translations/
|
||||
# oû xx sont les 2 première lettres de la langue (es, pour espagnol...)
|
||||
# - Copier ce contenu dedans, et traduire les variables
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# Note: Fichier python
|
||||
|
||||
sidebar_title = "Articles recommandés"
|
||||
|
||||
home = "Accueil"
|
||||
directory = "Dossier"
|
||||
sitemap = "Plan du site"
|
||||
toc = "Table des matières"
|
||||
sitemap_gen = "%s généré par"%sitemap
|
||||
sitemap_empty = "Rien à afficher pour le moment."
|
||||
posts_list = "Liste des articles"
|
||||
source_code = "Code source"
|
||||
permalink = "Permalien"
|
||||
|
||||
license = "Licence"
|
||||
license_title = "%s du site web de"%license
|
||||
legals = "Mentions légales"
|
||||
legals_title = "%s de"%legals
|
||||
terms = "C.G.U"
|
||||
terms_title = "%s de"%terms
|
||||
bylaws = "Statuts"
|
||||
bylaws_title = "%s de"%bylaws
|
||||
feed_rss = "Flux RSS 2.0"
|
||||
generated_by = "Géneré par"
|
||||
off_website = "Site web officiel"
|
||||
about = "À propos de"
|
||||
tyto_credit = "Site web %s"%generated_by
|
Loading…
Reference in New Issue