📄 docfixer.py
字号:
node.parentNode.normalize()
lastchild = node.lastChild
before, after = wsmap[node.tagName]
if lastchild.nodeType == TEXT:
data = lastchild.data.rstrip() + before
lastchild.data = data
norm = 0
if wsmap[node.tagName]:
nextnode = node.nextSibling
if nextnode and nextnode.nodeType == TEXT:
nextnode.data = after + nextnode.data.lstrip()
else:
wsnode = doc.createTextNode(after)
node.parentNode.insertBefore(wsnode, nextnode)
# hack to get the title in place:
if node.tagName == "title" \
and node.parentNode.firstChild.nodeType == ELEMENT:
node.parentNode.insertBefore(doc.createTextNode("\n "),
node.parentNode.firstChild)
node.parentNode.normalize()
def normalize(doc):
for node in doc.childNodes:
if node.nodeType == ELEMENT:
node.normalize()
def cleanup_trailing_parens(doc, element_names):
d = {}
for gi in element_names:
d[gi] = gi
rewrite_element = d.has_key
queue = [node for node in doc.childNodes if node.nodeType == ELEMENT]
while queue:
node = queue[0]
del queue[0]
if rewrite_element(node.tagName):
lastchild = node.lastChild
if lastchild and lastchild.nodeType == TEXT:
data = lastchild.data
if data.endswith("()"):
lastchild.data = data[:-2]
else:
for child in node.childNodes:
if child.nodeType == ELEMENT:
queue.append(child)
def contents_match(left, right):
left_children = left.childNodes
right_children = right.childNodes
if len(left_children) != len(right_children):
return 0
for l, r in map(None, left_children, right_children):
nodeType = l.nodeType
if nodeType != r.nodeType:
return 0
if nodeType == ELEMENT:
if l.tagName != r.tagName:
return 0
# should check attributes, but that's not a problem here
if not contents_match(l, r):
return 0
elif nodeType == TEXT:
if l.data != r.data:
return 0
else:
# not quite right, but good enough
return 0
return 1
def create_module_info(doc, section):
# Heavy.
node = extract_first_element(section, "modulesynopsis")
if node is None:
return
set_tagName(node, "synopsis")
lastchild = node.childNodes[-1]
if lastchild.nodeType == TEXT \
and lastchild.data[-1:] == ".":
lastchild.data = lastchild.data[:-1]
modauthor = extract_first_element(section, "moduleauthor")
if modauthor:
set_tagName(modauthor, "author")
modauthor.appendChild(doc.createTextNode(
modauthor.getAttribute("name")))
modauthor.removeAttribute("name")
platform = extract_first_element(section, "platform")
if section.tagName == "section":
modinfo_pos = 2
modinfo = doc.createElement("moduleinfo")
moddecl = extract_first_element(section, "declaremodule")
name = None
if moddecl:
modinfo.appendChild(doc.createTextNode("\n "))
name = moddecl.attributes["name"].value
namenode = doc.createElement("name")
namenode.appendChild(doc.createTextNode(name))
modinfo.appendChild(namenode)
type = moddecl.attributes.get("type")
if type:
type = type.value
modinfo.appendChild(doc.createTextNode("\n "))
typenode = doc.createElement("type")
typenode.appendChild(doc.createTextNode(type))
modinfo.appendChild(typenode)
versionadded = extract_first_element(section, "versionadded")
if versionadded:
modinfo.setAttribute("added", versionadded.getAttribute("version"))
title = get_first_element(section, "title")
if title:
children = title.childNodes
if len(children) >= 2 \
and children[0].nodeName == "module" \
and children[0].childNodes[0].data == name:
# this is it; morph the <title> into <short-synopsis>
first_data = children[1]
if first_data.data[:4] == " ---":
first_data.data = first_data.data[4:].lstrip()
set_tagName(title, "short-synopsis")
if children[-1].nodeType == TEXT \
and children[-1].data[-1:] == ".":
children[-1].data = children[-1].data[:-1]
section.removeChild(title)
section.removeChild(section.childNodes[0])
title.removeChild(children[0])
modinfo_pos = 0
else:
ewrite("module name in title doesn't match"
" <declaremodule/>; no <short-synopsis/>\n")
else:
ewrite("Unexpected condition: <section/> without <title/>\n")
modinfo.appendChild(doc.createTextNode("\n "))
modinfo.appendChild(node)
if title and not contents_match(title, node):
# The short synopsis is actually different,
# and needs to be stored:
modinfo.appendChild(doc.createTextNode("\n "))
modinfo.appendChild(title)
if modauthor:
modinfo.appendChild(doc.createTextNode("\n "))
modinfo.appendChild(modauthor)
if platform:
modinfo.appendChild(doc.createTextNode("\n "))
modinfo.appendChild(platform)
modinfo.appendChild(doc.createTextNode("\n "))
section.insertBefore(modinfo, section.childNodes[modinfo_pos])
section.insertBefore(doc.createTextNode("\n "), modinfo)
#
# The rest of this removes extra newlines from where we cut out
# a lot of elements. A lot of code for minimal value, but keeps
# keeps the generated *ML from being too funny looking.
#
section.normalize()
children = section.childNodes
for i in range(len(children)):
node = children[i]
if node.nodeName == "moduleinfo":
nextnode = children[i+1]
if nextnode.nodeType == TEXT:
data = nextnode.data
s = data.lstrip()
if len(s) < (len(data) - 4):
nextnode.data = "\n\n\n" + s
def cleanup_synopses(doc, fragment):
for node in find_all_elements(fragment, "section"):
create_module_info(doc, node)
def fixup_table_structures(doc, fragment):
for table in find_all_elements(fragment, "table"):
fixup_table(doc, table)
def fixup_table(doc, table):
# create the table head
thead = doc.createElement("thead")
row = doc.createElement("row")
move_elements_by_name(doc, table, row, "entry")
thead.appendChild(doc.createTextNode("\n "))
thead.appendChild(row)
thead.appendChild(doc.createTextNode("\n "))
# create the table body
tbody = doc.createElement("tbody")
prev_row = None
last_was_hline = 0
children = table.childNodes
for child in children:
if child.nodeType == ELEMENT:
tagName = child.tagName
if tagName == "hline" and prev_row is not None:
prev_row.setAttribute("rowsep", "1")
elif tagName == "row":
prev_row = child
# save the rows:
tbody.appendChild(doc.createTextNode("\n "))
move_elements_by_name(doc, table, tbody, "row", sep="\n ")
# and toss the rest:
while children:
child = children[0]
nodeType = child.nodeType
if nodeType == TEXT:
if child.data.strip():
raise ConversionError("unexpected free data in <%s>: %r"
% (table.tagName, child.data))
table.removeChild(child)
continue
if nodeType == ELEMENT:
if child.tagName != "hline":
raise ConversionError(
"unexpected <%s> in table" % child.tagName)
table.removeChild(child)
continue
raise ConversionError(
"unexpected %s node in table" % child.__class__.__name__)
# nothing left in the <table>; add the <thead> and <tbody>
tgroup = doc.createElement("tgroup")
tgroup.appendChild(doc.createTextNode("\n "))
tgroup.appendChild(thead)
tgroup.appendChild(doc.createTextNode("\n "))
tgroup.appendChild(tbody)
tgroup.appendChild(doc.createTextNode("\n "))
table.appendChild(tgroup)
# now make the <entry>s look nice:
for row in table.getElementsByTagName("row"):
fixup_row(doc, row)
def fixup_row(doc, row):
entries = []
map(entries.append, row.childNodes[1:])
for entry in entries:
row.insertBefore(doc.createTextNode("\n "), entry)
# row.appendChild(doc.createTextNode("\n "))
def move_elements_by_name(doc, source, dest, name, sep=None):
nodes = []
for child in source.childNodes:
if child.nodeName == name:
nodes.append(child)
for node in nodes:
source.removeChild(node)
dest.appendChild(node)
if sep:
dest.appendChild(doc.createTextNode(sep))
RECURSE_INTO_PARA_CONTAINERS = (
"chapter", "abstract", "enumerate",
"section", "subsection", "subsubsection",
"paragraph", "subparagraph", "back-matter",
"howto", "manual",
"item", "itemize", "fulllineitems", "enumeration", "descriptionlist",
"definitionlist", "definition",
)
PARA_LEVEL_ELEMENTS = (
"moduleinfo", "title", "verbatim", "enumerate", "item",
"interpreter-session", "back-matter", "interactive-session",
"opcodedesc", "classdesc", "datadesc",
"cfuncdesc", "ctypedesc", "cvardesc",
"funcdesc", "methoddesc", "excdesc", "memberdesc", "membderdescni",
"funcdescni", "methoddescni", "excdescni",
"tableii", "tableiii", "tableiv", "localmoduletable",
"sectionauthor", "seealso", "itemize",
# include <para>, so we can just do it again to get subsequent paras:
PARA_ELEMENT,
)
PARA_LEVEL_PRECEEDERS = (
"setindexsubitem", "author",
"stindex", "obindex", "COMMENT", "label", "xi:include", "title",
"versionadded", "versionchanged", "declaremodule", "modulesynopsis",
"moduleauthor", "indexterm", "leader",
)
def fixup_paras(doc, fragment):
for child in fragment.childNodes:
if child.nodeName in RECURSE_INTO_PARA_CONTAINERS:
fixup_paras_helper(doc, child)
descriptions = find_all_elements(fragment, "description")
for description in descriptions:
fixup_paras_helper(doc, description)
def fixup_paras_helper(doc, container, depth=0):
# document is already normalized
children = container.childNodes
start = skip_leading_nodes(children)
while len(children) > start:
if children[start].nodeName in RECURSE_INTO_PARA_CONTAINERS:
# Something to recurse into:
fixup_paras_helper(doc, children[start])
else:
# Paragraph material:
build_para(doc, container, start, len(children))
if DEBUG_PARA_FIXER and depth == 10:
sys.exit(1)
start = skip_leading_nodes(children, start + 1)
def build_para(doc, parent, start, i):
children = parent.childNodes
after = start + 1
have_last = 0
BREAK_ELEMENTS = PARA_LEVEL_ELEMENTS + RECURSE_INTO_PARA_CONTAINERS
# Collect all children until \n\n+ is found in a text node or a
# member of BREAK_ELEMENTS is found.
for j in range(start, i):
after = j + 1
child = children[j]
nodeType = child.nodeType
if nodeType == ELEMENT:
if child.tagName in BREAK_ELEMENTS:
after = j
break
elif nodeType == TEXT:
pos = child.data.find("\n\n")
if pos == 0:
after = j
break
if pos >= 1:
child.splitText(pos)
break
else:
have_last = 1
if (start + 1) > after:
raise ConversionError(
"build_para() could not identify content to turn into a paragraph")
if children[after - 1].nodeType == TEXT:
# we may need to split off trailing white space:
child = children[after - 1]
data = child.data
if data.rstrip() != data:
have_last = 0
child.splitText(len(data.rstrip()))
para = doc.createElement(PARA_ELEMENT)
prev = None
indexes = range(start, after)
indexes.reverse()
for j in indexes:
node = parent.childNodes[j]
parent.removeChild(node)
para.insertBefore(node, prev)
prev = node
if have_last:
parent.appendChild(para)
parent.appendChild(doc.createTextNode("\n\n"))
return len(parent.childNodes)
else:
nextnode = parent.childNodes[start]
if nextnode.nodeType == TEXT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -