[0.10.5] - sitemap, bash-autocompletion...

This commit is contained in:
Cyrille L 2023-05-01 18:35:55 +02:00
parent 32acda6fab
commit 7d44eb781e
20 changed files with 964 additions and 300 deletions

2
debian/control vendored
View File

@ -1,5 +1,5 @@
Package: tyto
Version: 0.10.4
Version: 0.10.5
Section: custom
Priority: optional
Architecture: all

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3
# Version: 0.10.4
# Version: 0.10.5
# Tyto - Littérateur
#
# Copyright (C) 2023 Cyrille Louarn <echolib+tyto@a-lec.org>
@ -62,25 +62,27 @@ status.domain()
# Command start argument
import check, form, html, new, publish, show, wip, infos
import check, form, html, new, publish, show, wip, infos, creators
actions = {
'check' : check.manage,
'help' : infos.tyto,
'edit' : show.manage,
'edit-about' : show.manage,
'edit-db' : show.manage,
'edit-wip' : show.manage,
'edit-www' : show.manage,
'new' : new.manage,
'publish' : publish.manage_publish,
'show' : show.manage,
'show-about' : show.manage,
'show-db' : show.manage,
'show-wip' : show.manage,
'show-www' : show.manage,
'status' : status.check,
'template' : publish.manage_publish,
'wip' : wip.manage,
"check" : check.manage,
"create" : creators.manage,
"help" : infos.tyto,
"edit" : show.manage,
"edit-about" : show.manage,
"edit-db" : show.manage,
"edit-wip" : show.manage,
"edit-www" : show.manage,
"new" : new.manage,
"publish" : publish.manage,
"quick-pub" : publish.manage,
"show" : show.manage,
"show-about" : show.manage,
"show-db" : show.manage,
"show-wip" : show.manage,
"show-www" : show.manage,
"status" : status.check,
"template" : publish.manage,
"wip" : wip.manage,
}

View File

@ -0,0 +1,282 @@
#!/bin/bash
# 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 Affero General Public License
# as published by the Free Software Foundation, either version 3 of the
# License, or 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#----------------------------------------------------------------------
# XMPP: echolib (im@echolib.re)
#
# Description: Autocompletion commands
# File: /usr/share/bash-completion/completions/tyto
#----------------------------------------------------------------------
#=====================================================================#
# Actions section #
#=====================================================================#
# Actions: argument 1 #
#---------------------#
_tyto_actions() {
cat <<EOL
check
domains
edit
edit-about
edit-db
edit-wip
edit-www
help
new
show
show-about
show-db
show-wip
show-www
publish
quick-pub
status
version
wip
EOL
}
_tyto_actions_only() {
grep -F -q -x "$1" <<EOL
domains
help
version
EOL
}
# Actions for articles and modules
#--------------------------------
_tyto_actions_wp() {
grep -F -q -x "$1" <<EOL
publish
wip
EOL
}
# Actions for edit
#-----------------
_tyto_actions_edits() {
grep -F -q -x "$1" <<EOL
edit
edit-about
edit-db
edit-wip
edit-www
EOL
}
# Actions for show
#-----------------
_tyto_actions_shows() {
grep -F -q -x "$1" <<EOL
show
show-about
show-db
show-wip
show-www
EOL
}
#=====================================================================#
# Targets section #
#=====================================================================#
# Targets with wip or publish
#----------------------------
_tyto_targets_wp() {
cat <<EOL
added
again
footer
metas
navbar
sidebar
stats
template
updated
EOL
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
}
# Targets with quick-pub
#-----------------------
_tyto_targets_qp() {
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
}
# Targets with edit
#------------------
_tyto_targets_edits() {
cat <<EOL
domain
footer
metas
navbar
sidebar
EOL
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
}
# Targets with edit
#------------------
_tyto_targets_shows() {
cat <<EOL
domain
footer
metas
navbar
sidebar
stats
EOL
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
}
# Targets: argument 2 (all + .tyto files)
#----------------------------------------
_tyto_targets() {
cat <<EOL
added
again
domain
footer
metas
navbar
sidebar
stats
template
updated
EOL
find . -type f -name "*.tyto" -printf '%P\n' 2>/dev/null
}
# Targets: only with action "new"
#--------------------------------
_tyto_targets_new() {
cat <<EOL
domain
footer
metas
navbar
sidebar
EOL
}
#
#
_tyto_targets_not_options() {
grep -F -q -x "$1" <<EOL
added
again
domain
footer
metas
navbar
sidebar
stats
template
updated
EOL
}
#=====================================================================#
# Targets section #
#=====================================================================#
_tyto_options() {
cat <<EOL
--force
--static
EOL
}
#=====================================================================#
# Main autocompletion #
#=====================================================================#
_tyto_completions() {
local cur
cur="${COMP_WORDS[COMP_CWORD]}"
case $COMP_CWORD in
# Actions
1)
COMPREPLY=( $(compgen -W "$(_tyto_actions)" -- ${cur}) )
return 0
;;
# Targets
2)
local prev="${COMP_WORDS[COMP_CWORD-1]}"
# With action "new"
if [ "$prev" == "new" ];then
COMPREPLY=( $(compgen -W "$(_tyto_targets_new)" -- ${cur}) )
return 0
elif [ "$prev" == "quick-pub" ];then
COMPREPLY=( $(compgen -W "$(_tyto_targets_qp)" -- ${cur}) )
return 0
# With action "edit"
elif _tyto_actions_edits "$prev";then
COMPREPLY=( $(compgen -W "$(_tyto_targets_edits)" -- ${cur}) )
return 0
# With action "show"
elif _tyto_actions_shows "$prev";then
COMPREPLY=( $(compgen -W "$(_tyto_targets_shows)" -- ${cur}) )
return 0
# With wip/publish only
elif _tyto_actions_wp "$prev";then
COMPREPLY=( $(compgen -W "$(_tyto_targets_wp)" -- ${cur}) )
return 0
# When action is alone
elif ! _tyto_actions_only "$prev";then
COMPREPLY=( $(compgen -W "$(_tyto_targets)" -- ${cur}) )
return 0
fi
;;
# Optionss
3)
local prev1="${COMP_WORDS[COMP_CWORD-1]}"
local prev2="${COMP_WORDS[COMP_CWORD-2]}"
if [ "$prev2" == "wip" ];then
if ! _tyto_targets_not_options "$prev1";then
COMPREPLY=( $(compgen -W "$(_tyto_options)" -- ${cur}) )
return 0
fi
fi
;;
esac
}
complete -F _tyto_completions 'tyto'

