"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "txt2tags.py" between
txt2tags-3.6.tar.gz and txt2tags-3.7.tar.gz

About: txt2tags is a document generator that reads a text file with minimal markup such as **bold** and //italic// and converts it to formats like AsciiDoc, DocBook, HTML, LaTeX, MediaWiki. MoinMoin, Plain Text, SGML or Unix Manpage. For Python 3.5 or newer (some 2.x features removed).

txt2tags.py  (txt2tags-3.6):txt2tags.py  (txt2tags-3.7)
skipping to change at line 82 skipping to change at line 82
import collections import collections
import getopt import getopt
import io import io
import os import os
import re import re
import sys import sys
############################################################################## ##############################################################################
# Program information # Program information
my_url = "http://txt2tags.org" my_url = "https://txt2tags.org"
my_name = "txt2tags" my_name = "txt2tags"
my_email = "jendrikseipp@gmail.com" my_email = "jendrikseipp@gmail.com"
__version__ = "3.6" __version__ = "3.7"
# FLAGS : the conversion related flags , may be used in %!options # FLAGS : the conversion related flags , may be used in %!options
# OPTIONS : the conversion related options, may be used in %!options # OPTIONS : the conversion related options, may be used in %!options
# ACTIONS : the other behavior modifiers, valid on command line only # ACTIONS : the other behavior modifiers, valid on command line only
# SETTINGS: global miscellaneous settings, valid on RC file only
# NO_TARGET: actions that don't require a target specification # NO_TARGET: actions that don't require a target specification
# NO_MULTI_INPUT: actions that don't accept more than one input file # NO_MULTI_INPUT: actions that don't accept more than one input file
# CONFIG_KEYWORDS: the valid %!key:val keywords # CONFIG_KEYWORDS: the valid %!key:val keywords
# #
# FLAGS and OPTIONS are configs that affect the converted document. # FLAGS and OPTIONS are configs that affect the converted document.
# They usually have also a --no-<option> to turn them OFF. # They usually have also a --no-<option> to turn them OFF.
# #
# ACTIONS are needed because when handling multiple input files, strange # ACTIONS are needed because when handling multiple input files, strange
# behavior may occur. There is no --no-<action>. # behavior may occur. There is no --no-<action>.
# Options --version and --help inside %!options are odd. # Options --version and --help inside %!options are odd.
FLAGS = { FLAGS = {
"headers": 1, "headers": 1,
"enum-title": 0, "enum-title": 0,
"mask-email": 0,
"toc-only": 0,
"toc": 0, "toc": 0,
"rc": 1, "rc": 1,
"quiet": 0, "quiet": 0,
"slides": 0, "slides": 0,
} }
OPTIONS = { OPTIONS = {
"target": "", "target": "",
"toc-level": 3,
"style": "", "style": "",
"infile": "", "infile": "",
"outfile": "", "outfile": "",
"config-file": "", "config-file": "",
"lang": "", "lang": "",
} }
ACTIONS = { ACTIONS = {
"help": 0, "help": 0,
"version": 0, "version": 0,
"verbose": 0, "verbose": 0,
"debug": 0, "debug": 0,
"targets": 0, "targets": 0,
} }
SETTINGS = {} # for future use NO_TARGET = ["help", "version", "targets"]
NO_TARGET = ["help", "version", "toc-only", "targets"]
CONFIG_KEYWORDS = ["target", "style", "options", "preproc", "postproc"] CONFIG_KEYWORDS = ["target", "style", "options", "preproc", "postproc"]
TARGET_NAMES = { TARGET_NAMES = {
"html": "HTML page", "html": "HTML page",
"sgml": "SGML document", "sgml": "SGML document",
"dbk": "DocBook document", "dbk": "DocBook document",
"tex": "LaTeX document", "tex": "LaTeX document",
"lout": "Lout document", "lout": "Lout document",
"man": "UNIX Manual page", "man": "UNIX Manual page",
"mgp": "MagicPoint presentation", "mgp": "MagicPoint presentation",
skipping to change at line 182 skipping to change at line 177
MODULEIN = MODULEOUT = "-module-" MODULEIN = MODULEOUT = "-module-"
ESCCHAR = "\x00" ESCCHAR = "\x00"
SEPARATOR = "\x01" SEPARATOR = "\x01"
LISTNAMES = {"-": "list", "+": "numlist", ":": "deflist"} LISTNAMES = {"-": "list", "+": "numlist", ":": "deflist"}
VERSIONSTR = "{} version {} <{}>".format(my_name, __version__, my_url) VERSIONSTR = "{} version {} <{}>".format(my_name, __version__, my_url)
USAGE = "\n".join( USAGE = "\n".join(
[ [
"", "",
"Usage: %s [OPTIONS] [infile.t2t ...]" % my_name, "Usage: %s [OPTIONS] infile.t2t" % my_name,
"", "",
" --targets print a list of all the available targets and exi t", " --targets list available targets and exit",
" -t, --target=TYPE set target document type. currently supported:", " -t, --target=TYPE set target document type. currently supported:",
" %s," % ", ".join(TARGETS[:9]), " %s" % ", ".join(TARGETS),
" %s" % ", ".join(TARGETS[9:]),
" -i, --infile=FILE set FILE as the input file name ('-' for STDIN)", " -i, --infile=FILE set FILE as the input file name ('-' for STDIN)",
" -o, --outfile=FILE set FILE as the output file name ('-' for STDOUT) ", " -o, --outfile=FILE set FILE as the output file name ('-' for STDOUT) ",
" --toc add an automatic Table of Contents to the output" " --toc add a table of contents to the output",
, " -n, --enum-title enumerate all titles as 1, 1.1, 1.1.1, etc.",
" --toc-level=N set maximum TOC level (depth) to N", " --style=FILE use FILE as the document style (e.g., a CSS file)
" --toc-only print the Table of Contents and exit", ",
" -n, --enum-title enumerate all titles as 1, 1.1, 1.1.1, etc", " -H, --no-headers omit header and footer from output",
" --style=FILE use FILE as the document style (like HTML CSS)",
" -H, --no-headers suppress header and footer from the output",
" --mask-email hide email from spam robots. x@y.z turns <x (a) y
z>",
" -C, --config-file=F read configuration from file F", " -C, --config-file=F read configuration from file F",
" -q, --quiet quiet mode, suppress all output (except errors)", " -q, --quiet suppress all output (except errors)",
" -v, --verbose print informative messages during conversion", " -v, --verbose print informative messages during conversion",
" -h, --help print this help information and exit", " -h, --help print this help text and exit",
" -V, --version print program version and exit", " -V, --version print program version and exit",
"", "",
"Turn OFF options:", "Turn off options:",
" --no-enum-title, --no-headers, --no-infile,", " --no-enum-title, --headers, --no-quiet,",
" --no-mask-email, --no-outfile, --no-quiet, --no-rc, --no-slides,", " --no-rc, --no-style, --no-toc",
" --no-style, --no-targets, --no-toc, --no-toc-only",
"", "",
"Example:", "Example:",
" {} -t html --toc {}".format(my_name, "file.t2t"), " {} -t html --toc {}".format(my_name, "file.t2t"),
"", "",
"By default, converted output is saved to 'infile.<target>'.", "By default, converted output is saved to 'infile.<target>'.",
"Use --outfile to force an output file name.", "Use --outfile to force an output file name.",
"If input file is '-', reads from STDIN.", "If input file is '-', read from STDIN.",
"If output file is '-', dumps output to STDOUT.", "If output file is '-', dump output to STDOUT.",
"", "",
my_url, my_url,
"", "",
] ]
) )
############################################################################## ##############################################################################
# Here is all the target's templates # Here is all the target's templates
# You may edit them to fit your needs # You may edit them to fit your needs
skipping to change at line 244 skipping to change at line 234
%(HEADER2)s %(HEADER2)s
%(HEADER3)s %(HEADER3)s
""", """,
"sgml": """\ "sgml": """\
<!doctype linuxdoc system> <!doctype linuxdoc system>
<article> <article>
<title>%(HEADER1)s <title>%(HEADER1)s
<author>%(HEADER2)s <author>%(HEADER2)s
<date>%(HEADER3)s <date>%(HEADER3)s
""", """,
# HTML5 reference code:
# https://github.com/h5bp/html5-boilerplate/blob/master/index.html
# https://github.com/murtaugh/HTML5-Reset/blob/master/index.html
"html": """\ "html": """\
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="%(ENCODING)s"> <meta charset="%(ENCODING)s">
<title>%(HEADER1)s</title> <title>%(HEADER1)s</title>
<meta name="generator" content="http://txt2tags.org"> <meta name="generator" content="https://txt2tags.org">
<link rel="stylesheet" href="%(STYLE)s"> <link rel="stylesheet" href="%(STYLE)s">
<style> <style type="text/css">
body{background-color:#fff;color:#000;} blockquote{margin: 1em 2em; border-left: 2px solid #999;
font-style: oblique; padding-left: 1em;}
blockquote:first-letter{margin: .2em .1em .1em 0; font-size: 160%%; font-weight:
bold;}
blockquote:first-line{font-weight: bold;}
body{font-family: sans-serif;}
hr{background-color:#000;border:0;color:#000;} hr{background-color:#000;border:0;color:#000;}
hr.heavy{height:5px;} hr.heavy{height:2px;}
hr.light{height:1px;} hr.light{height:1px;}
img{border:0;display:block;} img{border:0;display:block;}
img.right{margin:0 0 0 auto;} img.right{margin:0 0 0 auto;}
img.center{border:0;margin:0 auto;} img.center{border:0;margin:0 auto;}
table th,table td{padding:4px;} table{border-collapse: collapse;}
.center,header{text-align:center;} table th,table td{padding: 3px 7px 2px 7px;}
table.center {margin-left:auto; margin-right:auto;} table th{background-color: lightgrey;}
table.center{margin-left:auto; margin-right:auto;}
.center{text-align:center;}
.right{text-align:right;} .right{text-align:right;}
.left{text-align:left;} .left{text-align:left;}
.tableborder,.tableborder td,.tableborder th{border:1px solid #000;} .tableborder,.tableborder td,.tableborder th{border:1px solid #000;}
.underline{text-decoration:underline;} .underline{text-decoration:underline;}
</style> </style>
</head> </head>
<body> <body>
<header> <header>
<hgroup> <hgroup>
<h1>%(HEADER1)s</h1> <h1>%(HEADER1)s</h1>
skipping to change at line 2066 skipping to change at line 2059
ret.append(["all", "infile", infile]) ret.append(["all", "infile", infile])
# Apply 'ignore' and 'filter_' rules (filter_ is stronger) # Apply 'ignore' and 'filter_' rules (filter_ is stronger)
if ignore or filter_: if ignore or filter_:
filtered = [] filtered = []
for target, name, value in ret: for target, name, value in ret:
if (filter_ and name in filter_) or (ignore and name not in igno re): if (filter_ and name in filter_) or (ignore and name not in igno re):
filtered.append([target, name, value]) filtered.append([target, name, value])
ret = filtered[:] ret = filtered[:]
# Add the original command line string as 'realcmdline'
ret.append(["all", "realcmdline", cmdline])
return ret return ret
############################################################################## ##############################################################################
class SourceDocument: class SourceDocument:
""" """
SourceDocument class - scan document structure, extract data SourceDocument class - scan document structure, extract data
It knows about full files. It reads a file and identify all It knows about full files. It reads a file and identify all
the areas beginning (Head,Conf,Body). With this info it can the areas beginning (Head,Conf,Body). With this info it can
skipping to change at line 2229 skipping to change at line 2219
This class is the configuration master. It knows how to handle This class is the configuration master. It knows how to handle
the RAW and PARSED config format. It also performs the sanity the RAW and PARSED config format. It also performs the sanity
checking for a given configuration. checking for a given configuration.
DATA: DATA:
self.raw - Stores the config on the RAW format self.raw - Stores the config on the RAW format
self.parsed - Stores the config on the PARSED format self.parsed - Stores the config on the PARSED format
self.defaults - Stores the default values for all keys self.defaults - Stores the default values for all keys
self.off - Stores the OFF values for all keys self.off - Stores the OFF values for all keys
self.multi - List of keys which can have multiple values self.multi - List of keys which can have multiple values
self.numeric - List of keys which value must be a number
self.incremental - List of keys which are incremental self.incremental - List of keys which are incremental
RAW FORMAT: RAW FORMAT:
The RAW format is a list of lists, being each mother list item The RAW format is a list of lists, being each mother list item
a full configuration entry. Any entry is a 3 item list, on a full configuration entry. Any entry is a 3 item list, on
the following format: [ TARGET, KEY, VALUE ] the following format: [ TARGET, KEY, VALUE ]
Being a list, the order is preserved, so it's easy to use Being a list, the order is preserved, so it's easy to use
different kinds of configs, as CONF area and command line, different kinds of configs, as CONF area and command line,
respecting the precedence. respecting the precedence.
The special target 'all' is used when no specific target was The special target 'all' is used when no specific target was
skipping to change at line 2268 skipping to change at line 2257
{'enum-title': 1, 'headers': 0} {'enum-title': 1, 'headers': 0}
""" """
def __init__(self, raw=None, target=""): def __init__(self, raw=None, target=""):
self.raw = raw or [] self.raw = raw or []
self.target = target self.target = target
self.parsed = {} self.parsed = {}
self.dft_options = OPTIONS.copy() self.dft_options = OPTIONS.copy()
self.dft_flags = FLAGS.copy() self.dft_flags = FLAGS.copy()
self.dft_actions = ACTIONS.copy() self.dft_actions = ACTIONS.copy()
self.dft_settings = SETTINGS.copy()
self.defaults = self._get_defaults() self.defaults = self._get_defaults()
self.off = self._get_off() self.off = self._get_off()
self.incremental = ["verbose"] self.incremental = ["verbose"]
self.numeric = ["toc-level"]
self.multi = ["infile", "preproc", "postproc", "options", "style"] self.multi = ["infile", "preproc", "postproc", "options", "style"]
def _get_defaults(self): def _get_defaults(self):
"Get the default values for all config/options/flags" "Get the default values for all config/options/flags"
empty = {} empty = {}
for kw in CONFIG_KEYWORDS: for kw in CONFIG_KEYWORDS:
empty[kw] = "" empty[kw] = ""
empty.update(self.dft_options) empty.update(self.dft_options)
empty.update(self.dft_flags) empty.update(self.dft_flags)
empty.update(self.dft_actions) empty.update(self.dft_actions)
empty.update(self.dft_settings)
empty["realcmdline"] = "" # internal use only
empty["sourcefile"] = "" # internal use only empty["sourcefile"] = "" # internal use only
return empty return empty
def _get_off(self): def _get_off(self):
"Turns OFF all the config/options/flags" "Turns OFF all the config/options/flags"
off = {} off = {}
for key in self.defaults.keys(): for key in self.defaults.keys():
kind = type(self.defaults[key]) kind = type(self.defaults[key])
if kind == int: if kind == int:
off[key] = 0 off[key] = 0
skipping to change at line 2406 skipping to change at line 2391
"No target specified (try --help)." "No target specified (try --help)."
+ "\n\n" + "\n\n"
+ "Please select a target using the -t option or the %!target co mmand." + "Please select a target using the -t option or the %!target co mmand."
+ "\n" + "\n"
+ "Example:" + "Example:"
+ " {} -t html {}".format(my_name, "file.t2t") + " {} -t html {}".format(my_name, "file.t2t")
+ "\n\n" + "\n\n"
+ "Run 'txt2tags --targets' to see all available targets." + "Run 'txt2tags --targets' to see all available targets."
) )
# And of course, an infile also # And of course, an infile also
# TODO#1: It seems that this checking is never reached if "infile" not in config:
if not config.get("infile"):
Error("Missing input file (try --help)") Error("Missing input file (try --help)")
# Is the target valid? # Is the target valid?
if not TARGETS.count(target): if not TARGETS.count(target):
Error( Error(
"Invalid target '%s'" % target "Invalid target '%s'" % target
+ "\n\n" + "\n\n"
+ "Run 'txt2tags --targets' to see all the available targets." + "Run 'txt2tags --targets' to see all the available targets."
) )
# Ensure all keys are present # Ensure all keys are present
empty = self.defaults.copy() empty = self.defaults.copy()
empty.update(config) empty.update(config)
config = empty.copy() config = empty.copy()
# Check integers options
for key in config.keys():
if key in self.numeric:
try:
config[key] = int(config[key])
except ValueError:
Error("--%s value must be a number" % key)
# --toc-only is stronger than others
if config["toc-only"]:
config["headers"] = 0
config["toc"] = 0
config["outfile"] = config["outfile"] or STDOUT
# Restore target # Restore target
config["target"] = target config["target"] = target
# Set output file name # Set output file name
config["outfile"] = self.get_outfile_name(config) config["outfile"] = self.get_outfile_name(config)
# Checking suicide # Checking suicide
if os.path.abspath(config["sourcefile"]) == os.path.abspath( if os.path.abspath(config["sourcefile"]) == os.path.abspath(
config["outfile"] config["outfile"]
) and config["outfile"] not in [STDOUT, MODULEOUT]: ) and config["outfile"] not in [STDOUT, MODULEOUT]:
Error("Input and Output files are the same: %s" % config["outfile"]) Error("Input and Output files are the same: %s" % config["outfile"])
return config return config
skipping to change at line 2896 skipping to change at line 2868
self.count[i] = 0 self.count[i] = 0
# Compose count id from hierarchy # Compose count id from hierarchy
for i in range(self.level): for i in range(self.level):
count_id = "%s%d." % (count_id, self.count[i + 1]) count_id = "%s%d." % (count_id, self.count[i + 1])
self.count_id = count_id self.count_id = count_id
def _set_label(self): def _set_label(self):
"Compose and save title label, used by anchors." "Compose and save title label, used by anchors."
# Remove invalid chars from label set by user # Remove invalid chars from label set by user
self.label = re.sub("[^A-Za-z0-9_-]", "", self.label or "") self.label = re.sub("[^A-Za-z0-9_-]", "", self.label or "")
# Generate name as 15 first :alnum: chars
# TODO how to translate safely accented chars to plain?
# self.label = re.sub('[^A-Za-z0-9]', '', self.txt)[:15]
# 'tocN' label - sequential count, ignoring 'toc-level'
# self.label = self.anchor_prefix + str(len(self.toc)+1)
def _get_tagged_anchor(self): def _get_tagged_anchor(self):
"Return anchor if user defined a label, or TOC is on." "Return anchor if user defined a label, or TOC is on."
ret = "" ret = ""
label = self.label label = self.label
if CONF["toc"] and self.level <= CONF["toc-level"]: if CONF["toc"]:
# This count is needed bcos self.toc stores all
# titles, regardless of the 'toc-level' setting,
# so we can't use self.toc length to number anchors
self.anchor_count += 1 self.anchor_count += 1
# Autonumber label (if needed) # Autonumber label (if needed)
label = label or "{}{}".format(self.anchor_prefix, self.anchor_count ) label = label or "{}{}".format(self.anchor_prefix, self.anchor_count )
if label and TAGS["anchor"]: if label and TAGS["anchor"]:
ret = regex["x"].sub(label, TAGS["anchor"]) ret = regex["x"].sub(label, TAGS["anchor"])
return ret return ret
def _get_full_title_text(self): def _get_full_title_text(self):
"Returns the full title contents, already escaped." "Returns the full title contents, already escaped."
ret = self.txt ret = self.txt
skipping to change at line 2961 skipping to change at line 2925
ret.append("") # blank line before ret.append("") # blank line before
ret.append(tagged) ret.append(tagged)
# Get the right letter count for UTF # Get the right letter count for UTF
if isinstance(full_title, bytes): if isinstance(full_title, bytes):
full_title = full_title.decode(ENCODING) full_title = full_title.decode(ENCODING)
ret.append(regex["x"].sub("=" * len(full_title), self.tag)) ret.append(regex["x"].sub("=" * len(full_title), self.tag))
else: else:
ret.append(tagged) ret.append(tagged)
return ret return ret
def dump_marked_toc(self, max_level=99): def dump_marked_toc(self):
"Dumps all toc itens as a valid t2t-marked list" "Dumps all toc itens as a valid t2t-marked list"
ret = [] ret = []
toc_count = 1 toc_count = 1
for level, count_id, txt, label in self.toc: for level, count_id, txt, label in self.toc:
if level > max_level:
continue # ignore
indent = " " * level indent = " " * level
id_txt = ("{} {}".format(count_id, txt)).lstrip() id_txt = ("{} {}".format(count_id, txt)).lstrip()
label = label or self.anchor_prefix + repr(toc_count) label = label or self.anchor_prefix + repr(toc_count)
toc_count += 1 toc_count += 1
# TOC will have crosslinks to anchors # TOC will have crosslinks to anchors
if TAGS["anchor"]: if TAGS["anchor"]:
if CONF["enum-title"] and level == 1: if CONF["enum-title"] and level == 1:
# 1. [Foo #anchor] is more readable than [1. Foo #anchor] in level 1. # 1. [Foo #anchor] is more readable than [1. Foo #anchor] in level 1.
# This is a stoled idea from Windows .CHM help files. # This is an idea stolen from Windows .CHM help files.
tocitem = '{}+ [""{}"" #{}]'.format(indent, txt, label) tocitem = '{}+ [""{}"" #{}]'.format(indent, txt, label)
else: else:
tocitem = '{}- [""{}"" #{}]'.format(indent, id_txt, label) tocitem = '{}- [""{}"" #{}]'.format(indent, id_txt, label)
# TOC will be plain text (no links) # TOC will be plain text (no links)
else: else:
if TARGET in ["txt", "man"]: if TARGET in ["txt", "man"]:
# For these, the list is not necessary, just dump the text # For these, the list is not necessary, just dump the text
tocitem = '{}""{}""'.format(indent, id_txt) tocitem = '{}""{}""'.format(indent, id_txt)
else: else:
skipping to change at line 3776 skipping to change at line 3738
return result return result
############################################################################## ##############################################################################
def listTargets(): def listTargets():
"""List available targets.""" """List available targets."""
for target, name in sorted(TARGET_NAMES.items()): for target, name in sorted(TARGET_NAMES.items()):
print("{:8}{}".format(target, name)) print("{:8}{}".format(target, name))
def dumpConfig(source_raw, parsed_config):
onoff = {1: "ON", 0: "OFF"}
data = [
("RC file", RC_RAW),
("source document", source_raw),
("command line", CMDLINE_RAW),
]
# First show all RAW data found
for label, cfg in data:
print("RAW config for %s" % label)
for target, key, val in cfg:
target = "(%s)" % target
key = dotted_spaces("%-14s" % key)
val = val or "ON"
print(" {:<8} {}: {}".format(target, key, val))
print()
# Then the parsed results of all of them
print("Full PARSED config")
keys = list(parsed_config.keys())
keys.sort() # sorted
for key in keys:
val = parsed_config[key]
# Filters are the last
if key == "preproc" or key == "postproc":
continue
# Flag beautifier
if key in list(FLAGS.keys()) or key in list(ACTIONS.keys()):
val = onoff.get(val) or val
# List beautifier
if isinstance(val, list):
if key == "options":
sep = " "
else:
sep = ", "
val = sep.join(val)
print("{:>25}: {}".format(dotted_spaces("%-14s" % key), val))
print()
print("Active filters")
for filter_ in ["preproc", "postproc"]:
for rule in parsed_config.get(filter_) or []:
print(
"%25s: %s -> %s"
% (dotted_spaces("%-14s" % filter_), rule[0], rule[1])
)
def get_file_body(file_): def get_file_body(file_):
"Returns all the document BODY lines" "Returns all the document BODY lines"
return process_source_file(file_, noconf=1)[1][2] return process_source_file(file_, noconf=1)[1][2]
def finish_him(outlist, config): def finish_him(outlist, config):
"Writing output to screen or file" "Writing output to screen or file"
outfile = config["outfile"] outfile = config["outfile"]
outlist = unmaskEscapeChar(outlist) outlist = unmaskEscapeChar(outlist)
outlist = expandLineBreaks(outlist) outlist = expandLineBreaks(outlist)
skipping to change at line 3859 skipping to change at line 3776
for line in outlist: for line in outlist:
print(line) print(line)
else: else:
Message("Saving results to the output file", 1) Message("Saving results to the output file", 1)
Savefile(outfile, outlist) Savefile(outfile, outlist)
if not QUIET: if not QUIET:
print("{} wrote {}".format(my_name, outfile)) print("{} wrote {}".format(my_name, outfile))
def toc_tagger(toc, config): def toc_tagger(toc, config):
"Returns the tagged TOC, as a single tag or a tagged list" "Returns the tagged TOC, as a single tag or a tagged list"
ret = [] if not config["toc"]:
return []
elif TAGS["TOC"]:
# Our TOC list is not needed, the target already knows how to do a TOC
ret = [TAGS["TOC"]]
# Convert the TOC list (t2t-marked) to the target's list format # Convert the TOC list (t2t-marked) to the target's list format
if config["toc-only"] or (config["toc"] and not TAGS["TOC"]): else:
fakeconf = config.copy() fakeconf = config.copy()
fakeconf["headers"] = 0 fakeconf["headers"] = 0
fakeconf["toc-only"] = 0
fakeconf["mask-email"] = 0
fakeconf["preproc"] = [] fakeconf["preproc"] = []
fakeconf["postproc"] = [] fakeconf["postproc"] = []
ret, _ = convert(toc, fakeconf) ret, _ = convert(toc, fakeconf)
set_global_config(config) # restore config set_global_config(config) # restore config
# Our TOC list is not needed, the target already knows how to do a TOC
elif config["toc"] and TAGS["TOC"]:
ret = [TAGS["TOC"]]
return ret return ret
def toc_formatter(toc, config): def toc_formatter(toc, config):
"Formats TOC for automatic placement between headers and body" "Formats TOC for automatic placement between headers and body"
if config["toc-only"]:
return toc # no formatting needed
if not config["toc"]: if not config["toc"]:
return [] # TOC disabled return [] # TOC disabled
ret = toc ret = toc
# TOC open/close tags (if any) # TOC open/close tags (if any)
if TAGS["tocOpen"]: if TAGS["tocOpen"]:
ret.insert(0, TAGS["tocOpen"]) ret.insert(0, TAGS["tocOpen"])
if TAGS["tocClose"]: if TAGS["tocClose"]:
ret.append(TAGS["tocClose"]) ret.append(TAGS["tocClose"])
skipping to change at line 4120 skipping to change at line 4034
guessurl = "http://" + url guessurl = "http://" + url
else: else:
guessurl = "ftp://" + url guessurl = "ftp://" + url
# Not link aware targets -> protocol is useless # Not link aware targets -> protocol is useless
if not rules["linkable"]: if not rules["linkable"]:
guessurl = "" guessurl = ""
# Simple link (not guessed) # Simple link (not guessed)
if not label and not guessurl: if not label and not guessurl:
if CONF["mask-email"] and linktype == "email": # Just add link data to tag
# Do the email mask feature (no TAGs, just text) tag = TAGS[linktype]
url = url.replace("@", " (a) ") ret = regex["x"].sub(url, tag)
url = url.replace(".", " ")
url = "<%s>" % url
if rules["linkable"]:
url = doEscape(target, url)
ret = url
else:
# Just add link data to tag
tag = TAGS[linktype]
ret = regex["x"].sub(url, tag)
# Named link or guessed simple link # Named link or guessed simple link
else: else:
# Adjusts for guessed link # Adjusts for guessed link
if not label: if not label:
label = url # no protocol label = url # no protocol
if guessurl: if guessurl:
url = guessurl # with protocol url = guessurl # with protocol
# Image inside link! # Image inside link!
if image_re.match(label): if image_re.match(label):
if rules["imglinkable"]: # get image tag if rules["imglinkable"]: # get image tag
label = parse_images(label) label = parse_images(label)
else: else:
# img@link !supported # img@link !supported
label = "(%s)" % image_re.match(label).group(1) label = "(%s)" % image_re.match(label).group(1)
skipping to change at line 4571 skipping to change at line 4476
targ, key, val = ConfigLines().parse_line(line, None, target) targ, key, val = ConfigLines().parse_line(line, None, target)
if key: if key:
Debug("Found config '{}', value '{}'".format(key, val), 1, linen r) Debug("Found config '{}', value '{}'".format(key, val), 1, linen r)
else: else:
Debug("Bogus Special Line", 1, linenr) Debug("Bogus Special Line", 1, linenr)
# %!include command # %!include command
if key == "include": if key == "include":
incpath = os.path.dirname(CONF["sourcefile"]) incpath = os.path.dirname(CONF["sourcefile"])
incfile = val incfile = val
err = "A file cannot include itself (loop!)" err = "A file cannot include itself (loop!)"
if CONF["sourcefile"] == incfile: if CONF["sourcefile"] == incfile:
Error("{}: {}".format(err, incfile)) Error("{}: {}".format(err, incfile))
inctype, inclines = get_include_contents(incfile, incpath) inctype, inclines = get_include_contents(incfile, incpath)
# Verb, raw and tagged are easy # Verb, raw and tagged are easy
if inctype != "t2t": if inctype != "t2t":
ret.extend(BLOCK.blockin(inctype)) ret.extend(BLOCK.blockin(inctype))
skipping to change at line 4840 skipping to change at line 4744
# Maybe close some opened title area? # Maybe close some opened title area?
if rules["titleblocks"]: if rules["titleblocks"]:
ret.extend(TITLE.close_all()) ret.extend(TITLE.close_all())
# Maybe a major tag to enclose body? (like DIV for CSS) # Maybe a major tag to enclose body? (like DIV for CSS)
if TAGS["bodyOpen"]: if TAGS["bodyOpen"]:
ret.insert(0, TAGS["bodyOpen"]) ret.insert(0, TAGS["bodyOpen"])
if TAGS["bodyClose"]: if TAGS["bodyClose"]:
ret.append(TAGS["bodyClose"]) ret.append(TAGS["bodyClose"])
if CONF["toc-only"]: marked_toc = TITLE.dump_marked_toc()
ret = []
marked_toc = TITLE.dump_marked_toc(CONF["toc-level"])
return ret, marked_toc return ret, marked_toc
def exec_command_line(user_cmdline=None): def exec_command_line(user_cmdline=None):
global CMDLINE_RAW, RC_RAW, DEBUG, VERBOSE, QUIET, Error global CMDLINE_RAW, RC_RAW, DEBUG, VERBOSE, QUIET, Error
# Extract command line data # Extract command line data
cmdline_data = user_cmdline or sys.argv[1:] cmdline_data = user_cmdline or sys.argv[1:]
CMDLINE_RAW = CommandLine().get_raw_config(cmdline_data, relative=True) CMDLINE_RAW = CommandLine().get_raw_config(cmdline_data, relative=True)
cmdline_parsed = ConfigMaster(CMDLINE_RAW).parse() cmdline_parsed = ConfigMaster(CMDLINE_RAW).parse()
 End of changes. 41 change blocks. 
145 lines changed or deleted 47 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)