mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-08-26 12:46:08 +00:00
doc: wikiparser: Preserve spaces during parsing and generation
- Matches the original XML more accurately and simplifies some parsing. Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
parent
aa27037c71
commit
d760ee004f
@ -166,10 +166,7 @@ class Paragraph(Element):
|
|||||||
xml = ''
|
xml = ''
|
||||||
|
|
||||||
for item_xml in items_xml:
|
for item_xml in items_xml:
|
||||||
if item_xml[0] in '.,:;-_!?':
|
|
||||||
xml += item_xml
|
xml += item_xml
|
||||||
else:
|
|
||||||
xml += ' ' + item_xml
|
|
||||||
|
|
||||||
return f'<para>{xml}</para>'
|
return f'<para>{xml}</para>'
|
||||||
|
|
||||||
@ -555,7 +552,6 @@ def split_formatted(text, delimiter, end_delimiter=None):
|
|||||||
Return (formatted_text, remaining_text) if it is found.
|
Return (formatted_text, remaining_text) if it is found.
|
||||||
Return (None, text) otherwise.
|
Return (None, text) otherwise.
|
||||||
"""
|
"""
|
||||||
text = text.strip()
|
|
||||||
end_delimiter = end_delimiter or delimiter
|
end_delimiter = end_delimiter or delimiter
|
||||||
content = None
|
content = None
|
||||||
if text.startswith(delimiter):
|
if text.startswith(delimiter):
|
||||||
@ -698,7 +694,6 @@ def parse_text(line, context=None, parse_links=True):
|
|||||||
content = re.split(r"''|`|{{|__|\[\[", line)[0]
|
content = re.split(r"''|`|{{|__|\[\[", line)[0]
|
||||||
if content:
|
if content:
|
||||||
line = line.replace(content, '', 1)
|
line = line.replace(content, '', 1)
|
||||||
content = content.strip()
|
|
||||||
result += parse_plain_text(content, parse_links=parse_links)
|
result += parse_plain_text(content, parse_links=parse_links)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -711,7 +706,6 @@ def parse_plain_text(content, parse_links=True):
|
|||||||
"""Parse a line or plain text and generate plain text and URL objects."""
|
"""Parse a line or plain text and generate plain text and URL objects."""
|
||||||
result = []
|
result = []
|
||||||
while content:
|
while content:
|
||||||
content = content.strip()
|
|
||||||
wiki_link_match = re.search(
|
wiki_link_match = re.search(
|
||||||
r'(?: |^)([A-Z][a-z0-9]+([A-Z][a-z0-9]+)+)(?: |$)', content)
|
r'(?: |^)([A-Z][a-z0-9]+([A-Z][a-z0-9]+)+)(?: |$)', content)
|
||||||
link_match = re.search(r'(https?://[^<> ]+[^<> .:\(\)])', content)
|
link_match = re.search(r'(https?://[^<> ]+[^<> .:\(\)])', content)
|
||||||
@ -737,9 +731,6 @@ def parse_plain_text(content, parse_links=True):
|
|||||||
# Replace occurrences of !WikiText with WikiText
|
# Replace occurrences of !WikiText with WikiText
|
||||||
text = re.sub(r'([^A-Za-z]|^)!', r'\g<1>', text)
|
text = re.sub(r'([^A-Za-z]|^)!', r'\g<1>', text)
|
||||||
|
|
||||||
# Gobble multiple spaces
|
|
||||||
text = re.sub(r' +', r' ', text)
|
|
||||||
|
|
||||||
result.append(PlainText(text))
|
result.append(PlainText(text))
|
||||||
|
|
||||||
if end:
|
if end:
|
||||||
@ -755,8 +746,8 @@ def parse_table_row(line, context=None):
|
|||||||
row_cells = re.split(r'\|\|', line)[1:-1]
|
row_cells = re.split(r'\|\|', line)[1:-1]
|
||||||
row_items = []
|
row_items = []
|
||||||
for cell in row_cells:
|
for cell in row_cells:
|
||||||
content = cell.strip()
|
content = cell
|
||||||
if content:
|
if content.strip():
|
||||||
# remove <tablestyle=...> that was already processed
|
# remove <tablestyle=...> that was already processed
|
||||||
content = re.sub('<tablestyle=[^>]+>', '', content)
|
content = re.sub('<tablestyle=[^>]+>', '', content)
|
||||||
align = None
|
align = None
|
||||||
@ -804,8 +795,21 @@ def parse_list(list_data, context=None):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
content = list_data.pop(0)[2]
|
content = list_data.pop(0)[2]
|
||||||
|
new_content = ''
|
||||||
|
in_code_block = False
|
||||||
|
for line in content.splitlines(True):
|
||||||
|
if line.startswith(' ' * current_level) and not in_code_block:
|
||||||
|
line = line[current_level:]
|
||||||
|
|
||||||
|
if line.strip().startswith('{{{'):
|
||||||
|
in_code_block = True
|
||||||
|
elif line.strip().startswith('}}}'):
|
||||||
|
in_code_block = False
|
||||||
|
|
||||||
|
new_content += line
|
||||||
|
|
||||||
parsed_list.add_item(
|
parsed_list.add_item(
|
||||||
ListItem(parse_wiki(content, context),
|
ListItem(parse_wiki(new_content, context),
|
||||||
override_marker=override_marker))
|
override_marker=override_marker))
|
||||||
|
|
||||||
return parsed_list, list_data
|
return parsed_list, list_data
|
||||||
@ -889,19 +893,20 @@ def parse_wiki(text, context=None, begin_marker=None, end_marker=None):
|
|||||||
>>> parse_wiki(' plain multispaced text ')
|
>>> parse_wiki(' plain multispaced text ')
|
||||||
[Paragraph([PlainText(' plain multispaced text ')])]
|
[Paragraph([PlainText(' plain multispaced text ')])]
|
||||||
>>> parse_wiki('https://freedombox.org')
|
>>> parse_wiki('https://freedombox.org')
|
||||||
[Paragraph([Url('https://freedombox.org')])]
|
[Paragraph([Url('https://freedombox.org'), PlainText(' ')])]
|
||||||
>>> parse_wiki("''italic''")
|
>>> parse_wiki("''italic''")
|
||||||
[Paragraph([ItalicText('italic')])]
|
[Paragraph([ItalicText('italic'), PlainText(' ')])]
|
||||||
>>> parse_wiki("'''bold'''")
|
>>> parse_wiki("'''bold'''")
|
||||||
[Paragraph([BoldText('bold')])]
|
[Paragraph([BoldText('bold'), PlainText(' ')])]
|
||||||
>>> parse_wiki("normal text followed by '''bold text'''")
|
>>> parse_wiki("normal text followed by '''bold text'''")
|
||||||
[Paragraph([PlainText('normal text followed by'), BoldText('bold text')])]
|
[Paragraph([PlainText('normal text followed by '), BoldText('bold text'), \
|
||||||
|
PlainText(' ')])]
|
||||||
>>> parse_wiki('`monospace`')
|
>>> parse_wiki('`monospace`')
|
||||||
[Paragraph([MonospaceText('monospace')])]
|
[Paragraph([MonospaceText('monospace'), PlainText(' ')])]
|
||||||
>>> parse_wiki('{{{code}}}')
|
>>> parse_wiki('{{{code}}}')
|
||||||
[Paragraph([CodeText('code')])]
|
[Paragraph([CodeText('code'), PlainText(' ')])]
|
||||||
>>> parse_wiki('__underline__')
|
>>> parse_wiki('__underline__')
|
||||||
[Paragraph([UnderlineText('underline')])]
|
[Paragraph([UnderlineText('underline'), PlainText(' ')])]
|
||||||
>>> parse_wiki('~-smaller text-~')
|
>>> parse_wiki('~-smaller text-~')
|
||||||
[Paragraph([SmallerTextWarning(), PlainText('smaller text ')])]
|
[Paragraph([SmallerTextWarning(), PlainText('smaller text ')])]
|
||||||
>>> parse_wiki('!FreedomBox')
|
>>> parse_wiki('!FreedomBox')
|
||||||
@ -914,36 +919,38 @@ def parse_wiki(text, context=None, begin_marker=None, end_marker=None):
|
|||||||
>>> parse_wiki('[[attachment:Searx.webm|Searx installation and first steps\
|
>>> parse_wiki('[[attachment:Searx.webm|Searx installation and first steps\
|
||||||
|&do=get]]')
|
|&do=get]]')
|
||||||
[Paragraph([Link('attachment:Searx.webm', \
|
[Paragraph([Link('attachment:Searx.webm', \
|
||||||
[PlainText('Searx installation and first steps')], '&do=get')])]
|
[PlainText('Searx installation and first steps')], '&do=get'), \
|
||||||
|
PlainText(' ')])]
|
||||||
>>> parse_wiki('[[https://onionshare.org/|Onionshare]]')
|
>>> parse_wiki('[[https://onionshare.org/|Onionshare]]')
|
||||||
[Paragraph([Link('https://onionshare.org/', [PlainText('Onionshare')])])]
|
[Paragraph([Link('https://onionshare.org/', [PlainText('Onionshare')]), \
|
||||||
|
PlainText(' ')])]
|
||||||
|
|
||||||
>>> parse_wiki('/!\\\\')
|
>>> parse_wiki('/!\\\\')
|
||||||
[Paragraph([EmbeddedAttachment('icons/alert.png', \
|
[Paragraph([EmbeddedAttachment('icons/alert.png', \
|
||||||
[PlainText('icons/alert.png')], 'height=20')])]
|
[PlainText('icons/alert.png')], 'height=20'), PlainText(' ')])]
|
||||||
>>> parse_wiki('(./)')
|
>>> parse_wiki('(./)')
|
||||||
[Paragraph([EmbeddedAttachment('icons/checkmark.png', \
|
[Paragraph([EmbeddedAttachment('icons/checkmark.png', \
|
||||||
[PlainText('icons/checkmark.png')], 'height=20')])]
|
[PlainText('icons/checkmark.png')], 'height=20'), PlainText(' ')])]
|
||||||
>>> parse_wiki('{X}')
|
>>> parse_wiki('{X}')
|
||||||
[Paragraph([EmbeddedAttachment('icons/icon-error.png', \
|
[Paragraph([EmbeddedAttachment('icons/icon-error.png', \
|
||||||
[PlainText('icons/icon-error.png')], 'height=20')])]
|
[PlainText('icons/icon-error.png')], 'height=20'), PlainText(' ')])]
|
||||||
>>> parse_wiki('{i}')
|
>>> parse_wiki('{i}')
|
||||||
[Paragraph([EmbeddedAttachment('icons/icon-info.png', \
|
[Paragraph([EmbeddedAttachment('icons/icon-info.png', \
|
||||||
[PlainText('icons/icon-info.png')], 'height=20')])]
|
[PlainText('icons/icon-info.png')], 'height=20'), PlainText(' ')])]
|
||||||
>>> parse_wiki('{o}')
|
>>> parse_wiki('{o}')
|
||||||
[Paragraph([EmbeddedAttachment('icons/star_off.png', \
|
[Paragraph([EmbeddedAttachment('icons/star_off.png', \
|
||||||
[PlainText('icons/star_off.png')], 'height=20')])]
|
[PlainText('icons/star_off.png')], 'height=20'), PlainText(' ')])]
|
||||||
>>> parse_wiki('{*}')
|
>>> parse_wiki('{*}')
|
||||||
[Paragraph([EmbeddedAttachment('icons/star_on.png', \
|
[Paragraph([EmbeddedAttachment('icons/star_on.png', \
|
||||||
[PlainText('icons/star_on.png')], 'height=20')])]
|
[PlainText('icons/star_on.png')], 'height=20'), PlainText(' ')])]
|
||||||
|
|
||||||
>>> parse_wiki('{{attachment:cockpit-enable.png}}')
|
>>> parse_wiki('{{attachment:cockpit-enable.png}}')
|
||||||
[Paragraph([EmbeddedAttachment('cockpit-enable.png', \
|
[Paragraph([EmbeddedAttachment('cockpit-enable.png', \
|
||||||
[PlainText('cockpit-enable.png')])])]
|
[PlainText('cockpit-enable.png')]), PlainText(' ')])]
|
||||||
>>> parse_wiki('{{attachment:Backups_Step1_v49.png|Backups: Step 1|\
|
>>> parse_wiki('{{attachment:Backups_Step1_v49.png|Backups: Step 1|\
|
||||||
width=800}}')
|
width=800}}')
|
||||||
[Paragraph([EmbeddedAttachment('Backups_Step1_v49.png', \
|
[Paragraph([EmbeddedAttachment('Backups_Step1_v49.png', \
|
||||||
[PlainText('Backups: Step 1')], 'width=800')])]
|
[PlainText('Backups: Step 1')], 'width=800'), PlainText(' ')])]
|
||||||
|
|
||||||
>>> parse_wiki(' * single item')
|
>>> parse_wiki(' * single item')
|
||||||
[List('bulleted', [ListItem([Paragraph([PlainText('single item ')])])])]
|
[List('bulleted', [ListItem([Paragraph([PlainText('single item ')])])])]
|
||||||
@ -1042,7 +1049,8 @@ to /plinth')])])]
|
|||||||
preformatted text (source code)\\n}}}''')
|
preformatted text (source code)\\n}}}''')
|
||||||
[CodeText('multi-line\\npreformatted text (source code)')]
|
[CodeText('multi-line\\npreformatted text (source code)')]
|
||||||
>>> parse_wiki('text to introduce {{{ a singleliner}}}')
|
>>> parse_wiki('text to introduce {{{ a singleliner}}}')
|
||||||
[Paragraph([PlainText('text to introduce'), CodeText(' a singleliner')])]
|
[Paragraph([PlainText('text to introduce '), CodeText(' a singleliner'),\
|
||||||
|
PlainText(' ')])]
|
||||||
>>> parse_wiki('text to introduce\\n{{{\\n a multiliner\\nstarting at\
|
>>> parse_wiki('text to introduce\\n{{{\\n a multiliner\\nstarting at\
|
||||||
\\n different indents.\\n}}}')
|
\\n different indents.\\n}}}')
|
||||||
[Paragraph([PlainText('text to introduce ')]), \
|
[Paragraph([PlainText('text to introduce ')]), \
|
||||||
@ -1074,9 +1082,9 @@ 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 but \
|
[Paragraph([PlainText(' If this command shows an error such as new key \
|
||||||
contains no user ID - skipped, then use a different keyserver to download the \
|
but contains no user ID - skipped, then use a different keyserver to download \
|
||||||
keys:')]), CodeText('$ gpg --keyserver keys.gnupg.net --recv-keys \
|
the keys: ')]), CodeText('$ 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')]
|
keys.gnupg.net --recv-keys 013D86D8BA32EAB4A6691BF85D4153D6FE188FC8')]
|
||||||
@ -1120,7 +1128,7 @@ calendar/addressbook')])])])])])])])]
|
|||||||
{{attachment:freedombox-screenshot-home.png|Home Page|width=300}}]]')
|
{{attachment:freedombox-screenshot-home.png|Home Page|width=300}}]]')
|
||||||
[Paragraph([Link('attachment:freedombox-screenshot-home.png', \
|
[Paragraph([Link('attachment:freedombox-screenshot-home.png', \
|
||||||
[EmbeddedAttachment('freedombox-screenshot-home.png', \
|
[EmbeddedAttachment('freedombox-screenshot-home.png', \
|
||||||
[PlainText('Home Page')], 'width=300')])])]
|
[PlainText('Home Page')], 'width=300')]), PlainText(' ')])]
|
||||||
|
|
||||||
>>> parse_wiki(" * New wiki and manual content licence: \
|
>>> parse_wiki(" * New wiki and manual content licence: \
|
||||||
''[[https://creativecommons.org/licenses/by-sa/4.0/|Creative Commons \
|
''[[https://creativecommons.org/licenses/by-sa/4.0/|Creative Commons \
|
||||||
@ -1133,8 +1141,8 @@ PlainText('(from June 13rd 2016).')])])])]
|
|||||||
>>> parse_wiki('An alternative to downloading these images is to \
|
>>> parse_wiki('An alternative to downloading these images is to \
|
||||||
[[InstallingDebianOn/TI/BeagleBone|install Debian]] on the !BeagleBone and \
|
[[InstallingDebianOn/TI/BeagleBone|install Debian]] on the !BeagleBone and \
|
||||||
then [[FreedomBox/Hardware/Debian|install FreedomBox]] on it.')
|
then [[FreedomBox/Hardware/Debian|install FreedomBox]] on it.')
|
||||||
[Paragraph([PlainText('An alternative to downloading these images is to'),\
|
[Paragraph([PlainText('An alternative to downloading these images is to ')\
|
||||||
Link('InstallingDebianOn/TI/BeagleBone', [PlainText('install Debian')]), \
|
, Link('InstallingDebianOn/TI/BeagleBone', [PlainText('install Debian')]), \
|
||||||
PlainText(' on the BeagleBone and then '), Link('FreedomBox/Hardware/Debian', \
|
PlainText(' on the BeagleBone and then '), Link('FreedomBox/Hardware/Debian', \
|
||||||
[PlainText('install FreedomBox')]), PlainText(' on it. ')])]
|
[PlainText('install FreedomBox')]), PlainText(' on it. ')])]
|
||||||
|
|
||||||
@ -1144,7 +1152,8 @@ existing accounts or \\"Create ...\\" in case of new accounts (see the second \
|
|||||||
screenshot below).\\n 1. Check the checkboxes for the address books and \
|
screenshot below).\\n 1. Check the checkboxes for the address books and \
|
||||||
calendars you want to synchronize and click on the sync button in the header. \
|
calendars you want to synchronize and click on the sync button in the header. \
|
||||||
(see the third screenshot below)")
|
(see the third screenshot below)")
|
||||||
[Paragraph([BoldText('Synchronizing contacts')]), List('numbered', \
|
[Paragraph([BoldText('Synchronizing contacts'), PlainText(' ')]), \
|
||||||
|
List('numbered', \
|
||||||
[ListItem([Paragraph([PlainText('Click on the hamburger menus of CalDAV and \
|
[ListItem([Paragraph([PlainText('Click on the hamburger menus of CalDAV and \
|
||||||
CardDAV and select either "Refresh ..." in case of existing accounts or \
|
CardDAV and select either "Refresh ..." in case of existing accounts or \
|
||||||
"Create ..." in case of new accounts (see the second screenshot below). ')])]),\
|
"Create ..." in case of new accounts (see the second screenshot below). ')])]),\
|
||||||
@ -1171,12 +1180,12 @@ PlainText('and not just the username like'), ItalicText('exampleuser'), \
|
|||||||
PlainText(". Enter the address of your email service's IMAP server address in \
|
PlainText(". Enter the address of your email service's IMAP server address in \
|
||||||
the "), ItalicText('Server'), PlainText(' field. You can try providing your \
|
the "), ItalicText('Server'), PlainText(' field. You can try providing your \
|
||||||
domain name here such as '), ItalicText('example.org'), PlainText(' for email \
|
domain name here such as '), ItalicText('example.org'), PlainText(' for email \
|
||||||
address'), ItalicText('exampleuser@example.org'), PlainText("and if this does \
|
address '), ItalicText('exampleuser@example.org'), PlainText(" and if this \
|
||||||
not work, consult your email provider's documentation for the address of the \
|
does not work, consult your email provider's documentation for the address \
|
||||||
IMAP server. Using encrypted connection to your IMAP server is strongly \
|
of the IMAP server. Using encrypted connection to your IMAP server is \
|
||||||
recommended. To do this, prepend 'imaps://' at the beginning of your IMAP \
|
strongly recommended. To do this, prepend 'imaps://' at the beginning of \
|
||||||
server address. For example,"), ItalicText('imaps://imap.example.org'), \
|
your IMAP server address. For example, "), \
|
||||||
PlainText('.')])]
|
ItalicText('imaps://imap.example.org'), PlainText('. ')])]
|
||||||
|
|
||||||
>>> parse_wiki('Tor Browser is the recommended way to browse the web \
|
>>> parse_wiki('Tor Browser is the recommended way to browse the web \
|
||||||
using Tor. You can download the Tor Browser from \
|
using Tor. You can download the Tor Browser from \
|
||||||
@ -1207,18 +1216,23 @@ MICRO|width=235,height=132}}]]<<BR>> [[FreedomBox/Hardware/A20-OLinuXino-MICRO\
|
|||||||
|A20 OLinuXino MICRO]] ||<style="text-align: center;"> [[FreedomBox/Hardware/\
|
|A20 OLinuXino MICRO]] ||<style="text-align: center;"> [[FreedomBox/Hardware/\
|
||||||
APU|{{attachment:apu1d_thumb.jpg|PC Engines APU|width=235,height=157}}]]<<BR>>\
|
APU|{{attachment:apu1d_thumb.jpg|PC Engines APU|width=235,height=157}}]]<<BR>>\
|
||||||
[[FreedomBox/Hardware/APU|PC Engines APU]] ||')
|
[[FreedomBox/Hardware/APU|PC Engines APU]] ||')
|
||||||
[Table([TableRow([TableItem([Paragraph([Link('FreedomBox/Hardware/\
|
[Table([TableRow([TableItem([Paragraph([PlainText(' '), \
|
||||||
A20-OLinuXino-Lime2', [EmbeddedAttachment('a20-olinuxino-lime2_thumb.jpg', [\
|
Link('FreedomBox/Hardware/A20-OLinuXino-Lime2', \
|
||||||
PlainText('A20 OLinuXino Lime2')], 'width=235,height=159')])]), Paragraph([\
|
[EmbeddedAttachment('a20-olinuxino-lime2_thumb.jpg', \
|
||||||
Link('FreedomBox/Hardware/A20-OLinuXino-Lime2', [PlainText('A20 OLinuXino \
|
[PlainText('A20 OLinuXino Lime2')], 'width=235,height=159')])]), \
|
||||||
Lime2')])])], 'center'), TableItem([Paragraph([Link('FreedomBox/Hardware/\
|
Paragraph([PlainText(' '), Link('FreedomBox/Hardware/A20-OLinuXino-Lime2', \
|
||||||
A20-OLinuXino-MICRO', [EmbeddedAttachment('a20-olinuxino-micro_thumb.jpg', [\
|
[PlainText('A20 OLinuXino Lime2')]), PlainText(' ')])], 'center'), \
|
||||||
PlainText('A20 OLinuXino MICRO')], 'width=235,height=132')])]), Paragraph([\
|
TableItem([Paragraph([PlainText(' '), \
|
||||||
Link('FreedomBox/Hardware/A20-OLinuXino-MICRO', [PlainText('A20 OLinuXino \
|
Link('FreedomBox/Hardware/A20-OLinuXino-MICRO', \
|
||||||
MICRO')])])], 'center'), TableItem([Paragraph([Link('FreedomBox/Hardware/\
|
[EmbeddedAttachment('a20-olinuxino-micro_thumb.jpg', \
|
||||||
APU', [EmbeddedAttachment('apu1d_thumb.jpg', [PlainText('PC Engines APU')], \
|
[PlainText('A20 OLinuXino MICRO')], 'width=235,height=132')])]), \
|
||||||
'width=235,height=157')])]), Paragraph([Link('FreedomBox/Hardware/APU', [\
|
Paragraph([PlainText(' '), Link('FreedomBox/Hardware/A20-OLinuXino-MICRO', \
|
||||||
PlainText('PC Engines APU')])])], 'center')])])]
|
[PlainText('A20 OLinuXino MICRO')]), PlainText(' ')])], 'center'), \
|
||||||
|
TableItem([Paragraph([PlainText(' '), Link('FreedomBox/Hardware/APU', \
|
||||||
|
[EmbeddedAttachment('apu1d_thumb.jpg', [PlainText('PC Engines APU')], \
|
||||||
|
'width=235,height=157')])]), Paragraph([PlainText(' '), \
|
||||||
|
Link('FreedomBox/Hardware/APU', [PlainText('PC Engines APU')]), \
|
||||||
|
PlainText(' ')])], 'center')])])]
|
||||||
|
|
||||||
>>> parse_wiki(" 1. When created, go to the virtual machine's Settings -> \
|
>>> parse_wiki(" 1. When created, go to the virtual machine's Settings -> \
|
||||||
[Network] -> [Adapter 1]->[Attached to:] and choose the network type your \
|
[Network] -> [Adapter 1]->[Attached to:] and choose the network type your \
|
||||||
@ -1250,8 +1264,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([EmbeddedAttachment('quassel-client-1-connect-to-core.png', \
|
Paragraph([PlainText(' '), \
|
||||||
[PlainText('Connect to Core')], 'width=394')])]), \
|
EmbeddedAttachment('quassel-client-1-connect-to-core.png', \
|
||||||
|
[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. ')])])])]
|
||||||
@ -1264,7 +1279,7 @@ PlainText('dialog.')])])])]
|
|||||||
if begin_marker:
|
if begin_marker:
|
||||||
removed_lines = []
|
removed_lines = []
|
||||||
while lines:
|
while lines:
|
||||||
line = lines.pop(0).strip()
|
line = lines.pop(0)
|
||||||
removed_lines.append(line)
|
removed_lines.append(line)
|
||||||
if line.startswith(begin_marker):
|
if line.startswith(begin_marker):
|
||||||
break
|
break
|
||||||
@ -1375,7 +1390,8 @@ PlainText('dialog.')])])])]
|
|||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
next_list_item += '\n' + line
|
next_list_item += '\n' + line
|
||||||
elif candidate.strip().startswith('{{'):
|
elif (candidate.strip().startswith('{{')
|
||||||
|
and next_list_item[-1] != '\n'):
|
||||||
# Add line break before inline image
|
# Add line break before inline image
|
||||||
next_list_item += ' <<BR>>\n' + lines.pop(0)
|
next_list_item += ' <<BR>>\n' + lines.pop(0)
|
||||||
else:
|
else:
|
||||||
@ -1396,7 +1412,7 @@ PlainText('dialog.')])])])]
|
|||||||
list_type = ListType.BULLETED
|
list_type = ListType.BULLETED
|
||||||
else:
|
else:
|
||||||
list_type = ListType.NUMBERED
|
list_type = ListType.NUMBERED
|
||||||
content = line.lstrip(match.group(2) + ' ')
|
content = ' ' * indent + line.lstrip(match.group(2) + ' ')
|
||||||
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)
|
||||||
@ -1457,13 +1473,17 @@ PlainText('dialog.')])])])]
|
|||||||
if line.strip():
|
if line.strip():
|
||||||
texts = []
|
texts = []
|
||||||
br = '<<BR>>'
|
br = '<<BR>>'
|
||||||
texts.extend(parse_text(line.rstrip(br), context))
|
space_line = line.rstrip(br) if br in line else line + ' '
|
||||||
|
texts.extend(parse_text(space_line, context))
|
||||||
if br not in line:
|
if br not in line:
|
||||||
# Collect text until next empty line is reached.
|
# Collect text until next empty line is reached.
|
||||||
while lines and lines[0].strip():
|
while lines and lines[0].strip():
|
||||||
if end_marker and lines[0].strip().startswith(end_marker):
|
if end_marker and lines[0].strip().startswith(end_marker):
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if br in line:
|
||||||
|
break
|
||||||
|
|
||||||
# If any of the syntax that ends a paragraph
|
# If any of the syntax that ends a paragraph
|
||||||
paragraph_breakers = ['{{{', '##', '----', '||']
|
paragraph_breakers = ['{{{', '##', '----', '||']
|
||||||
if any([
|
if any([
|
||||||
@ -1476,7 +1496,8 @@ PlainText('dialog.')])])])]
|
|||||||
break
|
break
|
||||||
|
|
||||||
line = lines.pop(0)
|
line = lines.pop(0)
|
||||||
texts.extend(parse_text(line.rstrip(br), context))
|
space_line = line.rstrip(br) if br in line else line + ' '
|
||||||
|
texts.extend(parse_text(space_line, context))
|
||||||
|
|
||||||
elements.append(Paragraph(texts))
|
elements.append(Paragraph(texts))
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user