View File

@ -1,16 +1,18 @@
# Changelog
Tyto - Littérateur
- Repository: https://git.a-lec.org/echolib/tyto
- Issues: https://git.a-lec.org/echolib/tyto/-/issues
- Changelog: https://git.a-lec.org/echolib/tyto/-/blob/main/CHANGELOG.md
- License: https://git.a-lec.org/echolib/tyto/-/blob/main/LICENSE
- Repository: https://git.a-lec.org/echolib/tyto-litterateur
- Issues: https://git.a-lec.org/echolib/tyto-litterateur/-/issues
- Changelog: https://git.a-lec.org/echolib/tyto-litterateur/-/blob/master/CHANGELOG.md
- License: https://git.a-lec.org/echolib/tyto-litterateur/-/blob/master/LICENSE
- Documentation: https://tyto.echolib.re
Tyto - Litterateur is a Libre project to create and manage multiple
websites from articles' files. Tyto uses its own syntax to convert
your articles in HTML5 static pages. Tyto works on a GNU/Linux system
and needs minimal dependancies.
- python3 rsync nano gawk curl
## [0.9.0] First Commit version (pre-final)
## {0.10.5]
- added sitemap with `tyto create sitemap`
- added escaped markers
- added bash-autocompletion (not yet all)
- updated help
- changed function to protect icodes
- very lots more
- pre 1.0

View File

