This commit is contained in:
Cyrille L 2023-11-23 18:51:19 +01:00
parent cfb564eb23
commit 03960f733b
35 changed files with 796 additions and 122 deletions

View File

@ -10,6 +10,22 @@ Tyto - Littérateur
# CURRENTLY IN DEV (in devel branch) ! # 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] ## [1.9.38]
- Moved: HTML footer in div site_container - Moved: HTML footer in div site_container
- fix: main title in HTML page h1 - fix: main title in HTML page h1

View File

@ -216,7 +216,7 @@ abbr: css
#2 Une liste mixée {_<ol>, <ul>_} #2 Une liste mixée {_<ol>, <ul>_}
(( ((
<: mylist <: mylist
+ numeric o: item 1 + numeric ol item 1
++ numeric ol sub-Item 1 ++ numeric ol sub-Item 1
+++ numeric ol sub-sub-item 1 +++ numeric ol sub-sub-item 1
==== ul item >_top: Go to Top_< ==== ul item >_top: Go to Top_<
@ -325,7 +325,7 @@ Here, i am
<h3 class="tyto">Une liste mixée <code class="tyto icode">&lt;ol&gt;, &lt;ul&gt;</code></h3> <h3 class="tyto">Une liste mixée <code class="tyto icode">&lt;ol&gt;, &lt;ul&gt;</code></h3>
<p class="tyto"> <p class="tyto">
<ol class="mylist"> <ol class="mylist">
<li class="mylist">numeric o: item 1</li> <li class="mylist">numeric ol item 1</li>
<ol> <ol>
<li class="mylist">numeric ol sub-Item 1</li> <li class="mylist">numeric ol sub-Item 1</li>
<ol> <ol>

2
debian/control vendored
View File

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

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Version: 1.9.38 # Version: 1.9.39
# Updated: 2023-11-11 1699742831 # Updated: 2023-11-11 1699742831
# Tyto - Littérateur # Tyto - Littérateur
@ -41,7 +41,7 @@
# file program : # file program :
#-------------------------- #--------------------------
import os import os, sys
#===============# #===============#
@ -56,8 +56,8 @@ def error_message(path):
# A little checker to be sure, all files are installed # # A little checker to be sure, all files are installed #
#------------------------------------------------------# #------------------------------------------------------#
def check_install(): def check_install():
if not os.path.exists(libs): error_message(libs) os.path.exists(libs) or error_message(libs)
if not os.path.exists(trfs): error_message(trfs) os.path.exists(trfs) or error_message(trfs)
for f in prog_files: for f in prog_files:
f = os.path.join(libs, f + ".py") f = os.path.join(libs, f + ".py")
@ -75,7 +75,6 @@ def check_install():
#======#======================================================================= #======#=======================================================================
# MAIN # # MAIN #
#======# #======#
import sys
if not __name__ == "__main__": if not __name__ == "__main__":
print("! Error: '%s' not '%s'"%(__name__, "__main__")) print("! Error: '%s' not '%s'"%(__name__, "__main__"))
sys.exit(1) sys.exit(1)

View File

@ -59,15 +59,21 @@ def get_target():
#================================# #================================#
# Searching options in arguments # # Searching options in arguments #
# Done only once #
#--------------------------------# #--------------------------------#
def get_options(): def get_options():
global dlogs, force, erron global dlogs, force, erron, set_options
try: set_options ; return
except: pass
dlogs = force = erron = False dlogs = force = erron = False
for arg in range(1, len(sys.argv)): for arg in range(1, len(sys.argv)):
dlogs = sys.argv[arg] in tyto.debug_options if sys.argv[arg] in tyto.debug_options: dlogs = True
force = sys.argv[arg] in tyto.force_options if sys.argv[arg] in tyto.force_options: force = True
erron = sys.argv[arg] in tyto.debug_errors if sys.argv[arg] in tyto.debug_errors: erron = True
set_options = True
#===========# #===========#
@ -75,6 +81,7 @@ def get_options():
#-----------# #-----------#
def valid_action(): def valid_action():
global action global action
if not action in tyto.actions: if not action in tyto.actions:
debug.out(1, "[action]", action, False, 2, False) debug.out(1, "[action]", action, False, 2, False)
action = "help" action = "help"
@ -93,14 +100,14 @@ def start_process():
valid_action() valid_action()
do = { do = {
"help" : help.show, "help" : help.show,
"check" : check.manage, "check" : check.manage,
"new" : new.manage, "new" : new.manage,
"set" : userset.manage, "set" : userset.manage,
"start" : userset.manage, "start" : userset.manage,
"stop" : userset.manage, "stop" : userset.manage,
"show" : show.manage, "show" : show.manage,
"wip" : wip.manage, "wip" : wip.manage,
} }
do[action](action, target) do[action](action, target)

View File

@ -46,8 +46,8 @@ import args, domain, langs, debug, post, tools, tyto, wip
# Domain must be activated # # Domain must be activated #
#-------------------------------------# #-------------------------------------#
def ready(): def ready():
domain.cf_update_values(False) domain.cf_update_values(False)
domain.ready() domain.ready()
#===========================================# #===========================================#
@ -67,6 +67,7 @@ def manage(action, target):
target == "domain" and wrk_domain() target == "domain" and wrk_domain()
target in ("wip", "www") and srv_domain(target) target in ("wip", "www") and srv_domain(target)
#==========================================# #==========================================#
# Check some things used by current domain # # Check some things used by current domain #
#------------------------------------------# #------------------------------------------#
@ -80,24 +81,44 @@ def wrk_domain():
#==========================================================# #==========================================================#
# Warn if unused registred file in wrk template/ directory # # Warn if unused registred file in wrk template/ directory #
# Done only once #
# - in case of "all" or direct "wip" #
#----------------------------------------------------------# #----------------------------------------------------------#
def wrk_template_files(): def wrk_template_files():
global check_tpl_files
try: check_tpl_files ; return
except: pass
for key, uri in domain.cf.items("USER_TEMPLATE_FILES"): for key, uri in domain.cf.items("USER_TEMPLATE_FILES"):
if not os.path.exists(uri): if not os.path.exists(uri):
debug.out(5, key, uri, True, 1, False) debug.out(5, key, uri, True, 1, False)
check_tpl_files = True
#==================================#
# Check wip and www dirs and files # #====================================#
#----------------------------------# # Check wip and www dirs and files #
# Done only once #
# - in case of "all" or direct "wip" #
#------------------------------------#
def srv_domain(target): def srv_domain(target):
global check_srv_domain
try: check_srv_domain ; return
except: pass
for section in ("%s_DIRS"%target.upper(), "%s_FILES"%target.upper()): for section in ("%s_DIRS"%target.upper(), "%s_FILES"%target.upper()):
# Set err number for directories or files
if section.endswith("DIRS"): err = 6 if section.endswith("DIRS"): err = 6
else: err = 5 else: err = 5
for key, uri in domain.cf.items(section): for key, uri in domain.cf.items(section):
if not os.path.exists(uri): if not os.path.exists(uri):
debug.out(err, key, uri, True, 1, False) debug.out(err, key, uri, True, 1, False)
check_srv_domain = True
#================================# #================================#
# Check article(S) # # Check article(S) #
@ -111,7 +132,7 @@ def is_article(target):
# When all is OK # When all is OK
# Will create post database, but now, show some values # Will create post database, but now, show some values
""" """
print("Final texts string:") print("> check: Final texts string...")
print('\n'.join(texts)) print('\n'.join(texts))
""" """
@ -192,6 +213,7 @@ def valid(target):
# Head contents # Head contents
# ============= # =============
# One Line targs in head_contents # One Line targs in head_contents
debug.out(215, "check. Headers", post.cf_uri, False, 0, False)
post.error == 0 and ol_tags() \ post.error == 0 and ol_tags() \
or tools.exit(targets, post.error) or tools.exit(targets, post.error)
# Multiple and optional Tags on 3 linges # Multiple and optional Tags on 3 linges
@ -253,7 +275,7 @@ def ol_tags():
global stats_total_files global stats_total_files
stats_total_files = 0 stats_total_files = 0
sitemap = "True" post.cf_set("HEADERS", "sitemap", "True")
stats_tyto_head_coms = 0 stats_tyto_head_coms = 0
for ln, line in enumerate(headers, 1): for ln, line in enumerate(headers, 1):
@ -614,6 +636,8 @@ def is_value2_file_exists(ln, tag, val2):
def sl_ptags(markers): def sl_ptags(markers):
global texts global texts
debug.out(215, "check. %s"%markers[2], post.cf_uri, False, 0, False)
convert = { convert = {
"bcodes" : wip.bcode, "bcodes" : wip.bcode,
"quotes" : wip.quote, "quotes" : wip.quote,
@ -736,6 +760,8 @@ def sl_ptags(markers):
def icodes(): def icodes():
global texts global texts
debug.out(215, "check. icodes", post.cf_uri, False, 0, False)
stats_text_icodes = 0 stats_text_icodes = 0
markers = post.words_markers markers = post.words_markers
@ -853,6 +879,8 @@ def icodes():
def sl_stags(): def sl_stags():
global anchors_ids, stats_tyto_text_coms global anchors_ids, stats_tyto_text_coms
debug.out(215, "check. Contents", post.cf_uri, False, 0, False)
anchors_ids = () # Uniq anchors IDs anchors_ids = () # Uniq anchors IDs
stats_tyto_text_coms = stats_html_coms = 0 stats_tyto_text_coms = stats_html_coms = 0
stats_text_anc_ids = 0 stats_text_anc_ids = 0
@ -871,7 +899,9 @@ def sl_stags():
# Avoid wanting #6 - #9 (but accept #1x.. #5x.. as comments...) # Avoid wanting #6 - #9 (but accept #1x.. #5x.. as comments...)
elif linels[1].isdigit() and int(linels[1]) >= 6: elif linels[1].isdigit() and int(linels[1]) >= 6:
post.error = \ post.error = \
debug.out(52, "%s) %s..."%(ln, linels[0:10]), post.uri, True, 1, False) debug.out(52, "%s) %s..."%(
ln, linels[0:10]
), post.uri, True, 1, False)
return False return False
stats_titles += 1 stats_titles += 1

View File

@ -33,43 +33,19 @@
#-------------------------- #--------------------------
import sys import sys
import langs, args import langs, args, logs
#===================================#
# Show all logs if "show" is True #
# or with -D argument #
# color is for "*" in message #
# - 3 colors levels: #
# - - 0 = Green #
# - - 1 = Yellow #
# - - 2 = Red #
# stop to sys exit with nbr if True #
#-----------------------------------#
def out(nbr, var, val, show, color, stop):
args.get_options()
logit = show or args.erron and color > 0 or args.dlogs #===================#
if not logit: # Messages for logs #
return nbr #-------------------#
def set_messages():
global messages, got_messages
# COlors try: got_messages ; return
CS = '\033[0;0m' # Unset except: pass
CL = '\033[0;2m' # Gray
CB = '\033[1;34m' # Blue
CC = '\033[1;36m' # Cyan
CR = '\033[1;31m' # Red
CG = '\033[1;32m' # Green
CY = '\033[1;33m' # Yellow
CP = '\033[1;35m' # Pink
# Color of "*"
SC = CL # Default gray
if color == 0: SC = CG
elif color == 1: SC = CY
elif color == 2: SC = CR
# Messages for logs
messages = \ messages = \
{ {
# ERRORS (1-100) # ERRORS (1-100)
@ -83,6 +59,8 @@ def out(nbr, var, val, show, color, stop):
8 : langs.logs.err_lang, 8 : langs.logs.err_lang,
9 : langs.logs.err_ini_file, 9 : langs.logs.err_ini_file,
10 : langs.logs.err_post_global, 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, 20 : langs.logs.err_bad_uri,
21 : langs.logs.err_post_sep, 21 : langs.logs.err_post_sep,
22 : langs.logs.err_post_head, 22 : langs.logs.err_post_head,
@ -114,10 +92,59 @@ def out(nbr, var, val, show, color, stop):
208 : langs.logs.website_lang, 208 : langs.logs.website_lang,
209 : langs.logs.domain_on, 209 : langs.logs.domain_on,
210 : langs.logs.post_chk_yet, 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, 254 : langs.logs.post_chk_ready,
255 : langs.logs.later, 255 : langs.logs.later,
} }
got_messages = True
#===================================#
# Show all logs if "show" is True #
# or with -D argument #
# color is for "*" in message #
# - 3 colors levels: #
# - - 0 = Green #
# - - 1 = Yellow #
# - - 2 = Red #
# stop to sys exit with nbr if True #
#-----------------------------------#
def out(nbr, var, val, show, color, stop):
set_messages()
logs.add_line(nbr, messages[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
# COlors
CS = '\033[0;0m' # Unset
CL = '\033[0;2m' # Gray
CB = '\033[1;34m' # Blue
CC = '\033[1;36m' # Cyan
CR = '\033[1;31m' # Red
CG = '\033[1;32m' # Green
CY = '\033[1;33m' # Yellow
CP = '\033[1;35m' # Pink
# Color of "*"
SC = CL # Default gray
if color == 0: SC = CG
elif color == 1: SC = CY
elif color == 2: SC = CR
# Print, acoording to parameters # Print, acoording to parameters
print("%s*%s %s%s%s > %s%s%s < %s%s%s"%( print("%s*%s %s%s%s > %s%s%s < %s%s%s"%(

View File

@ -56,6 +56,7 @@ def cf_load():
cf = False cf = False
cf = configparser.ConfigParser() cf = configparser.ConfigParser()
cf.read(cf_uri) cf.read(cf_uri)
debug.out(200, langs.logs.domain, cf_uri, False, 0, False)
#=====================================# #=====================================#
@ -221,6 +222,7 @@ def cf_set(section, key, default):
def cf_update_values(write): def cf_update_values(write):
# Load Domain Configuration file # Load Domain Configuration file
cf_load() cf_load()
debug.out(214, "...", cf_uri, False, 0, False)
# [DOMAIN] # [DOMAIN]
# ======== # ========

View File

@ -0,0 +1,140 @@
#!/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 logs files in /var/log/tyto/
# File: /var/lib/tyto/program/logs.py
#----------------------------------------------------------------------
#-------------------------
# Funny Stats Project
#-------------------------
# file lines :
# file comments :
# file functions:
# file program :
#--------------------------
import os, sys, datetime
# 2 Files for logs
f_current = "/var/log/tyto/current.log" # Last session
f_archive = "/var/log/tyto/archive.log" # All sessions
#==============================#
# Set and return date and time #
#------------------------------#
def nowdate():
return(datetime.datetime.utcnow().isoformat())
#===================================#
# Create logs files (if not exists) #
#-----------------------------------#
def create_files():
global error_write, check
# Process done.
# In error case or files exist, not need to create again
try: check ; return
except: pass
# Process could not write file, no need to continue
try: error_write ; return
except: pass
CS = '\033[0;0m' # Unset
CL = '\033[0;2m' # Gray
CR = '\033[1;31m' # Red
for f in (f_current, f_archive):
if not os.path.exists(f):
try:
with open(f, "w") as f:
f.write("")
except:
print("%s!%s %sUnused%s %s"%(
CR,CS, CL,CS, f )
)
error_write = True
check = True
#=====================================#
# Create current.log for each session #
#
def add_line(nbr, message, var, val):
global first_log
# Create logs files (if not exists)
create_files()
# In error case (unused log file), return
try: error_write ; return
except: pass
# Merge current logs in archive logs (done only at first log)
archive_current_logs()
# At first log only, add command line to current logs
try:
first_log
except:
first_log = True
# Get command line
command = ""
for arg in range(1, len(sys.argv)):
command = command + sys.argv[arg] + " "
with open(f_current, "w") as f:
f.write("[%s] $ tyto %s"%(nowdate(), command))
# Create line for file
n_spaces = 3 - len(str(nbr))
with open(f_current, "a") as f:
f.write("\n[%s] %s%s => %s > %s < %s"%(
nowdate(), nbr, (n_spaces * " "), message, var, val
)
)
#==================================#
# Merge current.log to archive.log #
# Done only once, at first log #
#----------------------------------#
def archive_current_logs():
global merge_done
try: merge_done ; return
except: pass
# Load current logs file lines
current_logs = open(f_current, "r").read()
# No need to append empty current logs file
if current_logs:
# Append current logs file to archive logs
with open(f_archive, "a") as f:
f.write("%s\n\n"%(current_logs))
merge_done = True

View File

@ -32,7 +32,8 @@
# file program : # file program :
#-------------------------- #--------------------------
import args, domain import os
import args, domain, debug, sitemaps
#====================================# #====================================#
@ -41,7 +42,8 @@ import args, domain
#------------------------------------# #------------------------------------#
def manage(action, target): def manage(action, target):
do = { do = {
"domain" : create_domain, "domain" : create_domain,
"sitemaps" : sitemaps.manage,
} }
do[target]() do[target]()
@ -54,8 +56,18 @@ def manage(action, target):
# or if user "force" option # or if user "force" option
#-----------------------------------# #-----------------------------------#
def create_domain(): def create_domain():
if not domain.cf_exists() or args.force: # Check if in a domain set yet
domain.cf_create() d_uri = "/"
return 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()

View File

@ -49,6 +49,8 @@ write = False # When updating database in cf_set(), cf_write()
def is_article(target): def is_article(target):
global error global error
debug.out(211, '"%s"'%target, "", False, 0, False)
# User MUST be in articles/ # User MUST be in articles/
domain.user_dir.startswith(domain.wrk_articles) or \ domain.user_dir.startswith(domain.wrk_articles) or \
debug.out(2, "-> articles/", domain.wrk_articles, True, 2, True) debug.out(2, "-> articles/", domain.wrk_articles, True, 2, True)
@ -146,41 +148,47 @@ def is_tyto_format():
# return True, or False if unused (yet) # # return True, or False if unused (yet) #
#---------------------------------------# #---------------------------------------#
def cf_load(): def cf_load():
global cf global cf, not_chk
cf = False cf = not_chk = False
os.path.exists(cf_uri) or tools.create_file(cf_uri, ini_template)
if not os.path.exists(cf_uri):
not_chk = True
tools.create_file(cf_uri, ini_template)
cf = configparser.ConfigParser() cf = configparser.ConfigParser()
cf.read(cf_uri) cf.read(cf_uri)
debug.out(200, uri_id, cf_uri, False, 0, False)
return True return True
#======================================# #======================================#
# Load another post configuration file # # Load another post configuration file #
# Used by modules: navbar, sidebar #
#--------------------------------------# #--------------------------------------#
def tmp_load(wrk_post, wrk_post_uri): def tmp_load(module, wrk_post, wrk_post_uri):
global error global error
db_uri = os.path.join( db_uri = os.path.join(
domain.wrk_db, domain.wrk_db,
tools.get_filesum(wrk_post_uri, False) + ".ini" tools.get_filesum(wrk_post_uri, False) + ".ini"
) )
if not os.path.exists(db_uri): if not os.path.exists(db_uri):
error = \ error = \
debug.out(5, wrk_post, db_uri, True, 2, False) debug.out(11, '%s. "%s"'%(module, wrk_post), db_uri, True, 2, False)
return False return False
global tmp_cf global tmp_cf
tmp_cf = "" tmp_cf = ""
tmp_cf = configparser.ConfigParser() tmp_cf = configparser.ConfigParser()
tmp_cf.read(db_uri) tmp_cf.read(db_uri)
debug.out(200, '%s. "%s"'%(module, wrk_post), db_uri, False, 0, False)
if tmp_cf.getboolean("CHECK", "errors"): if tmp_cf.getboolean("CHECK", "errors"):
error = \ error = \
debug.out(10, "True", db_uri, True, 2, False) debug.out(10, "check: %s"%langs.logs.error, db_uri, True, 2, False)
return False return False
global tmp_title, tmp_about, tmp_logo global tmp_title, tmp_about, tmp_logo
@ -208,6 +216,55 @@ def tmp_load(wrk_post, wrk_post_uri):
return True 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 ""
#================================# #================================#
# Return value from section, key # # Return value from section, key #
#--------------------------------# #--------------------------------#
@ -325,6 +382,7 @@ def cf_write():
if write: if write:
with open(cf_uri, "w") as f: with open(cf_uri, "w") as f:
cf.write(f) cf.write(f)
debug.out(207, uri_id, cf_uri, False, 0, False)
write = False write = False
@ -336,7 +394,7 @@ def find_tyto_article():
nothere = (domain.wrk_files, domain.wrk_images) nothere = (domain.wrk_files, domain.wrk_images)
os.chdir(domain.wrk_articles) os.chdir(domain.wrk_articles)
for root,dirs,files in os.walk(domain.wrk_articles): for root, dirs, files in os.walk(domain.wrk_articles):
if root.startswith(nothere): if root.startswith(nothere):
continue continue

View File

@ -0,0 +1,252 @@
#!/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 sitemaps
# File: /var/lib/tyto/program/sitemaps.py
#----------------------------------------------------------------------
#-------------------------
# Funny Stats Project
#-------------------------
# file lines :
# file comments :
# file functions:
# file program :
#--------------------------
import os
import args, debug, domain, post, langs, tools, check, wip
sitemap_post = """# %s Tyto - Littérateur
! NoSitemap
title: %s (%s)
about: %s (%s)
tags: %s
author: Tyto
date: %s
-----
#1 %s. %s%s "%s"
(( sitemap
<: sitemap-items
%s
:>
))
#1 %s
(( sitemap
<: sitemap-items
%s
:>
))
"""
sitemap_post_empty = """ %s Tyto - Littérateur
! NoSitemap
title: %s (%s)
about: %s (%s)
tags: %s
author: Tyto
date: %s
-----
(( sitemap
%s
))
"""
# Generic link for sitemap
link = ' %s <a class="%s sitemap" href="%s" title="%s [%s]">%s%s</a>'
#===========================#
# Manage sitemaps creations #
#---------------------------#
def manage():
domain.cf_update_values(False)
domain.ready()
if not domain.sitemaps:
return
global nowdate
nowdate = tools.nowdate().rsplit()[0]
debug.out(216, "sitemap.tyto", "sitemap.html", False, 0, False)
# Create sitemap for root and sub-directories
create_by_dir(domain.wrk_articles)
create_by_subdir()
#====================================================#
# Search in specific path directory #
# for Tyto articles, and filter them by newest first #
#---------------------------------------------------#
def articles_sorted(path):
os.chdir(path)
files = filter(os.path.isfile, os.listdir(path))
files = [os.path.join(path, f) for f in files if f.endswith(".tyto")]
files.sort(key=lambda t: os.path.getmtime(t), reverse=True)
return files
#=======================#
# Return post DB values #
#-----------------------#
def set_db_values():
return post.tmp_db_item("FILE", "target", False), \
post.tmp_db_item("FILE", "web", False), \
post.tmp_db_item("HEADERS", "title", False), \
post.tmp_db_item("HEADERS", "about", False), \
post.tmp_db_item("HEADERS", "date", False), \
post.tmp_db_item("HEADERS", "authors", False)
#=========================================================#
# Main function to make sitemap.tyto and sitemap.html #
# List Tyto articles by newest in each directory #
# Create 2 links lists (only if a valid article is added) #
# 1. directories pointing to sitemap.html
# 2. articles
# ...
#
def create_by_dir(path):
target_dir = path.rsplit(domain.wrk_articles[:-1])[1]
target_slashes = target_dir.count("/")
curr_root = root = list_pages_links = list_posts_links = ""
has_article = False
for root, dirs, files in os.walk(path):
articles = articles_sorted(root)
for article in articles:
has_article = True
if curr_root != root:
curr_root = root
add_page_link = True
else:
add_page_link = False
# Load post DB (if exists)
post.tmp_db_error = False
if not post.tmp_load_db(article) or post.tmp_db_error:
curr_root = ""
continue
target, web, title, about, date, authors = set_db_values()
web_slashes = web.count("/")
# Add page link (pointing to sitemap.html)
# Add only one same link if an article exists
if add_page_link:
# For sub directories, mark "="
# is the différence with web target and root domain
if path != domain.wrk_articles:
web_slashes = web_slashes - target_slashes
if list_pages_links: nl1 = "\n"
else: nl1 = ""
list_pages_links = \
list_pages_links + nl1 + link%(
"=" * web_slashes,
domain.css, "%ssitemap.html"%web,
"%s%s %s"%(
langs.site.sitemap, langs.logs.pp, web
), "Tyto", "", web
)
# Add article link
if list_posts_links: nl2 = "\n"
else: nl2 = ""
list_posts_links = \
list_posts_links + nl2 + link%(
"=" * web_slashes,
domain.css, web, about, authors, date + ", ", title
)
# A sitemap is created if a Tyto article file is found
if not list_posts_links and not has_article:
return
if not list_posts_links:
root_sitemap = \
sitemap_post_empty%(
langs.site.sitemap_gen,
langs.site.sitemap, target_dir,
langs.site.sitemap, target_dir,
langs.site.sitemap,
nowdate,
langs.site.sitemap_empty
)
else:
root_sitemap = \
sitemap_post%(
langs.site.sitemap_gen,
langs.site.sitemap, target_dir,
langs.site.sitemap, target_dir,
langs.site.sitemap,
nowdate,
langs.site.sitemap, langs.site.directory, langs.logs.pp, target_dir,
list_pages_links,
langs.site.posts_list,
list_posts_links,
)
#print(root_sitemap)
if path != domain.wrk_articles: target_file = "/sitemap.tyto"
else: target_file = "sitemap.tyto"
target_file = target_dir[1:] + target_file
#print(">> target_f", target_file)
file_uri = domain.wrk_articles + target_file
#print(">> file_uri", file_uri)
os.chdir(domain.wrk_articles)
args.targets = "all"
tools.create_file(file_uri, root_sitemap)
wip.is_article(target_file)
#==========================================================#
# Loop from all sub directories from root domain articles/ #
# For each, create_by_dir() sitemaps #
#
def create_by_subdir():
for root, dirs, files in os.walk(domain.wrk_articles):
for d in dirs:
dir_uri = os.path.join(root,d)
create_by_dir(dir_uri)

View File

@ -109,13 +109,13 @@ def dir_exists(dir_path, out):
# Create directories # # Create directories #
#--------------------# #--------------------#
def create_dirs(path): def create_dirs(path):
try: if not os.path.exists(path):
if not os.path.exists(path): try:
os.makedirs(path, exist_ok=True) os.makedirs(path, exist_ok=True)
debug.out(203, "True", path, False, 0, False) debug.out(203, langs.logs.success, path, True, 0, False)
except: except:
# Exit if not created # Exit if not created
debug.out(6, "False", path, True, 2, True) debug.out(6, langs.logs.error, path, True, 2, True)
#============================# #============================#
@ -128,7 +128,7 @@ def create_file(file_path, contents):
f.write(contents) f.write(contents)
except: except:
# Exit if not created # Exit if not created
debug.out(7, "False", file_path, True, 2, True) debug.out(7, langs.logs.error, file_path, True, 2, True)
# log "update" or "new" # log "update" or "new"
file_name = os.path.basename(file_path) file_name = os.path.basename(file_path)

View File

@ -41,6 +41,8 @@ targets = (
"domains", "domains",
"title", "date", "about", "mail", "tags", "lang", "server", "title", "date", "about", "mail", "tags", "lang", "server",
"all", "all",
"metas", "header", "navbar", "sidebar", "footer",
"sitemaps",
) )
force_options = ("--force", "-F") force_options = ("--force", "-F")
@ -53,7 +55,7 @@ debug_errors = ('--errors', "-E")
# #
full_name = "Tyto - Littérateur" full_name = "Tyto - Littérateur"
web_url = "https://tyto.echolib.re" web_url = "https://tyto.echolib.re"
git_url = "https://git.a-lec.org/echolib/tyto-litterateur" git_url = "https://forge.a-lec.org/echolib/tyto-litterateur"
#=============================================================# #=============================================================#

View File

@ -32,7 +32,7 @@
# file program : # file program :
#-------------------------- #--------------------------
import langs, forms, domain import langs, forms, domain, wip
#====================================# #====================================#
@ -45,15 +45,21 @@ def manage(action, target):
if action == "set": if action == "set":
do = { do = {
"title" : forms.ask_domain_title, "title" : forms.ask_domain_title,
"date" : forms.ask_domain_date, "date" : forms.ask_domain_date,
"about" : forms.ask_domain_about, "about" : forms.ask_domain_about,
"mail" : forms.ask_domain_mail, "mail" : forms.ask_domain_mail,
"lang" : forms.ask_domain_lang, "lang" : forms.ask_domain_lang,
"server" : forms.ask_domain_server, "server" : forms.ask_domain_server,
"metas" : wip.create_default_module,
"header" : wip.create_default_module,
"navbar" : wip.create_default_module,
"sidebar" : wip.create_default_module,
"footer" : wip.create_default_module,
} }
do[target](True) try: do[target](target)
except: pass
elif action in ("start", "stop") and target == "domain": elif action in ("start", "stop") and target == "domain":
domain.userset_status(action) domain.userset_status(action)

View File

@ -92,6 +92,13 @@ def is_article(target):
# Copy article files # Copy article files
create_files() create_files()
post.cf_set("WIP", "hash", post.wrk_id)
post.cf_set("WIP", "date", datepub)
post.cf_write()
debug.out(250, langs.logs.success, post.wip_uri, True, 0, False)
#print() #print()
#print(html_post) #print(html_post)
@ -144,6 +151,17 @@ def page_html_create():
# Create and copy files for this article # # Create and copy files for this article #
#----------------------------------------# #----------------------------------------#
def create_files(): def create_files():
# Create source post wip dirs and html file
wip_dirs = \
post.wip_uri.rsplit(os.path.basename(post.wip_uri))[0] or domain.wip
tools.create_dirs(wip_dirs)
tools.create_file(post.wip_uri, page_html)
# Check/Create modules files
# navbar, sidebar, header, footer
if not get_modules("wip"):
return False
# Copy files used by article # Copy files used by article
for key, src_uri in post.cf.items("SOURCE_FILES"): for key, src_uri in post.cf.items("SOURCE_FILES"):
dst_uri = src_uri.replace(domain.wrk_articles, domain.wip) dst_uri = src_uri.replace(domain.wrk_articles, domain.wip)
@ -153,12 +171,6 @@ def create_files():
tools.create_dirs(wip_dirs) tools.create_dirs(wip_dirs)
tools.copy_files(src_uri, dst_uri) tools.copy_files(src_uri, dst_uri)
# Create source post wip dirs and html file
wip_dirs = \
post.wip_uri.rsplit(os.path.basename(post.wip_uri))[0] or domain.wip
tools.create_dirs(wip_dirs)
tools.create_file(post.wip_uri, page_html)
# Copy domain work template directory # Copy domain work template directory
shutil.copytree(domain.wrk_tpl, shutil.copytree(domain.wrk_tpl,
domain.wip_tpl, domain.wip_tpl,
@ -192,19 +204,19 @@ def convert(target):
check.wrk_template_files() check.wrk_template_files()
# Check/Create modules files debug.out(212, target, post.wip_uri, False, 0, False)
# navbar, sidebar, header, footer
if not get_modules("wip"):
return False
# Article has errors or changed : needs check first # Article has errors or changed : needs check first
if post.has_changed or post.chk_errors: if post.has_changed or post.chk_errors:
if post.has_changed: debug.out(106, "'check'", post.uri, True, 1,False) if post.chk_errors: debug.out(10, "'check'", post.uri, True, 2, False)
elif post.chk_errors: debug.out(10, "'check'", post.uri, True, 2, False) elif post.not_chk: debug.out(11, "'check'", post.uri, True, 1, False)
elif post.has_changed: debug.out(106, "'check'", post.uri, True, 1, False)
args.force = True args.force = True
check.is_article(target) check.is_article(target)
if post.error != 0: if post.error != 0:
return False return False
is_article(target) is_article(target)
return return
@ -232,6 +244,7 @@ def convert(target):
value_replace("CODES", False, True) value_replace("CODES", False, True)
footer_post_create() footer_post_create()
return True return True
@ -252,6 +265,8 @@ def text_replace(src, html):
# tgt_b64 : True to decode base64 target # # # tgt_b64 : True to decode base64 target # #
#------------------------------------------# #------------------------------------------#
def value_replace(section, src_b64, tgt_b64): def value_replace(section, src_b64, tgt_b64):
debug.out(215, "wip. %s"%section.lower(), post.cf_uri, False, 0, False)
for key, val in post.cf.items(section): for key, val in post.cf.items(section):
if key.startswith("html_"): if key.startswith("html_"):
continue continue
@ -333,6 +348,7 @@ def sl_tags():
elif line.lstrip().startswith(post.html_brline[0]): elif line.lstrip().startswith(post.html_brline[0]):
css = tools.get_css(line, post.html_brline[0][0], "?") css = tools.get_css(line, post.html_brline[0][0], "?")
text_replace(html_post.rsplit("\n")[ln], post.html_brline[1]%css) text_replace(html_post.rsplit("\n")[ln], post.html_brline[1]%css)
# <hr> # <hr>
elif line.lstrip().startswith(post.html_hrline[0]): elif line.lstrip().startswith(post.html_hrline[0]):
css = tools.get_css(line, post.html_hrline[0][0], "?") css = tools.get_css(line, post.html_hrline[0][0], "?")
@ -704,6 +720,27 @@ def footer_post_create():
#=========# #=========#
# Modules #==================================================================== # Modules #====================================================================
#---------# #---------#
#============================#
# With command "set [module] #
# remove if any [module] #
# Create default [module] #
#----------------------------#
def create_default_module(target):
domain.cf_update_values(False)
domain.ready()
files = {
"metas" : domain.wrk_metas,
"header" : domain.wrk_header,
"navbar" : domain.wrk_navbar,
"sidebar" : domain.wrk_sidebar,
"footer" : domain.wrk_footer
}
os.path.exists(files[target]) and os.remove(files[target])
get_modules("wip")
#==================================# #==================================#
# Create modules ini database file # # Create modules ini database file #
# return False if: # # return False if: #
@ -731,7 +768,10 @@ def modules_db():
# - footer # # - footer #
#--------------------------------------------# #--------------------------------------------#
def get_modules(srv): def get_modules(srv):
global modules global modules, datepub
try: datepub
except: datepub = tools.nowdate()
# Modules settings # Modules settings
fill_footer_raw() fill_footer_raw()
@ -806,6 +846,7 @@ def get_modules(srv):
# Manage modules # Manage modules
# Create raw files, and set html "srv" file # Create raw files, and set html "srv" file
for mod in modules: for mod in modules:
debug.out(215, "wip. Module %s"%(mod), modules[mod][srv], False, 0, False)
create_html_module = False create_html_module = False
# Create user raw files modules in modules/ directory # Create user raw files modules in modules/ directory
@ -825,11 +866,11 @@ def get_modules(srv):
create_html_module = True create_html_module = True
# Unused module HTML file or "--force" option # Unused module HTML file or "--force" option
if not os.path.exists(modules[mod][srv]) or args.force: if not os.path.exists(modules[mod][srv]):
create_html_module = True create_html_module = True
# Create HTML module if needed (raw updated, or unused html file) # Create HTML module if needed (raw updated, or unused html file)
if create_html_module: if args.force or create_html_module:
modules[mod]["set"](srv) modules[mod]["set"](srv)
if post.error != 0: if post.error != 0:
@ -965,7 +1006,7 @@ def navbar_html_create(srv):
# Load post configuration file in tmp module # Load post configuration file in tmp module
# return if unused or post errors # return if unused or post errors
if not post.tmp_load(wrk_index, wrk_index_uri): if not post.tmp_load("Navbar", wrk_index, wrk_index_uri):
return False return False
items = True items = True
@ -1073,7 +1114,7 @@ def sidebar_html_create(srv):
# Load post configuration file in tmp module # Load post configuration file in tmp module
# return if unused or post errors # return if unused or post errors
if not post.tmp_load(wrk_post, wrk_post_uri): if not post.tmp_load("Sidebar", wrk_post, wrk_post_uri):
return False return False
# Post can be added to list # Post can be added to list
@ -1122,15 +1163,26 @@ def fill_footer_raw():
if not domain.license_url: domain.license_url = "/" if not domain.license_url: domain.license_url = "/"
show_license = "%s%s %s"%(langs.site.license, langs.logs.pp, domain.license) show_license = "%s%s %s"%(langs.site.license, langs.logs.pp, domain.license)
footer_items = "%s\n%s"%( footer_items = "%s\n%s\n%s\n%s"%(
footer_items, footer_items,
item%( item%(
domain.license_url, domain.license_url,
langs.site.license_title, domain.title, langs.site.license_title, domain.title,
show_license show_license
),
item%(
"/%s"%domain.rss,
langs.site.feed_rss, domain.title,
langs.site.feed_rss
),
item%(
"/sitemap.html",
langs.site.sitemap, domain.title,
langs.site.sitemap
) )
) )
# Loop to [WEBSITE_FOOTER] and make link from key_url # Loop to [WEBSITE_FOOTER] and make link from key_url
for key, link in domain.cf.items("WEBSITE_FOOTER"): for key, link in domain.cf.items("WEBSITE_FOOTER"):
if link: if link:
@ -1159,6 +1211,19 @@ def fill_footer_raw():
# modules/tyto_footer.raw has default contents # # modules/tyto_footer.raw has default contents #
#------------------------------------------------# #------------------------------------------------#
def footer_html_create(srv): def footer_html_create(srv):
generator = '<div id="Tyto_links">%s '%(
langs.site.generated_by
) + \
'<a class="generator" ' + \
'title="%s" '%langs.site.off_website + \
'href="%s">'%tyto.web_url + \
'%s</a> '%tyto.full_name + \
'[<a class="generator" ' + \
'title="%s%s GPLv3" '%(langs.site.license, langs.logs.pp) + \
'href="%s">'%tyto.git_url + \
'%s</a>]'%langs.site.source_code + \
'</div>'
with open(domain.wrk_footer, "r") as f: with open(domain.wrk_footer, "r") as f:
footer_raw = f.read().rsplit("\n") footer_raw = f.read().rsplit("\n")
footer_html = "" footer_html = ""
@ -1172,6 +1237,9 @@ def footer_html_create(srv):
if not footer_html: footer_html = line if not footer_html: footer_html = line
else: footer_html = "%s\n%s"%(footer_html, line) else: footer_html = "%s\n%s"%(footer_html, line)
# Add generator credentials
footer_html = "%s\n%s"%(footer_html, generator)
tools.create_file(modules["footer"][srv], footer_html) tools.create_file(modules["footer"][srv], footer_html)
return True return True
@ -1319,4 +1387,4 @@ page_tpl = """<!-- %s - %s -->
</body> </body>
</html>""" </html>"""
page_time = '<!-- pagetime --><time datetime="%s">' page_time = '<!-- pagetime --><time datetime="%s">'

View File

@ -131,6 +131,17 @@ img.post_logo {}
img.tyto {} img.tyto {}
/*
* ----------------
* Sitemaps article
*/
p.sitemap {}
ul.sitemap-items {}
li.sitemap-item {}
/* Also a.tyto */
a.sitemap {}
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Sidebar (Website) * Sidebar (Website)
*/ */
@ -161,3 +172,7 @@ li.site_footer_item {}
/* Also a.tyto */ /* Also a.tyto */
a.site_footer_item_link {} a.site_footer_item_link {}
p#site_footer_copyright {} p#site_footer_copyright {}
/* After footer, TYto, credential */
div#Tyto_links {}
a.generator {}

View File

@ -36,7 +36,10 @@ ok = ("yes", "y")
# Form # Form
q = "?" q = "?"
pp = ":" pp = ":"
error = "Error"
success = "Success"
configure_domain = "Configure domain" configure_domain = "Configure domain"
domain = "Domain"
domain_title = "Domain title" domain_title = "Domain title"
domain_date = "Creation date" domain_date = "Creation date"
domain_about = "Domain description" domain_about = "Domain description"
@ -45,6 +48,8 @@ domain_tags = "Domain tags [1,2,3]"
domain_lang = "Website lang" domain_lang = "Website lang"
domain_srv = "Server URI" domain_srv = "Server URI"
copy = "Copy" copy = "Copy"
create_sitemaps = "Creating sitemaps"
completed = "Completed"
# Misc # Misc
anchor_title = "Anchor title" anchor_title = "Anchor title"
@ -73,6 +78,8 @@ err_post_in_tag = "Markers without contents"
err_post_datatag = "Data reserved" err_post_datatag = "Data reserved"
err_post_id_yet = "ID used yet" err_post_id_yet = "ID used yet"
err_post_global = "Article Error" err_post_global = "Article Error"
err_post_not_chk = "Article not checked"
err_post_not_www = "Article not published"
# Warnings # Warnings
warn_no_dom = "Domain not configured" warn_no_dom = "Domain not configured"
@ -93,6 +100,10 @@ domain_new = "Domain created"
created_dir = "Directory created" created_dir = "Directory created"
created_file = "File created" created_file = "File created"
updated_file = "File Updated" 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_yet = "Article checked yet"
post_chk_ready = "Article checked" post_chk_ready = "Article checked"
later = "Maybe later..." later = "Maybe later..."
@ -104,12 +115,12 @@ help_contents = """
tyto [action] [target] [options] tyto [action] [target] [options]
[action] [action]
new : create new domain (reset with -F) new : create new domain (reset with -F)
set : set website lang, domain values (title, server...) set : [server, date, title, mail, footer, header, ...]
start : activate domain (default "no" when created) start : activate domain (default "no" when created)
stop : deactivate domain stop : deactivate domain
show : [domains, metas] show : [domains, metas]
check : [domain, wip, www, [name].tyto] check : [domain, wip, www, [name].tyto]
wip : wip : [name].tyto: create HTML page in "wip/" server
publish : publish :
[target] [target]
@ -120,8 +131,9 @@ tyto [action] [target] [options]
about : [set]: domain description about : [set]: domain description
mail : [set]: domain admin mail mail : [set]: domain admin mail
tags : [set]: domain tags (added to all articles) tags : [set]: domain tags (added to all articles)
lang : lang : [set]: Website language
server : [set]: server local URI server : [set]: server local URI
footer : [set]: Create default module (also header...)
wip : [check] Directories and files wip : [check] Directories and files
www : [check] Directories and files www : [check] Directories and files

View File

@ -36,7 +36,10 @@ ok = ("oui", "o")
# Form # Form
q = " ?" q = " ?"
pp = " :" pp = " :"
error = "Erreur"
success = "Succès"
configure_domain = "Configurer le domaine" configure_domain = "Configurer le domaine"
domain = "Domaine"
domain_title = "Titre du domaine" domain_title = "Titre du domaine"
domain_date = "Date de création" domain_date = "Date de création"
domain_about = "Description du domaine" domain_about = "Description du domaine"
@ -45,6 +48,8 @@ domain_tags = "Mots-clés du domaine [1,2,3]"
domain_lang = "Langue du site web" domain_lang = "Langue du site web"
domain_srv = "URI du serveur" domain_srv = "URI du serveur"
copy = "Copie" copy = "Copie"
create_sitemaps = "Création des plans du site"
completed = "Terminé"
# Misc # Misc
anchor_title = "Titre de l'ancre" anchor_title = "Titre de l'ancre"
@ -73,6 +78,8 @@ err_post_in_tag = "Marqueurs sans contenu"
err_post_datatag = "Donnée réservée" err_post_datatag = "Donnée réservée"
err_post_id_yet = "Identité déjà utilisée" err_post_id_yet = "Identité déjà utilisée"
err_post_global = "Article erronné" err_post_global = "Article erronné"
err_post_not_chk = "Article non vérifié"
err_post_not_www = "Article non publié"
# Warnings # Warnings
warn_no_dom = "Domaine non configuré" warn_no_dom = "Domaine non configuré"
@ -93,6 +100,10 @@ domain_new = "Domaine créé"
created_dir = "Dossier créé" created_dir = "Dossier créé"
created_file = "Fichier créé" created_file = "Fichier créé"
updated_file = "Fichier mis à jour" 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_yet = "Article déjà vérifié"
post_chk_ready = "Article vérifié" post_chk_ready = "Article vérifié"
later = "Peut-être plus tard..." later = "Peut-être plus tard..."
@ -104,12 +115,12 @@ help_contents = """
tyto [action] [target] [options] tyto [action] [target] [options]
[action] [action]
new : créer un nouveau domaine (réinitialisé avec -F) new : créer un nouveau domaine (réinitialisé avec -F)
set : définir la langue du site web, du domaine (titre, serveur...) set : [server, date, title, mail, footer, header, ...]
start : activer le domaine (défaut "no" à la création) start : activer le domaine (défaut "no" à la création)
stop : désactiver le domaine stop : désactiver le domaine
show : [domains, metas] show : [domains, metas]
check : [domain, wip, www, [name].tyto] check : [domain, wip, www, [name].tyto]
wip : wip : [name].tyto: crée la page HTML dans le serveur "wip/"
publish : publish :
[target] [target]
@ -120,8 +131,9 @@ tyto [action] [target] [options]
about : [set]: description du domaine about : [set]: description du domaine
mail : [set]: courriel de l'administrateur mail : [set]: courriel de l'administrateur
tags : [set]: étiquettes du domaine (ajoutées aux articles) tags : [set]: étiquettes du domaine (ajoutées aux articles)
lang : lang : [set]
server : [set]: URI du serveur local server : [set]: URI du serveur local
footer : [set]: Crée le module par défaut (aussi header...)
wip : [check] dossiers et fichiers wip : [check] dossiers et fichiers
www : [check] dossiers et fichiers www : [check] dossiers et fichiers

View File

@ -31,7 +31,12 @@
# Note: python file # Note: python file
sidebar_title = "Featured posts" sidebar_title = "Featured posts"
sitemap = "sitemap"
directory = "Directory"
sitemap = "Sitemap"
sitemap_gen = "Sitemap source article generated by"
sitemap_empty = "Nothing to show yet"
posts_list = "Articles list"
source_code = "Source code" source_code = "Source code"
permalink = "Permalink" permalink = "Permalink"
@ -43,3 +48,6 @@ terms = "Terms of Service"
terms_title = "%s of"%terms terms_title = "%s of"%terms
bylaws = "Bylaws" bylaws = "Bylaws"
bylaws_title = "%s of"%bylaws bylaws_title = "%s of"%bylaws
feed_rss = "RSS feed 2.0"
generated_by = "Generated by"
off_website = "Official website"

View File

@ -31,7 +31,12 @@
# Note: Fichier au format python # Note: Fichier au format python
sidebar_title = "Articles recommandés" sidebar_title = "Articles recommandés"
directory = "Dossier"
sitemap = "Plan du site" sitemap = "Plan du site"
sitemap_gen = "Article source du plan du site généré par"
sitemap_empty = "Rien à afficher pour le moment."
posts_list = "Liste des articles"
source_code = "Code source" source_code = "Code source"
permalink = "Permalien" permalink = "Permalien"
@ -43,3 +48,6 @@ terms = "C.G.U"
terms_title = "%s de"%terms terms_title = "%s de"%terms
bylaws = "Statuts" bylaws = "Statuts"
bylaws_title = "%s de"%bylaws bylaws_title = "%s de"%bylaws
feed_rss = "Flux RSS 2.0"
generated_by = "Géneré par"
off_website = "Site web officiel"