mirror of
https://github.com/liberatedsystems/openCom-Companion.git
synced 2025-02-22 17:29:52 +01:00
Removed library
This commit is contained in:
parent
6b2cf01c69
commit
09db4a9328
@ -1,132 +0,0 @@
|
|||||||
# converts some HTML tags to BBCode
|
|
||||||
# pass --debug to save the output to readme.finalpass
|
|
||||||
# may be better off replacing this with html to markdown (and then to bbcode). Lepture recommeds a JS html to markdown converter: sundown
|
|
||||||
from bs4 import BeautifulSoup, NavigableString
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
def handle_font_tag(tag, replacements):
|
|
||||||
"""Handles the conversion of <font> tag with attributes like color and size."""
|
|
||||||
attributes = []
|
|
||||||
if 'color' in tag.attrs:
|
|
||||||
attributes.append(f"COLOR={tag['color']}")
|
|
||||||
if 'size' in tag.attrs:
|
|
||||||
attributes.append(f"SIZE={tag['size']}")
|
|
||||||
if 'face' in tag.attrs:
|
|
||||||
attributes.append(f"FONT={tag['face']}")
|
|
||||||
|
|
||||||
inner_content = ''.join(recursive_html_to_bbcode(child, replacements) for child in tag.children)
|
|
||||||
if attributes:
|
|
||||||
# Nest all attributes. Example: [COLOR=red][SIZE=5]content[/SIZE][/COLOR]
|
|
||||||
for attr in reversed(attributes):
|
|
||||||
inner_content = f"[{attr}]{inner_content}[/{attr.split('=')[0]}]"
|
|
||||||
return inner_content
|
|
||||||
|
|
||||||
def handle_style_tag(tag, replacements):
|
|
||||||
"""Handles the conversion of tags with style attributes like color, size, and font."""
|
|
||||||
attributes = []
|
|
||||||
style = tag.attrs.get('style', '')
|
|
||||||
|
|
||||||
# Extracting CSS properties
|
|
||||||
css_properties = {item.split(':')[0].strip(): item.split(':')[1].strip() for item in style.split(';') if ':' in item}
|
|
||||||
|
|
||||||
# Mapping CSS properties to BBCode
|
|
||||||
if 'color' in css_properties:
|
|
||||||
attributes.append(f"COLOR={css_properties['color']}")
|
|
||||||
if 'font-size' in css_properties:
|
|
||||||
attributes.append(f"SIZE={css_properties['font-size']}")
|
|
||||||
if 'font-family' in css_properties:
|
|
||||||
attributes.append(f"FONT={css_properties['font-family']}")
|
|
||||||
if 'text-decoration' in css_properties and 'line-through' in css_properties['text-decoration']:
|
|
||||||
attributes.append("S") # Assume strike-through
|
|
||||||
if 'text-decoration' in css_properties and 'underline' in css_properties['text-decoration']:
|
|
||||||
attributes.append("U")
|
|
||||||
if 'font-weight' in css_properties:
|
|
||||||
if css_properties['font-weight'].lower() == 'bold' or (css_properties['font-weight'].isdigit() and int(css_properties['font-weight']) >= 700):
|
|
||||||
attributes.append("B") # Assume bold
|
|
||||||
|
|
||||||
inner_content = ''.join(recursive_html_to_bbcode(child, replacements) for child in tag.children)
|
|
||||||
if attributes:
|
|
||||||
# Nest all attributes
|
|
||||||
for attr in reversed(attributes):
|
|
||||||
if '=' in attr: # For attributes with values
|
|
||||||
inner_content = f"[{attr}]{inner_content}[/{attr.split('=')[0]}]"
|
|
||||||
else: # For simple BBCode tags like [B], [I], [U], [S]
|
|
||||||
inner_content = f"[{attr}]{inner_content}[/{attr}]"
|
|
||||||
return inner_content
|
|
||||||
|
|
||||||
def recursive_html_to_bbcode(element):
|
|
||||||
"""Recursively convert HTML elements to BBCode."""
|
|
||||||
bbcode = ''
|
|
||||||
|
|
||||||
if isinstance(element, NavigableString):
|
|
||||||
bbcode += str(element)
|
|
||||||
elif element.name == 'details':
|
|
||||||
# Handle <details> tag
|
|
||||||
summary = element.find('summary')
|
|
||||||
spoiler_title = ''
|
|
||||||
if summary:
|
|
||||||
# Get the summary content and remove the summary element
|
|
||||||
spoiler_title = '=' + ''.join([recursive_html_to_bbcode(child) for child in summary.contents])
|
|
||||||
summary.decompose()
|
|
||||||
|
|
||||||
# Process remaining content
|
|
||||||
content = ''.join([recursive_html_to_bbcode(child) for child in element.contents])
|
|
||||||
bbcode += f'[SPOILER{spoiler_title}]{content}[/SPOILER]'
|
|
||||||
elif element.name == 'summary':
|
|
||||||
# Skip summary tag as it's handled in details
|
|
||||||
return ''
|
|
||||||
else:
|
|
||||||
# Handle other tags or pass through
|
|
||||||
content = ''.join([recursive_html_to_bbcode(child) for child in element.contents])
|
|
||||||
bbcode += content
|
|
||||||
|
|
||||||
return bbcode
|
|
||||||
|
|
||||||
def html_to_bbcode(html):
|
|
||||||
replacements = {
|
|
||||||
'b': 'B',
|
|
||||||
'strong': 'B',
|
|
||||||
'i': 'I',
|
|
||||||
'em': 'I',
|
|
||||||
'u': 'U',
|
|
||||||
's': 'S',
|
|
||||||
'sub': 'SUB',
|
|
||||||
'sup': 'SUP',
|
|
||||||
'p': '', # Handled by default
|
|
||||||
'ul': 'LIST',
|
|
||||||
'ol': 'LIST=1',
|
|
||||||
'li': '*', # Special handling in recursive function
|
|
||||||
'font': '', # To be handled for attributes
|
|
||||||
'blockquote': 'QUOTE',
|
|
||||||
'pre': 'CODE',
|
|
||||||
'code': 'ICODE',
|
|
||||||
'a': 'URL', # Special handling for attributes
|
|
||||||
'img': 'IMG' # Special handling for attributes
|
|
||||||
}
|
|
||||||
|
|
||||||
soup = BeautifulSoup(html, 'html.parser')
|
|
||||||
return recursive_html_to_bbcode(soup)
|
|
||||||
|
|
||||||
def process_html(input_html, debug=False, output_file=None):
|
|
||||||
converted_bbcode = html_to_bbcode(input_html)
|
|
||||||
|
|
||||||
if debug:
|
|
||||||
with open(output_file, 'w', encoding='utf-8') as file:
|
|
||||||
file.write(converted_bbcode)
|
|
||||||
else:
|
|
||||||
return converted_bbcode
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
parser = argparse.ArgumentParser(description="Convert HTML to BBCode with optional debugging output.")
|
|
||||||
parser.add_argument('input_file', type=str, help='Input HTML file path')
|
|
||||||
parser.add_argument('--debug', action='store_true', help='Save output to readme.finalpass for debugging')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
input_file = args.input_file
|
|
||||||
output_file = 'readme.finalpass' if args.debug else None
|
|
||||||
|
|
||||||
with open(input_file, 'r', encoding='utf-8') as file:
|
|
||||||
html_content = file.read()
|
|
||||||
|
|
||||||
# Call the processing function
|
|
||||||
process_html(html_content, debug=args.debug, output_file=output_file)
|
|
@ -1,67 +0,0 @@
|
|||||||
# uses a custom mistune renderer to convert Markdown to BBCode. The custom renderer is defined in the bbcode.py file.
|
|
||||||
# pass --debug to save the output to readme.1stpass (main.py) and readme.finalpass (html2bbcode)
|
|
||||||
# for further debugging, you can convert the markdown file to AST using md2ast.py. Remember to load the plugin(s) you want to test.
|
|
||||||
|
|
||||||
#standard library
|
|
||||||
import argparse
|
|
||||||
import sys
|
|
||||||
import RNS
|
|
||||||
|
|
||||||
# mistune
|
|
||||||
import mistune
|
|
||||||
from mistune.plugins.formatting import strikethrough, mark, superscript, subscript, insert
|
|
||||||
from mistune.plugins.table import table, table_in_list
|
|
||||||
from mistune.plugins.footnotes import footnotes
|
|
||||||
from mistune.plugins.task_lists import task_lists
|
|
||||||
from mistune.plugins.def_list import def_list
|
|
||||||
from mistune.plugins.abbr import abbr
|
|
||||||
from mistune.plugins.spoiler import spoiler
|
|
||||||
|
|
||||||
if RNS.vendor.platformutils.is_android():
|
|
||||||
from .plugins.merge_lists import merge_ordered_lists
|
|
||||||
from .renderers.bbcode import BBCodeRenderer
|
|
||||||
from .html2bbcode import process_html
|
|
||||||
else:
|
|
||||||
from sbapp.md2bbcode.plugins.merge_lists import merge_ordered_lists
|
|
||||||
from sbapp.md2bbcode.renderers.bbcode import BBCodeRenderer
|
|
||||||
from sbapp.md2bbcode.html2bbcode import process_html
|
|
||||||
|
|
||||||
def convert_markdown_to_bbcode(markdown_text, domain):
|
|
||||||
# Create a Markdown parser instance using the custom BBCode renderer
|
|
||||||
markdown_parser = mistune.create_markdown(renderer=BBCodeRenderer(domain=domain), plugins=[strikethrough, mark, superscript, subscript, insert, table, footnotes, task_lists, def_list, abbr, spoiler, table_in_list, merge_ordered_lists])
|
|
||||||
|
|
||||||
# Convert Markdown text to BBCode
|
|
||||||
return markdown_parser(markdown_text)
|
|
||||||
|
|
||||||
def process_readme(markdown_text, domain=None, debug=False):
|
|
||||||
# Convert Markdown to BBCode
|
|
||||||
bbcode_text = convert_markdown_to_bbcode(markdown_text, domain)
|
|
||||||
|
|
||||||
# Convert BBCode formatted as HTML to final BBCode
|
|
||||||
final_bbcode = process_html(bbcode_text, debug, 'readme.finalpass')
|
|
||||||
|
|
||||||
return final_bbcode
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description='Convert Markdown file to BBCode with HTML processing.')
|
|
||||||
parser.add_argument('input', help='Input Markdown file path')
|
|
||||||
parser.add_argument('--domain', help='Domain to prepend to relative URLs')
|
|
||||||
parser.add_argument('--debug', action='store_true', help='Output intermediate results to files for debugging')
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
if args.input == '-':
|
|
||||||
# Read Markdown content from stdin
|
|
||||||
markdown_text = sys.stdin.read()
|
|
||||||
else:
|
|
||||||
with open(args.input, 'r', encoding='utf-8') as md_file:
|
|
||||||
markdown_text = md_file.read()
|
|
||||||
|
|
||||||
# Process the readme and get the final BBCode
|
|
||||||
final_bbcode = process_readme(markdown_text, args.domain, args.debug)
|
|
||||||
|
|
||||||
# Optionally, print final BBCode to console
|
|
||||||
if not args.debug:
|
|
||||||
print(final_bbcode)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@ -1,47 +0,0 @@
|
|||||||
# this is for debugging the custom mistune renderer bbcode.py
|
|
||||||
import argparse
|
|
||||||
import mistune
|
|
||||||
import json # Import the json module for serialization
|
|
||||||
from mistune.plugins.formatting import strikethrough, mark, superscript, subscript, insert
|
|
||||||
from mistune.plugins.table import table, table_in_list
|
|
||||||
from mistune.plugins.footnotes import footnotes
|
|
||||||
from mistune.plugins.task_lists import task_lists
|
|
||||||
from mistune.plugins.def_list import def_list
|
|
||||||
from mistune.plugins.abbr import abbr
|
|
||||||
from mistune.plugins.spoiler import spoiler
|
|
||||||
|
|
||||||
#local
|
|
||||||
from sbapp.md2bbcode.plugins.merge_lists import merge_ordered_lists
|
|
||||||
|
|
||||||
def convert_markdown_to_ast(input_filepath, output_filepath):
|
|
||||||
# Initialize Markdown parser with no renderer to produce an AST
|
|
||||||
markdown_parser = mistune.create_markdown(renderer=None, plugins=[strikethrough, mark, superscript, subscript, insert, table, footnotes, task_lists, def_list, abbr, spoiler, table_in_list, merge_ordered_lists])
|
|
||||||
|
|
||||||
# Read the input Markdown file
|
|
||||||
with open(input_filepath, 'r', encoding='utf-8') as md_file:
|
|
||||||
markdown_text = md_file.read()
|
|
||||||
|
|
||||||
# Convert Markdown text to AST
|
|
||||||
ast_text = markdown_parser(markdown_text)
|
|
||||||
|
|
||||||
# Serialize the AST to a JSON string
|
|
||||||
ast_json = json.dumps(ast_text, indent=4)
|
|
||||||
|
|
||||||
# Write the output AST to a new file in JSON format
|
|
||||||
with open(output_filepath, 'w', encoding='utf-8') as ast_file:
|
|
||||||
ast_file.write(ast_json)
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Create argument parser
|
|
||||||
parser = argparse.ArgumentParser(description='Convert Markdown file to AST file (JSON format).')
|
|
||||||
# Add arguments
|
|
||||||
parser.add_argument('input', help='Input Markdown file path')
|
|
||||||
parser.add_argument('output', help='Output AST file path (JSON format)')
|
|
||||||
# Parse arguments
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# Convert the Markdown to AST using the provided paths
|
|
||||||
convert_markdown_to_ast(args.input, args.output)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
@ -1,83 +0,0 @@
|
|||||||
from typing import Dict, Any, List
|
|
||||||
|
|
||||||
def merge_ordered_lists(md):
|
|
||||||
"""
|
|
||||||
A plugin to merge consecutive "top-level" ordered lists into one,
|
|
||||||
and also attach any intervening code blocks or blank lines to the
|
|
||||||
last list item so that the final BBCode appears as a single list
|
|
||||||
with multiple steps.
|
|
||||||
|
|
||||||
This relies on a few assumptions:
|
|
||||||
1) The only tokens between two ordered lists that should be merged
|
|
||||||
are code blocks or blank lines (not normal paragraphs).
|
|
||||||
2) We want any code block(s) right after a list item to appear in
|
|
||||||
that same bullet item.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def rewrite_tokens(md, state):
|
|
||||||
tokens = state.tokens
|
|
||||||
merged = []
|
|
||||||
i = 0
|
|
||||||
|
|
||||||
while i < len(tokens):
|
|
||||||
token = tokens[i]
|
|
||||||
|
|
||||||
# Check if this token is a top-level ordered list
|
|
||||||
if (
|
|
||||||
token["type"] == "list"
|
|
||||||
and token.get("attrs", {}).get("ordered", False)
|
|
||||||
and token.get("attrs", {}).get("depth", 0) == 0
|
|
||||||
):
|
|
||||||
# Start new merged list
|
|
||||||
current_depth = token["attrs"]["depth"]
|
|
||||||
list_items = list(token["children"]) # bullet items in the first list
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# Continue until we run into something that's not:
|
|
||||||
# another top-level ordered list,
|
|
||||||
# or code blocks / blank lines (which we'll attach to the last bullet).
|
|
||||||
while i < len(tokens):
|
|
||||||
nxt = tokens[i]
|
|
||||||
|
|
||||||
# If there's another ordered list at the same depth, merge its bullet items
|
|
||||||
if (
|
|
||||||
nxt["type"] == "list"
|
|
||||||
and nxt.get("attrs", {}).get("ordered", False)
|
|
||||||
and nxt.get("attrs", {}).get("depth", 0) == current_depth
|
|
||||||
):
|
|
||||||
list_items.extend(nxt["children"])
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# If there's a code block or blank line, attach it to the *last* bullet item.
|
|
||||||
elif nxt["type"] in ["block_code", "blank_line"]:
|
|
||||||
if list_items: # attach to last bullet item, if any
|
|
||||||
list_items[-1]["children"].append(nxt)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
else:
|
|
||||||
# Not a same-depth list or code block—stop merging
|
|
||||||
break
|
|
||||||
|
|
||||||
# Create single merged list token
|
|
||||||
merged.append(
|
|
||||||
{
|
|
||||||
"type": "list",
|
|
||||||
"children": list_items,
|
|
||||||
"attrs": {
|
|
||||||
"ordered": True,
|
|
||||||
"depth": current_depth,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
else:
|
|
||||||
# If not a top-level ordered list, just keep it as-is
|
|
||||||
merged.append(token)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# Replace the old tokens with the merged version
|
|
||||||
state.tokens = merged
|
|
||||||
|
|
||||||
# Attach to before_render_hooks so we can manipulate tokens before rendering
|
|
||||||
md.before_render_hooks.append(rewrite_tokens)
|
|
||||||
return md
|
|
@ -1,240 +0,0 @@
|
|||||||
from mistune.core import BaseRenderer
|
|
||||||
from mistune.util import escape as escape_text, striptags, safe_entity
|
|
||||||
from urllib.parse import urljoin, urlparse
|
|
||||||
|
|
||||||
|
|
||||||
class BBCodeRenderer(BaseRenderer):
|
|
||||||
"""A renderer for converting Markdown to BBCode."""
|
|
||||||
_escape: bool
|
|
||||||
NAME = 'bbcode'
|
|
||||||
|
|
||||||
def __init__(self, escape=False, domain=None):
|
|
||||||
super(BBCodeRenderer, self).__init__()
|
|
||||||
self._escape = escape
|
|
||||||
self.domain = domain
|
|
||||||
|
|
||||||
def render_token(self, token, state):
|
|
||||||
func = self._get_method(token['type'])
|
|
||||||
attrs = token.get('attrs')
|
|
||||||
|
|
||||||
if 'raw' in token:
|
|
||||||
text = token['raw']
|
|
||||||
elif 'children' in token:
|
|
||||||
text = self.render_tokens(token['children'], state)
|
|
||||||
else:
|
|
||||||
if attrs:
|
|
||||||
return func(**attrs)
|
|
||||||
else:
|
|
||||||
return func()
|
|
||||||
|
|
||||||
if attrs:
|
|
||||||
return func(text, **attrs)
|
|
||||||
else:
|
|
||||||
return func(text)
|
|
||||||
|
|
||||||
def safe_url(self, url: str) -> str:
|
|
||||||
# Simple URL sanitization
|
|
||||||
if url.startswith(('javascript:', 'vbscript:', 'data:')):
|
|
||||||
return '#harmful-link'
|
|
||||||
# Check if the URL is absolute by looking for a netloc part in the URL
|
|
||||||
if not urlparse(url).netloc:
|
|
||||||
url = urljoin(self.domain, url)
|
|
||||||
return url
|
|
||||||
|
|
||||||
def text(self, text: str) -> str:
|
|
||||||
if self._escape:
|
|
||||||
return escape_text(text)
|
|
||||||
return text
|
|
||||||
|
|
||||||
def emphasis(self, text: str) -> str:
|
|
||||||
return '[i]' + text + '[/i]'
|
|
||||||
|
|
||||||
def strong(self, text: str) -> str:
|
|
||||||
return '[b]' + text + '[/b]'
|
|
||||||
|
|
||||||
def link(self, text: str, url: str, title=None) -> str:
|
|
||||||
return '[url=' + self.safe_url(url) + ']' + text + '[/url]'
|
|
||||||
|
|
||||||
def image(self, text: str, url: str, title=None) -> str:
|
|
||||||
alt_text = f' alt="{text}"' if text else ''
|
|
||||||
img_tag = f'[img{alt_text}]' + self.safe_url(url) + '[/img]'
|
|
||||||
# Check if alt text starts with 'pixel' and treat it as pixel art
|
|
||||||
if text and text.lower().startswith('pixel'):
|
|
||||||
return f'[pixelate]{img_tag}[/pixelate]'
|
|
||||||
return img_tag
|
|
||||||
|
|
||||||
def codespan(self, text: str) -> str:
|
|
||||||
return '[icode]' + text + '[/icode]'
|
|
||||||
|
|
||||||
def linebreak(self) -> str:
|
|
||||||
return '\n'
|
|
||||||
|
|
||||||
def softbreak(self) -> str:
|
|
||||||
return '\n'
|
|
||||||
|
|
||||||
def inline_html(self, html: str) -> str:
|
|
||||||
if self._escape:
|
|
||||||
return escape_text(html)
|
|
||||||
return html
|
|
||||||
|
|
||||||
def paragraph(self, text: str) -> str:
|
|
||||||
return text + '\n\n'
|
|
||||||
|
|
||||||
def heading(self, text: str, level: int, **attrs) -> str:
|
|
||||||
if 1 <= level <= 3:
|
|
||||||
return f"[HEADING={level}]{text}[/HEADING]\n"
|
|
||||||
else:
|
|
||||||
# Handle cases where level is outside 1-3
|
|
||||||
return f"[HEADING=3]{text}[/HEADING]\n"
|
|
||||||
|
|
||||||
def blank_line(self) -> str:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def thematic_break(self) -> str:
|
|
||||||
return '[hr][/hr]\n'
|
|
||||||
|
|
||||||
def block_text(self, text: str) -> str:
|
|
||||||
return text
|
|
||||||
|
|
||||||
def block_code(self, code: str, **attrs) -> str:
|
|
||||||
# Renders blocks of code using the language specified in Markdown
|
|
||||||
special_cases = {
|
|
||||||
'plaintext': None # Default [CODE]
|
|
||||||
}
|
|
||||||
|
|
||||||
if 'info' in attrs:
|
|
||||||
lang_info = safe_entity(attrs['info'].strip())
|
|
||||||
lang = lang_info.split(None, 1)[0].lower()
|
|
||||||
# Check if the language needs special handling
|
|
||||||
bbcode_lang = special_cases.get(lang, lang) # Use the special case if it exists, otherwise use lang as is
|
|
||||||
if bbcode_lang:
|
|
||||||
return f"[CODE={bbcode_lang}]{escape_text(code)}[/CODE]\n"
|
|
||||||
else:
|
|
||||||
return f"[CODE]{escape_text(code)}[/CODE]\n"
|
|
||||||
else:
|
|
||||||
# No language specified, render with a generic [CODE] tag
|
|
||||||
return f"[CODE]{escape_text(code)}[/CODE]\n"
|
|
||||||
|
|
||||||
def block_quote(self, text: str) -> str:
|
|
||||||
return '[QUOTE]\n' + text + '[/QUOTE]\n'
|
|
||||||
|
|
||||||
def block_html(self, html: str) -> str:
|
|
||||||
if self._escape:
|
|
||||||
return '<p>' + escape_text(html.strip()) + '</p>\n'
|
|
||||||
return html + '\n'
|
|
||||||
|
|
||||||
def block_error(self, text: str) -> str:
|
|
||||||
return '[color=red][icode]' + text + '[/icode][/color]\n'
|
|
||||||
|
|
||||||
def list(self, text: str, ordered: bool, **attrs) -> str:
|
|
||||||
depth = 0; sln = ""; tli = ""
|
|
||||||
if "depth" in attrs: depth = attrs["depth"]
|
|
||||||
if depth != 0: sln = "\n"
|
|
||||||
if depth == 0: tli = "\n"
|
|
||||||
def remove_empty_lines(text):
|
|
||||||
lines = text.split('\n')
|
|
||||||
non_empty_lines = [line for line in lines if line.strip() != '']
|
|
||||||
nli = ""; dlm = "\n"+" "*depth
|
|
||||||
if depth != 0: nli = dlm
|
|
||||||
return nli+dlm.join(non_empty_lines)
|
|
||||||
|
|
||||||
text = remove_empty_lines(text)
|
|
||||||
|
|
||||||
return sln+text+"\n"+tli
|
|
||||||
# return '[{}]'.format(tag) + text + '[/list]\n'
|
|
||||||
|
|
||||||
def list_item(self, text: str) -> str:
|
|
||||||
return '• ' + text + '\n'
|
|
||||||
|
|
||||||
def strikethrough(self, text: str) -> str:
|
|
||||||
return '[s]' + text + '[/s]'
|
|
||||||
|
|
||||||
def mark(self, text: str) -> str:
|
|
||||||
# Simulate the mark effect with a background color in BBCode
|
|
||||||
return '[mark]' + text + '[/mark]'
|
|
||||||
|
|
||||||
def insert(self, text: str) -> str:
|
|
||||||
# Use underline to represent insertion
|
|
||||||
return '[u]' + text + '[/u]'
|
|
||||||
|
|
||||||
def superscript(self, text: str) -> str:
|
|
||||||
return '[sup]' + text + '[/sup]'
|
|
||||||
|
|
||||||
def subscript(self, text: str) -> str:
|
|
||||||
return '[sub]' + text + '[/sub]'
|
|
||||||
|
|
||||||
def inline_spoiler(self, text: str) -> str:
|
|
||||||
return '[ISPOILER]' + text + '[/ISPOILER]'
|
|
||||||
|
|
||||||
def block_spoiler(self, text: str) -> str:
|
|
||||||
return '[SPOILER]\n' + text + '\n[/SPOILER]'
|
|
||||||
|
|
||||||
def footnote_ref(self, key: str, index: int):
|
|
||||||
# Use superscript for the footnote reference
|
|
||||||
return f'[sup][u][JUMPTO=fn-{index}]{index}[/JUMPTO][/u][/sup]'
|
|
||||||
|
|
||||||
def footnotes(self, text: str):
|
|
||||||
# Optionally wrap all footnotes in a specific section if needed
|
|
||||||
return '[b]Footnotes:[/b]\n' + text
|
|
||||||
|
|
||||||
def footnote_item(self, text: str, key: str, index: int):
|
|
||||||
# Define the footnote with an anchor at the end of the document
|
|
||||||
return f'[ANAME=fn-{index}]{index}[/ANAME]. {text}'
|
|
||||||
|
|
||||||
def table(self, children, **attrs):
|
|
||||||
# Starting with a full-width table by default if not specified
|
|
||||||
# width = attrs.get('width', '100%') # comment out until XF 2.3
|
|
||||||
# return f'[TABLE width="{width}"]\n' + children + '[/TABLE]\n' # comment out until XF 2.3
|
|
||||||
return '[TABLE]\n' + children + '[/TABLE]\n'
|
|
||||||
|
|
||||||
def table_head(self, children, **attrs):
|
|
||||||
return '[TR]\n' + children + '[/TR]\n'
|
|
||||||
|
|
||||||
def table_body(self, children, **attrs):
|
|
||||||
return children
|
|
||||||
|
|
||||||
def table_row(self, children, **attrs):
|
|
||||||
return '[TR]\n' + children + '[/TR]\n'
|
|
||||||
|
|
||||||
def table_cell(self, text, align=None, head=False, **attrs):
|
|
||||||
# BBCode does not support direct cell alignment,
|
|
||||||
# use [LEFT], [CENTER], or [RIGHT] tags
|
|
||||||
|
|
||||||
# Use th for header cells and td for normal cells
|
|
||||||
tag = 'TH' if head else 'TD'
|
|
||||||
|
|
||||||
# Initialize alignment tags
|
|
||||||
alignment_start = ''
|
|
||||||
alignment_end = ''
|
|
||||||
|
|
||||||
if align == 'center':
|
|
||||||
alignment_start = '[CENTER]'
|
|
||||||
alignment_end = '[/CENTER]'
|
|
||||||
elif align == 'right':
|
|
||||||
alignment_start = '[RIGHT]'
|
|
||||||
alignment_end = '[/RIGHT]'
|
|
||||||
elif align == 'left':
|
|
||||||
alignment_start = '[LEFT]'
|
|
||||||
alignment_end = '[/LEFT]'
|
|
||||||
|
|
||||||
return f'[{tag}]{alignment_start}{text}{alignment_end}[/{tag}]\n'
|
|
||||||
|
|
||||||
def task_list_item(self, text: str, checked: bool = False) -> str:
|
|
||||||
# Using emojis to represent the checkbox
|
|
||||||
checkbox_emoji = '' if checked else ''
|
|
||||||
return checkbox_emoji + ' ' + text + '\n'
|
|
||||||
|
|
||||||
def def_list(self, text: str) -> str:
|
|
||||||
# No specific BBCode tag for <dl>, so we just use the plain text grouping
|
|
||||||
return '\n' + text + '\n'
|
|
||||||
|
|
||||||
def def_list_head(self, text: str) -> str:
|
|
||||||
return '[b]' + text + '[/b]' + ' ' + ':' + '\n'
|
|
||||||
|
|
||||||
def def_list_item(self, text: str) -> str:
|
|
||||||
return '[INDENT]' + text + '[/INDENT]\n'
|
|
||||||
|
|
||||||
def abbr(self, text: str, title: str) -> str:
|
|
||||||
if title:
|
|
||||||
return f'[abbr={title}]{text}[/abbr]'
|
|
||||||
return text
|
|
Loading…
x
Reference in New Issue
Block a user