@ -1,17 +1,48 @@
# Tyto
Pour obtenir de l'aide, taper juste la commande tyto
## Répertoire de code du projet Tyto
https://git.a-lec.org/echolib/tyto-litterateur
## Documentation officielle
https://tyto.echolib.re (en cours de construction)
## Démarrage "rapide"
````
mkdir -p MONDOMAIN
cd MONDOMAIN
tyto new domain URL
tyto new index
# À ce stade, voir la doc "écrire"
tyto edit index.tyto
tyto check index.tyto
tyto wip index.tyto
# Publier !
tyto publish template
tyto publish index.tyto
```
## Comment définir les métas
```
# Obligatoires uniques
# Ces marqueurs se configurent sur UNE ligne
title: Titre
about: Infos de l'article
author: Autheur
tags: mots-clé-1,mots-clé-2
author: Auteur
tags: mot-clé-1,mot 2,
date: YYYY-MM-DD (AAAA-MM-JJ)
# Optionnels myltiples
# Pour snpic, l'image doit être configurée avec le même Nom
# qu'un marqueur d'entête "image:"
# Utilise l'image précisée comme "avatar" dans les réseaux sociaux
# Et dans le flux RSS
snpic: Nom
# Optionnels multiples
# Ces marqueurs se configurent sur 3 lignes
link: Nom du lien
URL
Texte Alternatif
@ -24,13 +55,13 @@ file: Nom du lien
URL
Texte Alternatif
brut: Nom
raw: Nom
URI
Texte Alternatif
abbr: NOM (en majuscule)
Définition du NOM
nom (forme à afficher dans l'artile (optionnel))
abbr: abbrev
Définition de abbrev
ABBR (forme à afficher dans l'artile (optionnel))
# Séparateur d'au moins 5 "-" pour définir la fin
# des métadonnées d'entête de l'article
@ -38,14 +69,36 @@ abbr: NOM (en majuscule)
```
## Comment écrire un article
### Titre h1 à h6
### Écrire des titres
```
# Les titres HTML vont de 1 à 6 mais h1 est utilisé pour afficher
# le titre de l'article.
# Utiliser #N, où N est entre 1 et 5. (h+1 en HTML)
# Si du contenu existe entre les titres, une <div> est ajoutée
# Source
#1 Titre 1
((
Un paragraphe
))
Contenu 1
#2 Titre 2
#3 Titre 3
contenu 2
#4 Titre 4
```
### Balise div
```
<< CSS
((
1er paragraphes dans une balise div class="CSS"
))
((
2e paragraphes dans une balise div class="CSS"
))
>>
```
### Paragraphes
@ -74,94 +127,114 @@ def hello_world():
-)
```
### Citations
```
[[ CSS
_cite: autheur
_lang: langue
_link: lien
_year: année ou date YYYY-MM-DD
_book: référence
((
Citation placée dans un paragraphe
))
]]
[[ CSS
Citation simple sans référence
]]
```
### Ancres
```
# Source de l'ancre cible. "id" est son identité
-> id
((
un long paragraphe
))
((
>_id:Retourner au point d'ancre_<
))
# Source de l'ancre d'appel
# Définir l'identité cible et le texte du lien
>_id:Retourner au point d'ancre id_<
```
### Retour à la ligne HTML
```
| # <br />
# Source
|
# HTML
<br />
```
### Lien vers URL
```
# Placer "_" devant le Nom du lien
Voir ce _Nom du lien # Ouverture même fenêtre
Voir ce _Nom du lien+ # ouverture nouvelle fenêtre
```
### Lien vers fichier
```
# Placer "__" devant le Nom du lien
Voir ce __Nom du lien # Ouverture même fenêtre
Voir ce __Nom du lien+ # ouverture nouvelle fenêtre
```
Note:
Vous pouvez avoir un NAME identique pour file: et link:
Vous pouvez avoir un Nom identique pour les marqueurs `file:` et `link:`
### Gras, Strong, italique...
```
*_très gras_* # <strong>
+_gras léger_+ # <b>
/_en italique_/ # <em>
[_en italique_] # <i>
;_en italique_; # <em>
:_en italique_: # <i>
~_texte barré_~ # <del>
{_Code_} # <code>
:_Citation rapide_: # <cite>
[_Citation rapide_] # <cite>
%_Classe personnalisée_% >>> <span class="custom">
._Souligné_. # <u>
{_Code_} # <code>
# Montrer comment écrire du code dans Tyto:
# Bypass avec \ devant {_ et _} (idem pour les marqueurs précédents)
{_\{_Comme ça\_}_}
```
### Abréviations
```
# ! NOM sera remplacé par "nom" dans la page si défini en entête
# sinon, NOM sera conservé
# Toujours écrire en majuscule les ABBR dans l'article brut
# <abbr title="Définition du NOM">nom</abbr>
Avec ce NOM.
# abbrev sera remplacé par "ABBR" dans la page si défini en entête
# sinon, abbrev sera conservé
# - Toujours écrire dans l'article :
# - entre parenthèses ET majuscules les "(ABBREV)"
Avec cette (ABBREV).
# HTML: <abbr title="Définition de abbrev">ABBR</abbr>
```
### Images
```
# Chaque image doit être placée en début de ligne
# Placer dans un paragraphe pour chaque ou après "|",
# Placer dans un paragraphe pour chacune ou après "|",
# sinon, affichage les une à côté des autres
# ! Si pas d'unité pour w= et h= : défaut "px"
_image:Nom
_image:Nom c=CSS
_image:Nom c=css w=1080
_image:Nom w=640em h=480em
_image:Nom t=+ # Rend l'image interne cliquable
_image:Nom t=https://...# Donne un lien à l'image
_image:Nom c=CSS t=https://... w=320px h=240
_image:Nom t=https://...# Donne un lien web à l'image
_image:Nom c=CSS t=https://... w=320px h=240 # 240px
```
### Code Brut depuis un fichier
### Code brut depuis un fichier
```
_brut:NOM
_raw:Nom
```
### Citations
Possibilité dans toute citation d'utiliser les marqueurs
optionnels `_xxx:`. Pour la date, utilisez le FORMAT INTERNATIONAL
```
# Source: citation complète
[[ CSS_TEST
_cite: echolib
_date: 2022-12-28 (format AAAA ou AAAA-MM ou AAAA-MM-JJ)
_lang: fr
_link: https://tyto.echolib.re
_book: Référence
((
Une belle citation complète
))
]]
````
```
# Source: citation basique
[[
Une citation simple, et sans paragraphe
]]
```

View File

@ -3,12 +3,13 @@
* DOMAIN MUST be changed by domain css set in configuration
*/
/*
/*=====================================================================
* Header
*/
header#header_page {
}
/* Block */
div#site_logo {
}
@ -18,6 +19,7 @@ a#site_logo_link {
img#site_logo_image {
}
/* Block */
div#site_infos {
}
@ -31,7 +33,7 @@ p#site_about {
}
/*
/*=====================================================================
* navbar
*/
nav#site_menu {
@ -46,7 +48,8 @@ li.site_menu_item {
a.site_menu_link {
}
/*
/*=====================================================================
* article
*/
article#article_main {
@ -69,14 +72,14 @@ h6.title_6 {
/* Between every <h3-6> IF CONTENTS */
div.contents {
}
div.contents_2 {
}
div.contents_3 {
}
div.contents_4 {
}
div.contents_5 {
}
div.contents_6 {
}
/* Default if not set in post */
p.DOMAIN {
@ -90,6 +93,10 @@ a.link {
a.link-file {
}
/* When block quote with _cite:*/
a.figc {
}
a.anchor_link {
}
@ -99,31 +106,32 @@ abbr.DOMAIN {
img.DOMAIN_image {
}
code.icode {
}
ul.DOMAIN {
}
li.DOMAIN
li.DOMAIN {
}
strong.strong {
/* Words tags*/
code.icode {
}
b.bold {
strong.DOMAIN {
}
em.em{
b.DOMAIN {
}
i.italic {
em.DOMAIN{
}
del.del {
i.DOMAIN {
}
u.underline {
del.DOMAIN {
}
cite.cite {
u.DOMAIN {
}
cite.DOMAIN {
}
span.custom {
}
/* Block_code */
/* Block-code */
code.DOMAIN {
}
pre.bcode {
@ -143,7 +151,13 @@ span#article_code {
a#article_code_link {
}
/*
/* Sitemap */
ul.sitemap {
}
/*=====================================================================
* sidebar
*/
@ -163,7 +177,7 @@ p.sidebar_item_about {
}
/*
/*=====================================================================
* footer
*/
footer#footer_page {
@ -198,5 +212,3 @@ p.footer_copyright {
}
p.footer_generator {
}

View File

@ -43,14 +43,14 @@ import infos
actions = \
(
'check',
'create',
'edit',
'edit-about',
'edit-db',
'edit-wip',
'edit-www',
'quick-pub',
'new',
'show',
'show-about',
'show-db',
'show-wip',
'show-www',
@ -59,9 +59,10 @@ actions = \
'publish'
)
option = \
options = \
(
'--static',
'--force',
)
pass_actions = ('new')
@ -75,6 +76,7 @@ pass_db = \
'edit-wip',
'edit-www',
'publish',
'quick-pub',
'show',
'show-about',
'show-db',
@ -94,6 +96,7 @@ pass_targets = \
'metas',
'navbar',
'sidebar',
'sitemap',
'stats',
'template'
)
@ -123,6 +126,8 @@ helps = \
try: action = sys.argv[1]
except: action = ''
act_err = False
# With no argument, show help
if not action:
infos.tyto('full')
@ -132,10 +137,7 @@ elif action in helps:
infos.tyto(action)
# Unused argument [action]
elif action in actions:
act_err = False
else:
elif not action in actions:
act_err = True
@ -147,7 +149,7 @@ except:
infos.tyto('full')
sys.exit(0)
# option
# options
try: option = sys.argv[3]
except: option = ''

View File

@ -68,7 +68,9 @@ def manage(target):
logs.out("1", db.uri_file, True)
# Already check
elif db.exists and not db.old_chk:
elif db.exists \
and not db.old_chk \
and not args.option == "--force":
print(' ├ [%s] > %s'%(db.title, db.uri_file))
logs.out("20", '%s > %s'%(db.date_chk, db.uri_file), False)
answer = form.asking('%s%s '%(
@ -235,9 +237,10 @@ def check_process(target):
post_bottom = tyto.protect_article
# Protect inline-codes
if icode:
tyto.protect_icodes(post_bottom)
post_bottom = tyto.protect_article
if icode: post_bottom = tyto.protect_icodes(post_bottom)
# Replace escaped markers
post_bottom = tyto.protect_escaped(post_bottom, False)
# Check header tags configurations
@ -294,6 +297,7 @@ def file_to_string():
for line in article.rsplit('\n'):
if line.startswith(logs.shebang):
print('')
logs.out("82", db.uri_file, False)
post_err = True
return
@ -313,6 +317,7 @@ def file_to_string():
# Check if separator or exit
if not sep:
print('')
logs.out("6", '"-----" > %s'%db.uri_file, False)
post_err = True
return
@ -402,14 +407,14 @@ def if_icodes_bcodes_quotes(post_bottom):
fcodes += 1
# icodes
elif tyto.words_tags[8][0] or tyto.words_tags[8][1] in line:
elif tyto.icode_tags[0] in line or tyto.icode_tags[1] in line:
icode_m1 = icode_m2 = 0
icode_m1 = line.count(tyto.words_tags[8][0])
icode_m2 = line.count(tyto.words_tags[8][1])
icode_m1 = line.count(tyto.icode_tags[0])
icode_m2 = line.count(tyto.icode_tags[1])
if icode_m1 != icode_m2:
logs.out("8", 'L=%s. icode "%s" + "%s" > %s'%(
ln + 1 + ln_header,
tyto.words_tags[8][0], tyto.words_tags[8][1],
tyto.icode_tags[0], tyto.icode_tags[1],
db.uri_file
), False
)
@ -424,23 +429,30 @@ def if_icodes_bcodes_quotes(post_bottom):
#-----------------------------------------#
def check_needed_tags(post_header):
global post_err
global title, author, about, tags, date
global title, author, about, tags, date, sitemap
global stat_tags
title = author = about = tags = ''
sitemap = "True"
date = ()
stat_tags = 0
# Check post header for each needed tags
for tag in tyto.needed_header_tags:
for ln, line in enumerate(post_header, 1):
# Sitemap : set to False if #NoSitemap
if line.startswith("# NoSitemap"):
sitemap = "False"
# Break if already set
if globals()[tag]: break
if globals()[tag]:
break
# Set data from tag
if line.startswith('%s:'%tag):
globals()[tag] = line.rsplit('%s:'%tag)[1].lstrip()
globals()[tag] = tyto.convert_altname(globals()[tag])
# Stat for "tags:"
if tag == 'tags':
stat_tags = len(globals()[tag].strip().split(","))
@ -451,8 +463,6 @@ def check_needed_tags(post_header):
logs.out("38", '%s:'%tag, False)
post_err = True
# Check date format
# Set french format in post DB
if not post_err:
@ -1006,6 +1016,7 @@ def create_database():
'meta_tags = "%s"\n'%tags + \
'date = "%s"\n'%date_tr + \
'snpic = "%s"\n'%snpic_url + \
'sitemap = %s\n'%sitemap + \
'\n# Post Configurations\n' + \
'post_id = "%s"\n'%db.uri_id + \
'post_src = "%s"\n'%db.uri_file + \

View File

@ -0,0 +1,185 @@
#!/usr/bin/env python3
# Tyto - Littérateur
#
# Copyright (C) 2023 Cyrille Louarn <echolib@dismail.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation, either version 3 of the
# License, or 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#----------------------------------------------------------------------
# XMPP: echolib (im@echolib.re)
#
# Description: Manage 'creators' argument.
# Create articles
# File: /var/lib/tyto/program/creators.py
#----------------------------------------------------------------------
#------------
# funny stats
#------------
# lines:
# functions:
# comments:
#----------------------------------------------------------------------
#**********************************************************************
import os, importlib, datetime, subprocess
import args, dom, db, langs, tyto, check, wip, logs
#========================#
# Manage action [create] #
#------------------------#
def manage(target):
creators = {
"sitemap" : create_sitemap,
}
try:
creators[target](target)
except:
logs.out("28", "%s + %s"%(args.action, args.target), True)
#=====================#
# Set and return date #
#---------------------#
def nowdate():
now = datetime.datetime.now()
return(now.strftime('%Y-%m-%d'))
#============================#
# Create sitemap.tyto file #
# Then check it, and wip it #
# ! sitemap is the "www" one #
# seen in 'wip' server #
#----------------------------#
def create_sitemap(target):
dom.valid()
# Define sitemap.tyto
sitemap_tyto = \
'# %s Tyto - Littérateur [tyto create sitemap]\n'%langs.site.sitemap_gen + \
'# NoSitemap\n' + \
'title: %s (%s %s)\n'%(langs.site.sitemap_t, '%s', langs.site.links) + \
'about: %s Tyto - Littérateur\n'%langs.site.sitemap_gen + \
'author: Tyto\n' + \
'tags: sitemap\n' + \
'date: %s\n'%nowdate() + \
'\n' + \
'%s\n' + \
'-----\n' + \
'\n' + \
'%s\n' + \
'-)'
print(sitemap_tyto)
tab = 8
uri_dir_set = ""
links = ""
contents = "#1 /\n-( sitemap"
# Not real articles folder
forbid_dir = (
dom.files_d,
dom.images_d,
dom.modules_d
)
# Get all .tyto files from domain
nbr_files = 0
for r, dirs, files in os.walk(os.getcwd()):
if r.startswith(forbid_dir):
continue
for f in files:
if f.endswith(".tyto"):
try:
uri_file = r.rsplit(dom.articles_d)[1]
uri_file = os.path.join(uri_file,f)
except:
uri_file = f
uri_dir = uri_file.rsplit(f)[0]
if not uri_dir:
uri_dir = "~/"
# Try to load Article Database
args.action = "check"
args.target = uri_file
importlib.reload(db)
if not db.exists:
continue
else:
try:
db.hash_www
db.sitemap
if not db.sitemap:
continue
except:
continue
# Count
nbr_files += 1
# create defined link
if not links:
links = \
"link: %s\n%s%s\n%s%s\n"%(
db.title, tab * " ", db.short_srv, tab * " ", db.about
)
else:
links = \
"%s\nlink: %s\n%s%s\n%s%s\n"%(
links,
db.title, tab * " ",
db.short_srv, tab * " ", db.about
)
# Create list link line
if not uri_dir.startswith(uri_dir_set):
root_dir = uri_dir.rsplit("/")[0]
contents = "%s\n-)\n\n#1 %s\n-( sitemap"%(contents, root_dir)
uri_dir_set = uri_dir.rsplit("/")[0]
uls = uri_dir.count("/")
contents = \
"%s\n%s [%s] _%s (%s)"%(
contents,
uls * "=", db.date, db.title, db.author
)
sitemap_tyto = \
sitemap_tyto%(
nbr_files,
links,
contents
)
sitemap_file = "%ssitemap.tyto"%dom.articles_d
tyto.set_file(sitemap_file, "New", sitemap_tyto)
# Check and wip
www = subprocess.run(
[
'/usr/bin/tyto',
'wip',
'sitemap.tyto',
'--force'
],
)

View File

@ -104,6 +104,7 @@ if args.target \
'meta_tags',
'date',
'snpic',
'sitemap',
'uris',
'uniq_anchors',
'uniq_abbrs',

View File

@ -77,7 +77,6 @@ dom_values = \
'sidebar_f',
'metas_f',
'footer_f',
'footer_about_f',
'shortname',
'www_url',
'wip_url',
@ -138,7 +137,6 @@ create_files = \
'sidebar_f',
'metas_f',
'footer_f',
'footer_about_f'
)
wip_html_mods = ()
@ -241,7 +239,6 @@ if not hole:
eval(str('footer_f')),
eval(str('wip_footer_f')),
eval(str('www_footer_f')),
eval(str('footer_about_f'))
)
templates = \
@ -312,3 +309,4 @@ if not hole:
def valid():
if incomplete: sys.exit(41)
elif not active: sys.exit(42)
elif not ready: sys.exit(41)

View File

@ -207,7 +207,6 @@ def create_domain(target):
'sidebar_f = "%styto.sidebar"\n'%modules_dir + \
'metas_f = "%styto.metas.html"\n'%modules_dir + \
'footer_f = "%styto.footer.html"\n'%modules_dir + \
'footer_about_f = "%s"\n'%footer_about_f + \
'\n# Domain\n' + \
'shortname = "%s"\n'%shortname + \
'www_url = "%s"\n'%www_url + \
@ -679,7 +678,7 @@ def create_domain(target):
#----------------
tyto.set_file(dom.config, False, '\nactivated = True')
# RELoad config
# ReLoad config
#--------------
importlib.reload(dom)
@ -718,15 +717,6 @@ def create_domain(target):
html.create_navbar('new')
html.create_sidebar('new')
html.create_user_footer('new')
create_footer_about('new')
'''
create_metas('form')
create_navbar('form')
create_sidebar('form')
create_footer('form')
create_footer_about('form')
'''
print(langs.site.form_ready)
@ -941,7 +931,6 @@ def create_footer(option):
if not dom.ready: dom.valid()
print('\n%s'%langs.site.footer_inf)
create_footer_about(option)
if option != "new": return
# Default footer contents
@ -968,18 +957,7 @@ def create_footer(option):
'%stitle="%s"\n'%(9 * ' ', langs.site.go_home) + \
'%sclass="footer_title_link">%s</a>'%(9 * ' ', dom.title)
# Insert content of footer_about_f or default if not exists
footer_about = ''
if tyto.exists(dom.footer_about_f):
footer_custom = open(dom.footer_about_f).read()
for line in footer_custom.rsplit('\n'):
if not line or line.startswith('#'):
continue
line = '%s%s'%(6 * ' ', line)
if footer_about: footer_about = '%s\n%s'%(footer_about, line)
else: footer_about = line
else:
# Insert content of fabout domain
footer_about = "<p>%s</p>"%dom.about
# License URL. Set to homepage if unknown
@ -1106,26 +1084,3 @@ def create_footer(option):
tyto.set_file(dom.footer_f, 'New', footer)
# Generic HTML list in footer
"""
' <li class="footer_item">\n' + \
' <a href="%s"\n'% + \
' title="%s"\n'% + \
' class="footer_item_link">%s</a> %s\n'%() + \
' </li>\n'
"""
#========================================#
# Create custom about section for footer #
#----------------------------------------#
def create_footer_about(option):
if not tyto.exists(dom.footer_about_f):
set_f = '%s\n'%langs.site.footer_about_doc%(tyto.Tyto,
dom.footer_about_f
) + \
'<p id="footer_about">%s</p>'%dom.about
tyto.set_file(dom.footer_about_f, 'New', set_f)

View File

@ -241,7 +241,7 @@ def create_html_time_meta(process):
' <span id="article_pub"\n' + \
' title="[%s] %s %s (%s)">%s</span>\n'%(
db.title, langs.site.w_published, date_pub, time_pub,
date_pub
db.date
) + \
' </time>\n' + \
'<!--/Tyto_Published-->'

View File

@ -68,8 +68,9 @@ def manage(target):
if args.target.endswith(".tyto"):
args.target = args.target.replace(".tyto", '')
u = unidecode(args.target, "utf-8")
args.target = unidecode(u)
# In case needed (todo later)
# u = unidecode(args.target, "utf-8")
# args.target = unidecode(u)
filepost = "%s%s.tyto"%(dom.articles_d, args.target)
if tyto.exists(filepost):

View File

@ -35,20 +35,37 @@
import os, sys, shutil, importlib
from pathlib import Path
import logs, args, dom, db, wip, html, tyto, form, stats, rss, langs
import logs, args, dom, db, wip, html, tyto, form, stats, rss, langs, check
#==============================#
# Manage action, get post db #
# check if publish can be done #
#------------------------------#
def manage_publish(target):
def manage(target):
dom.valid()
# Specific QUICK processes: check > wip > publish
if args.action == "quick-pub":
try:
db.uri_file
except:
logs.out("28", "%s + %s"%(args.action, args.target), True)
print(" ! Quick Publish")
check.check_process(target)
importlib.reload(db)
wip.wip_article(db.uri_file)
importlib.reload(db)
check_to_publish('one')
publish_article()
rss.create_feed()
return
# Target is footer, sidebar, navbar, metas
# template: create/copy template/ files
# all: publish all wip article
#-----------------------------------------
if target in args.pass_targets:
elif target in args.pass_targets:
do = {
'updated' : publish_all,
'again' : publish_all,
@ -64,6 +81,7 @@ def manage_publish(target):
do[target]('www')
return
# Database must exists...
if not target: logs.out("5", '', True)
if not db.post: logs.out("1", db.uri_file, True)

View File

@ -108,8 +108,6 @@ def manage(target):
"post" : 'src',
"show-db" : 'db',
"edit-db" : 'db',
"show-about" : 'about',
"edit-about" : 'about',
"show-wip" : 'wip',
"edit-wip" : 'wip',
"show-www" : 'www',
@ -136,14 +134,6 @@ def manage(target):
"sidebar" : dom.sidebar_f,
"post" : post_db
},
'about' : {
"domain" : dom.config,
"footer" : dom.footer_about_f,
"metas" : dom.metas_f,
"navbar" : dom.navbar_f,
"sidebar" : dom.sidebar_f,
"post" : post_db
},
'wip' : {
"domain" : dom.config,
"footer" : dom.wip_footer_f,

View File

@ -106,37 +106,37 @@ headers = \
words_tags = [
(
'*_', '_*',
'<strong class="strong">', '</strong>',
'<strong class="%s">'%dom.css, '</strong>',
'strongs'
),
(
'+_', '_+',
'<b class="bold">', '</b>',
'<b class="%s">'%dom.css, '</b>',
'bolds'
),
(
';_', '_;',
'<em class="em">', '</em>',
'<em class="%s">'%dom.css, '</em>',
'emphasis'
),
(
':_', '_:',
'<i class="italic">', '</i>',
'<i class="%s">'%dom.css, '</i>',
'italics'
),
(
'~_', '_~',
'<del class="del">', '</del>',
'<del class="%s">'%dom.css, '</del>',
'dels'
),
(
'._', '_.', '<u class="underline">',
'._', '_.', '<u class="%s">'%dom.css,
'</u>',
'underlines'
),
(
'[_', '_]',
'<cite class="cite">', '</cite>',
'<cite class="%s">'%dom.css, '</cite>',
'cites'
),
(
@ -144,12 +144,93 @@ words_tags = [
'<span class="custom">', '</span>',
'customs'
),
]
icode_tags = \
(
'{_', '_}',
'<code class="icode">', '</code>',
'codes'
),
]
'icodes',
'\\{_', '\\_}'
)
strong_tags = \
(
'*_', '_*',
'<strong class="%s">'%dom.css, '</strong>',
'strongs',
'\\*_', '\\_*',
'-S1-', '-S2-'
)
bold_tags = \
(
'+_', '_+',
'<b class="%s">'%dom.css, '</b>',
'bolds',
'\\+_', '\\_+',
'-B1-', '-B2-'
)
em_tags = \
(
';_', '_;',
'<em class="%s">'%dom.css, '</em>',
'emphasis',
'\\;_', '\\_;',
'-EM1-', '-EM2-'
)
i_tags = \
(
':_', '_:',
'<i class="%s">'%dom.css, '</i>',
'italics',
'\\:_', '\\_:',
'-I1-', '-I2-'
)
u_tags = \
(
'._', '_.', '<u class="%s">'%dom.css,
'</u>',
'underlines',
'\\._', '\\_.',
'-U1-', '-U2-'
)
del_tags = \
(
'~_', '_~',
'<del class="%s">'%dom.css, '</del>',
'dels',
'\\~_', '\\_~',
'-DE1-', '-DE2-'
)
cite_tags = \
(
'[_', '_]',
'<cite class="%s">'%dom.css, '</cite>',
'cites',
'\\[_', '\\_]',
'-CI1-', '-CI2-'
)
custom1_tags = \
(
'%_', '_%',
'<span class="custom">', '</span>',
'customs',
'\\%_', '\\_%',
'-CU1-', '-CU2-'
)
markers_tags = \
[
strong_tags,
bold_tags,
em_tags,
i_tags,
u_tags,
del_tags,
cite_tags,
custom1_tags,
]
# At begining line, create block contents
block_tags = [
@ -280,6 +361,48 @@ date: %s
nbr_icodes = 0
#==============================#
# Replace escaped markers #
# check: with "" #
# wip: with altternate #
# (recover when wip done) #
#------------------------------#
def protect_escaped(post_bottom, reverse):
for m1, m2, h1, h2, n, e1, e2, r1, r2 in markers_tags:
# In check mode, No need to keep escaped markers
if args.action == "check":
r1 = r2 = ''
if reverse:
post_bottom = post_bottom.replace(r1, m1)
post_bottom = post_bottom.replace(r2, m2)
else:
post_bottom = post_bottom.replace(e1, r1)
post_bottom = post_bottom.replace(e2, r2)
return post_bottom
# -- tests
def find_between( s, first, last ):
try:
start = s.index( first ) + len( first )
end = s.index( last, start )
return s[start:end]
except ValueError:
return ""
def find_between_r( s, first, last ):
try:
start = s.rindex( first ) + len( first )
end = s.rindex( last, start )
return s[start:end]
except ValueError:
return ""
# -- tests
#=======#
# TOOLS #
#=======#--------------------------------------------------------------
@ -478,56 +601,70 @@ def protect_bcodes_quotes(process, post_bottom):
if close_quote: quote = b64_quote = ''
#=======================#
#=======================================#
# Protec iCodes #
# Used in check and wip #
#-----------------------~
# Methode: iterate (c)haracter in lines #
# check: remove icdoe #
# wip: convert to b64 #
#---------------------------------------#
def protect_icodes(post_bottom):
global protect_article
global nbr_icodes
protect_article = post_bottom
in_icode = False
src_code = rep_code = ''
# Get only lines that contains code
in_icode = ok_icode = go_icode = False
for ln, line in enumerate(post_bottom.rsplit('\n')):
if not words_tags[8][0] in line: continue
if not "{_" in line or not "_}" in line:
continue
# Iterate (c)haracter in line
code = ""
for i, c in enumerate(line):
c_b = c_bb = c_a = ""
if c == '_':
c_b = line[i-1] # before
c_bb = line[i-2] # before, before
c_a = line[i+1] # after
# incode if
if c_b == '{' and not c_bb == '\\':
if c == "_":
try:
if line[i-1] == "{" and line[i-2] != "\\":
in_icode = True
nbr_icodes += 1
code = words_tags[8][2]
continue
# No more in code if
if c_a == '}' and not c_b == '\\':
ok_icode = False
go_icode = True
elif line[i+1] == "}" and line[i-2] != "\\":
in_icode = False
src_code = convert_altname(src_code)
code = '%s%s%s'%(code, src_code, words_tags[8][3])
b64_code = b64('Encode', code, 'I64.', '.I64')
rep_code = "%s%s%s"%(
words_tags[8][0], rep_code, words_tags[8][1]
)
protect_article = protect_article.replace(rep_code, b64_code)
src_code = rep_code = b64_code = ''
ok_icode = True
go_icode = False
except:
continue
if go_icode :
go_icode = False
continue
# Construct original replacement code and source code
if in_icode:
rep_code = '%s%s'%(rep_code, c)
if c == '\\': continue
src_code = '%s%s'%(src_code, c)
ok_icode = False
code = "%s%s"%(code, c)
# End icode
if ok_icode:
nbr_icodes += 1
tyto_code = "%s%s%s"%(icode_tags[0], code, icode_tags[1])
if args.action == "check":
post_bottom = \
post_bottom = post_bottom.replace(tyto_code , '')
elif args.action == "wip":
code = convert_altname(code)
html_code = "%s%s%s"%(
icode_tags[2], code, icode_tags[3])
b64_code = b64('Encode', html_code, 'I64.', '.I64')
post_bottom = post_bottom.replace(tyto_code, b64_code)
# Reset for next
code = tyto_code = html_code = b64_code = ""
ok_icode = False
post_bottom = post_bottom.replace("\\%s"%icode_tags[0], icode_tags[0])
post_bottom = post_bottom.replace("\\%s"%icode_tags[1], icode_tags[1])
return post_bottom
#=====================================#

View File

@ -38,7 +38,7 @@
import os, re, sys, locale, shutil, importlib, time
from pathlib import Path
import args, logs, langs, dom, db, tyto, html, form, stats
import args, logs, langs, dom, db, tyto, html, form, stats, check
#=========================================#
@ -49,11 +49,20 @@ def manage(target):
global post_db, hash_post, target_all
# wip_article(db.post_src) ; return # Force wip without checking
if not target:
logs.out("5", '[target]', True)
# option --force to check and wip processes
if args.option == '--force':
if args.target in args.pass_targets:
logs.out("28", "%s + %s"%(args.target, args.option), True)
check.manage(target)
#importlib.reload(db)
wip_article(target)
return
# Modules and multi-articles
elif target in args.pass_targets:
do = {
'updated' : wip_all,
@ -156,9 +165,10 @@ def wip_article(target):
# Protect inline-codes
if db.icodes > 0:
tyto.protect_icodes(post_bottom)
post_bottom = tyto.protect_article
post_bottom = tyto.protect_icodes(post_bottom)
# Replace escaped markers
post_bottom = tyto.protect_escaped(post_bottom, False)
# Convert contents from modules
wip_clean_lines() # Remove comments and empty lines
@ -170,6 +180,9 @@ def wip_article(target):
wip_titles() # Convert #N, remove empty line, add divs
wip_lists() # convert ul/ol lists
wip_quotes() # Quotes. Decode base64 Q64 and convert to HTML
# Replace escaped markers
post_bottom = tyto.protect_escaped(post_bottom, True)
wip_icodes() # inline_codes. Decode base64 icode and replace
wip_filecode(target) # Read file and convert to HTML
wip_bcodes() # Block-codes. Decode B64 and convert to HTML

View File

@ -20,6 +20,7 @@
# Generic
article = "Article"
links = "links"
sidebar = 'Sidebar'
navbar = 'Navbar'
metas = 'Metas Tags'
@ -88,7 +89,9 @@ rss_c = "Create ATOM/RSS feed"
# Other
uptpl = "Update directory"
stats_f = "Articles: %s (%s words)"
reg_domains = 'Registred domains'
reg_domains = "Registred domains"
sitemap_gen = "Sitemap generated by"
sitemap_t = "Sitemap"
# Form
#----------------------------------------------------------------------
@ -237,19 +240,6 @@ footer_doc = \
'# - Do NOT copy to template directory'
'# %s\n'%(20 * "-")
footer_about_doc = \
'# For %s\n' + \
'# Type text/HTML file\n' + \
'# Description Used when a footer is generated\n' + \
'# Content inserted in "about" section\n' + \
'# File %s\n' + \
'# How Put any HTML code\n' + \
'# Notes - Lines are ignored if:\n' + \
'# - empty\n' + \
'# - begin with "#"\n' + \
'# - Do NOT copy to template directory\n' + \
'# %s\n'%(20 * "-")
# Help with Tyto commands
args_helps = """\n# New domain :
- Create directory and go in
@ -261,13 +251,12 @@ args_helps = """\n# New domain :
- (css, logo...) files go in "wip/template/"
# Usage: tyto [action] [target]
# Actions
- [action] > withour [target]
# [action] > withour [target]
version : Show installed version
domains : Show installed domains
help : Show commands help
- [action] > According to [target]
# [action] > According to [target]
# Edit a file
edit : Source file, configuration module
edit-about: [footer] Edit description section in footer
@ -292,9 +281,9 @@ args_helps = """\n# New domain :
check : Check the validity of a tyto format file
wip : Create article HTML page in server 'wip'
publish : Create article HTML page in server 'www'
quick-pub : Do check, wip, publish ([file] only)
# Targets
- [target] > According to [action]
# [target] > According to [action]
# Multiple articles
updated : Update articles (already checked)
again : Force all articles (already checked)
@ -316,7 +305,11 @@ args_helps = """\n# New domain :
metas : <meta>, <link> configuration file
navbar : Navbar configuration file
sidebar : Sidebar configuration file
stats : Stats file (server 'wip' er 'www')"""
stats : Stats file (server 'wip' er 'www')
# [option] :
--static : Créer une page HTML entièrement statique
--force : Avec [wip], vérifier l'article et créer la page HTML"""
ex_helps = """# Examples :
# Check article (according to sub-folder)

View File

@ -20,6 +20,7 @@
# Generic
article = "Article"
links = "liens"
sidebar = 'Barre Latérale'
navbar = 'Barre de menu'
metas = 'Balises Metas'
@ -88,7 +89,9 @@ rss_c = "Créer le flux ATOM/RSS"
# Autre
uptpl = "Mettre à jour le dossier"
stats_f = "Articles : %s (%s mots)"
reg_domains = 'Domaines enregistrés'
reg_domains = "Domaines enregistrés"
sitemap_gen = "Plan du site (sitemap) généré par"
sitemap_t = "Plan du site"
# Formulaire
#----------------------------------------------------------------------
@ -237,19 +240,6 @@ footer_doc = \
'# - Ne PAS copier ce fichier dans le dossier template\n' + \
'# %s\n'%(20 * "-")
footer_about_doc = \
'# Pour %s\n' + \
'# Type Fichier text/HTML\n' + \
'# Description Utilisé lors de la génération du pied de page\n' + \
'# Contenu inséré dans la section "about"\n' + \
'# Fichier %s\n' + \
'# Comment Insérer du code HTML\n' + \
'# Notes - Les lignes sont ignorées si :\n' + \
'# - vides\n' + \
'# - commencent par "#"\n' + \
'# - Ne PAS copier ce fichier dans le dossier template\n' + \
'# %s\n'%(20 * "-")
# Help with Tyto commands
args_helps = """\n# Nouveau domaine :
- Créer un dossier et aller dedans
@ -261,17 +251,14 @@ args_helps = """\n# Nouveau domaine :
- Les fichier (css, logo...) vont dans le dossier serveur "wip/template/"
# Usage: tyto [action] [target]
# Les actions
- [action] > Sans [target]
# [action] > Sans [target]
version : Montre la version installée
domains : Montre les domains installés
help : Montre l'aide des commandes
- [action] > Selon l'argument [target]
# [action] > Selon l'argument [target]
# Modifier un ficher
edit : Fichier source, module de configuration
edit-about: [footer] Modifier la section description du pied de page
sinon comme l'action [edit-db]
edit-db : Modifier une base de données/fichier de configuration
edit-wip : Modifier un fichier dans le serveur 'wip'
edit_www : Modifier un fichier dans le serveur 'www'
@ -283,8 +270,6 @@ args_helps = """\n# Nouveau domaine :
# Afficher un fichier (avec numéros de ligne)
show : Fichier source, module de configuration
show-about: [footer] Afficher la section description du pied de page
sinon comme l'action [show-db]
show-db : Afficher une base de données/fichier de configuration
show-wip : Afficher un fichier dans le serveur 'wip'
show-www : Afficher un fichier dans le serveur 'www'
@ -293,9 +278,9 @@ args_helps = """\n# Nouveau domaine :
check : Vérifier la validité d'un article au format tyto
wip : Créer une page HTML de l'article dans le serveur 'wip'
publish : Créer une page HTML de l'article dans le serveur 'www'
quick-pub : Faire check, wip, publish ([file] seulement)
# Les cibles
- [target] > Selon l'action [action]
# [target] > Selon l'action [action]
# Traitement en masse
updated : Mise à jour des articles modifiés (déjà vérifiés)
again : Forcer TOUS les articles déjà vérifiés
@ -317,7 +302,11 @@ args_helps = """\n# Nouveau domaine :
metas : Fichier de configuration des balises HTML <meta>, <link>
navbar : Fichier de configuration du menu de navigation
sidebar : Fichier de configuration de la barre latérale
stats : Fichier de statistiques (serveur 'wip' ou 'www')"""
stats : Fichier de statistiques (serveur 'wip' ou 'www')
# [option]
--static : Créer une page HTML entièrement statique
--force : Avec [wip], vérifier l'article et créer la page HTML"""
ex_helps = """# Exemples :
# Vérifier l'article dans le sous dossier (suivant l'emplacement)