mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-20 10:34:30 +00:00
doc: wikiparser: Allow lists to started with just spaces
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
4fd5d0e73b
commit
5aa31266e2
@ -274,6 +274,7 @@ class ListType(Enum):
|
|||||||
PLAIN = 1
|
PLAIN = 1
|
||||||
BULLETED = 2
|
BULLETED = 2
|
||||||
NUMBERED = 3
|
NUMBERED = 3
|
||||||
|
SPACED = 4
|
||||||
|
|
||||||
|
|
||||||
class List(Element):
|
class List(Element):
|
||||||
@ -284,8 +285,10 @@ class List(Element):
|
|||||||
self.list_type = ListType.PLAIN
|
self.list_type = ListType.PLAIN
|
||||||
elif list_type == 'bulleted':
|
elif list_type == 'bulleted':
|
||||||
self.list_type = ListType.BULLETED
|
self.list_type = ListType.BULLETED
|
||||||
else:
|
elif list_type == 'numbered':
|
||||||
self.list_type = ListType.NUMBERED
|
self.list_type = ListType.NUMBERED
|
||||||
|
else:
|
||||||
|
self.list_type = ListType.SPACED
|
||||||
else:
|
else:
|
||||||
self.list_type = list_type
|
self.list_type = list_type
|
||||||
|
|
||||||
@ -296,8 +299,10 @@ class List(Element):
|
|||||||
list_type = 'plain'
|
list_type = 'plain'
|
||||||
elif self.list_type == ListType.BULLETED:
|
elif self.list_type == ListType.BULLETED:
|
||||||
list_type = 'bulleted'
|
list_type = 'bulleted'
|
||||||
else:
|
elif self.list_type == ListType.NUMBERED:
|
||||||
list_type = 'numbered'
|
list_type = 'numbered'
|
||||||
|
else:
|
||||||
|
list_type = 'spaced'
|
||||||
|
|
||||||
return super().__repr__(list_type, self.items)
|
return super().__repr__(list_type, self.items)
|
||||||
|
|
||||||
@ -309,8 +314,10 @@ class List(Element):
|
|||||||
xml = '<itemizedlist>'
|
xml = '<itemizedlist>'
|
||||||
elif self.list_type == ListType.BULLETED:
|
elif self.list_type == ListType.BULLETED:
|
||||||
xml = '<itemizedlist>'
|
xml = '<itemizedlist>'
|
||||||
else:
|
elif self.list_type == ListType.NUMBERED:
|
||||||
xml = '<orderedlist numeration="arabic">'
|
xml = '<orderedlist numeration="arabic">'
|
||||||
|
else:
|
||||||
|
xml = '<itemizedlist>'
|
||||||
|
|
||||||
for item in self.items:
|
for item in self.items:
|
||||||
xml += item.to_docbook(context)
|
xml += item.to_docbook(context)
|
||||||
@ -319,8 +326,10 @@ class List(Element):
|
|||||||
xml += '</itemizedlist>'
|
xml += '</itemizedlist>'
|
||||||
elif self.list_type == ListType.BULLETED:
|
elif self.list_type == ListType.BULLETED:
|
||||||
xml += '</itemizedlist>'
|
xml += '</itemizedlist>'
|
||||||
else:
|
elif self.list_type == ListType.NUMBERED:
|
||||||
xml += '</orderedlist>'
|
xml += '</orderedlist>'
|
||||||
|
else:
|
||||||
|
xml += '</itemizedlist>'
|
||||||
|
|
||||||
return xml
|
return xml
|
||||||
|
|
||||||
@ -811,7 +820,7 @@ def parse_list(list_data, context=None):
|
|||||||
list_type = list_data[0][0]
|
list_type = list_data[0][0]
|
||||||
current_level = list_data[0][1]
|
current_level = list_data[0][1]
|
||||||
parsed_list = List(list_type)
|
parsed_list = List(list_type)
|
||||||
override_marker = True if list_type == ListType.PLAIN else False
|
override_marker = (list_type in (ListType.PLAIN, ListType.SPACED))
|
||||||
while list_data:
|
while list_data:
|
||||||
level = list_data[0][1]
|
level = list_data[0][1]
|
||||||
if level > current_level:
|
if level > current_level:
|
||||||
@ -920,7 +929,8 @@ def parse_wiki(text, context=None, begin_marker=None, end_marker=None):
|
|||||||
>>> parse_wiki('plain text')
|
>>> parse_wiki('plain text')
|
||||||
[Paragraph([PlainText('plain text ')])]
|
[Paragraph([PlainText('plain text ')])]
|
||||||
>>> parse_wiki(' plain multispaced text ')
|
>>> parse_wiki(' plain multispaced text ')
|
||||||
[Paragraph([PlainText(' plain multispaced text ')])]
|
[List('spaced', [ListItem([Paragraph([PlainText(\
|
||||||
|
'plain multispaced text ')])])])]
|
||||||
>>> parse_wiki('https://freedombox.org')
|
>>> parse_wiki('https://freedombox.org')
|
||||||
[Paragraph([Url('https://freedombox.org'), PlainText(' ')])]
|
[Paragraph([Url('https://freedombox.org'), PlainText(' ')])]
|
||||||
>>> parse_wiki("''italic''")
|
>>> parse_wiki("''italic''")
|
||||||
@ -1087,7 +1097,7 @@ preformatted text (source code)\\n}}}''')
|
|||||||
\\n different indents.\\n}}}')
|
\\n different indents.\\n}}}')
|
||||||
[Paragraph([PlainText('text to introduce ')]), \
|
[Paragraph([PlainText('text to introduce ')]), \
|
||||||
CodeText(' a multiliner\\nstarting at\\n different indents.')]
|
CodeText(' a multiliner\\nstarting at\\n different indents.')]
|
||||||
>>> parse_wiki('Blah, blah:\\n {{{\\nmulti-line\\nformatted text\\n\
|
>>> parse_wiki('Blah, blah:\\n{{{\\nmulti-line\\nformatted text\\n\
|
||||||
starting at col #1\\n}}}')
|
starting at col #1\\n}}}')
|
||||||
[Paragraph([PlainText('Blah, blah: ')]), \
|
[Paragraph([PlainText('Blah, blah: ')]), \
|
||||||
CodeText('multi-line\\nformatted text\\nstarting at col #1')]
|
CodeText('multi-line\\nformatted text\\nstarting at col #1')]
|
||||||
@ -1100,10 +1110,11 @@ CodeText('multi-line\\nformatted text\\nstarting at col #1')])])]
|
|||||||
(replace the ip/netmask with the one the router uses)\\n }}}\\n In \
|
(replace the ip/netmask with the one the router uses)\\n }}}\\n In \
|
||||||
most cases you can look at your current IP address, and change the last \
|
most cases you can look at your current IP address, and change the last \
|
||||||
digits with zero to find your home network, like so: XXX.XXX.XXX.0/24')
|
digits with zero to find your home network, like so: XXX.XXX.XXX.0/24')
|
||||||
[CodeText(' nmap -p 80 --open -sV 192.168.0.0/24 (replace the \
|
[List('spaced', [ListItem([CodeText(' nmap -p 80 --open -sV 192.168.\
|
||||||
ip/netmask with the one the router uses)'), Paragraph([PlainText(' In \
|
0.0/24 (replace the ip/netmask with the one the router uses)'), Paragraph(\
|
||||||
most cases you can look at your current IP address, and change the last \
|
[PlainText('In most cases you can look at your current IP address, and \
|
||||||
digits with zero to find your home network, like so: XXX.XXX.XXX.0/24 ')])]
|
change the last digits with zero to find your home network, like so: XXX.XXX\
|
||||||
|
.XXX.0/24 ')])])])]
|
||||||
>>> parse_wiki('text to introduce\\n----\\n<<TableOfContents()>>')
|
>>> parse_wiki('text to introduce\\n----\\n<<TableOfContents()>>')
|
||||||
[Paragraph([PlainText('text to introduce ')]), \
|
[Paragraph([PlainText('text to introduce ')]), \
|
||||||
HorizontalRule(4), TableOfContents()]
|
HorizontalRule(4), TableOfContents()]
|
||||||
@ -1114,12 +1125,13 @@ the keys:\\n {{{\\n$ gpg --keyserver keys.gnupg.net --recv-keys \
|
|||||||
BCBEBD57A11F70B23782BC5736C361440C9BC971\\n$ gpg --keyserver keys.gnupg.net \
|
BCBEBD57A11F70B23782BC5736C361440C9BC971\\n$ gpg --keyserver keys.gnupg.net \
|
||||||
--recv-keys 7D6ADB750F91085589484BE677C0C75E7B650808\\n$ gpg --keyserver \
|
--recv-keys 7D6ADB750F91085589484BE677C0C75E7B650808\\n$ gpg --keyserver \
|
||||||
keys.gnupg.net --recv-keys 013D86D8BA32EAB4A6691BF85D4153D6FE188FC8\\n }}}')
|
keys.gnupg.net --recv-keys 013D86D8BA32EAB4A6691BF85D4153D6FE188FC8\\n }}}')
|
||||||
[Paragraph([PlainText(' If this command shows an error such as new key \
|
[List('spaced', [ListItem([Paragraph([PlainText('If this command shows an \
|
||||||
but contains no user ID - skipped, then use a different keyserver to download \
|
error such as new key but contains no user ID - skipped, then use a different \
|
||||||
the keys: ')]), CodeText('$ gpg --keyserver keys.gnupg.net --recv-keys \
|
keyserver to download the keys: ')]), CodeText('$ gpg --keyserver keys.gnupg.\
|
||||||
BCBEBD57A11F70B23782BC5736C361440C9BC971\\n$ gpg --keyserver keys.gnupg.net \
|
net --recv-keys BCBEBD57A11F70B23782BC5736C361440C9BC971\\n$ gpg --keyserver \
|
||||||
--recv-keys 7D6ADB750F91085589484BE677C0C75E7B650808\\n$ gpg --keyserver \
|
keys.gnupg.net --recv-keys 7D6ADB750F91085589484BE677C0C75E7B650808\\n$ gpg \
|
||||||
keys.gnupg.net --recv-keys 013D86D8BA32EAB4A6691BF85D4153D6FE188FC8')]
|
--keyserver keys.gnupg.net --recv-keys \
|
||||||
|
013D86D8BA32EAB4A6691BF85D4153D6FE188FC8')])])]
|
||||||
|
|
||||||
>>> parse_wiki('User documentation:\\n * List of \
|
>>> parse_wiki('User documentation:\\n * List of \
|
||||||
[[FreedomBox/Features|applications]] offered by !FreedomBox.')
|
[[FreedomBox/Features|applications]] offered by !FreedomBox.')
|
||||||
@ -1296,9 +1308,9 @@ width=394}}\\n\
|
|||||||
List('numbered', \
|
List('numbered', \
|
||||||
[ListItem([Paragraph([PlainText('Launch Quassel Client. You will be greeted \
|
[ListItem([Paragraph([PlainText('Launch Quassel Client. You will be greeted \
|
||||||
with a wizard to '), MonospaceText('Connect to Core'), PlainText('. ')]), \
|
with a wizard to '), MonospaceText('Connect to Core'), PlainText('. ')]), \
|
||||||
Paragraph([PlainText(' '), \
|
List('spaced', [ListItem([Paragraph([\
|
||||||
EmbeddedAttachment('quassel-client-1-connect-to-core.png', \
|
EmbeddedAttachment('quassel-client-1-connect-to-core.png', \
|
||||||
[PlainText('Connect to Core')], 'width=394'), PlainText(' ')])]), \
|
[PlainText('Connect to Core')], 'width=394'), PlainText(' ')])])])]), \
|
||||||
ListItem([Paragraph([PlainText('Click the '), MonospaceText('Add'), \
|
ListItem([Paragraph([PlainText('Click the '), MonospaceText('Add'), \
|
||||||
PlainText(' button to launch '), MonospaceText('Add Core Account'), \
|
PlainText(' button to launch '), MonospaceText('Add Core Account'), \
|
||||||
PlainText(' dialog. ')])])])]
|
PlainText(' dialog. ')])])])]
|
||||||
@ -1321,6 +1333,11 @@ PlainText(' dialog. ')])])])]
|
|||||||
|
|
||||||
while lines:
|
while lines:
|
||||||
line = lines.pop(0)
|
line = lines.pop(0)
|
||||||
|
# Empty line
|
||||||
|
match = re.match(r'^\s+$', line)
|
||||||
|
if match:
|
||||||
|
continue
|
||||||
|
|
||||||
# End of included file
|
# End of included file
|
||||||
if end_marker and line.strip().startswith(end_marker):
|
if end_marker and line.strip().startswith(end_marker):
|
||||||
break # end parsing
|
break # end parsing
|
||||||
@ -1387,17 +1404,31 @@ PlainText(' dialog. ')])])])]
|
|||||||
|
|
||||||
# List
|
# List
|
||||||
list_item_re = re.compile(r'(\s+)(\*|\.|\d\.|I\.|A\.)\s+(.*)')
|
list_item_re = re.compile(r'(\s+)(\*|\.|\d\.|I\.|A\.)\s+(.*)')
|
||||||
match = list_item_re.match(line)
|
space_list_re = re.compile(r'(\s+)')
|
||||||
if match:
|
match = list_item_re.match(line) or space_list_re.match(line)
|
||||||
|
if match or re.match(r'\s+', line):
|
||||||
# Collect lines until end of List is reached.
|
# Collect lines until end of List is reached.
|
||||||
list_lines = []
|
list_lines = []
|
||||||
next_list_item = line
|
next_list_item = line
|
||||||
top_indent = len(match.group(1))
|
top_indent = len(match.group(1))
|
||||||
|
|
||||||
|
if line.strip().startswith('{{{') and '}}}' not in line:
|
||||||
|
# Multi-line code text or admonition may not have expected
|
||||||
|
# indentation
|
||||||
|
while lines:
|
||||||
|
line = lines.pop(0)
|
||||||
|
if line.strip() == '}}}':
|
||||||
|
next_list_item += '\n}}}'
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
next_list_item += '\n' + line
|
||||||
|
|
||||||
while lines:
|
while lines:
|
||||||
candidate = lines[0]
|
candidate = lines[0]
|
||||||
if re.match(r'^ *$', candidate):
|
if re.match(r'^\s*$', candidate):
|
||||||
# Eat up empty lines
|
# Eat up empty lines
|
||||||
next_list_item += '\n' + lines.pop(0)
|
lines.pop(0)
|
||||||
|
next_list_item += '\n'
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not candidate.startswith(' ' * top_indent):
|
if not candidate.startswith(' ' * top_indent):
|
||||||
@ -1417,7 +1448,7 @@ PlainText(' dialog. ')])])])]
|
|||||||
# have expected indentation
|
# have expected indentation
|
||||||
while lines:
|
while lines:
|
||||||
line = lines.pop(0)
|
line = lines.pop(0)
|
||||||
if '}}}' == line.strip():
|
if line.strip() == '}}}':
|
||||||
next_list_item += '\n}}}'
|
next_list_item += '\n}}}'
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
@ -1436,15 +1467,23 @@ PlainText(' dialog. ')])])])]
|
|||||||
list_data = []
|
list_data = []
|
||||||
for line in list_lines:
|
for line in list_lines:
|
||||||
match = list_item_re.match(line)
|
match = list_item_re.match(line)
|
||||||
indent = len(match.group(1))
|
if match:
|
||||||
marker = match.group(2)
|
indent = len(match.group(1))
|
||||||
if marker == '.':
|
marker = match.group(2)
|
||||||
list_type = ListType.PLAIN
|
if marker == '.':
|
||||||
elif '*' in marker:
|
list_type = ListType.PLAIN
|
||||||
list_type = ListType.BULLETED
|
elif '*' in marker:
|
||||||
|
list_type = ListType.BULLETED
|
||||||
|
else:
|
||||||
|
list_type = ListType.NUMBERED
|
||||||
|
|
||||||
|
content = ' ' * indent + line.lstrip(match.group(2) + ' ')
|
||||||
else:
|
else:
|
||||||
list_type = ListType.NUMBERED
|
match = space_list_re.match(line)
|
||||||
content = ' ' * indent + line.lstrip(match.group(2) + ' ')
|
indent = len(match.group(1))
|
||||||
|
list_type = ListType.SPACED
|
||||||
|
content = line
|
||||||
|
|
||||||
list_data.append((list_type, indent, content))
|
list_data.append((list_type, indent, content))
|
||||||
|
|
||||||
new_list, _ = parse_list(list_data, context)
|
new_list, _ = parse_list(list_data, context)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user