docs/scripts/migrate.py

158 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import os
import re
import frontmatter
def get_md_files(content_dir: str) -> list[str]:
md_files = []
for root, _, files in os.walk(content_dir):
for filename in files:
if filename.endswith(".md"):
md_files.append(os.path.join(root, filename))
return md_files
def convert(filepath: str) -> frontmatter.Post:
page = frontmatter.load(filepath)
try:
page["aliases"] = page["redirect_from"]
del page["redirect_from"]
except:
pass
# handle CLI reference stubs
if "/engine/reference/commandline/" in filepath:
try:
if page["datafolder"]:
page = convert_cli(page)
return page
except:
pass
# handle sample stubs
if "/samples/" in filepath:
page = convert_sample(page)
return page
# all other files
convert_other(page)
return page
def convert_cli(page: frontmatter.Post) -> frontmatter.Post:
page["layout"] = "cli"
page.content = re.sub(r"\{% include cli.*", "", page.content)
page.content = re.sub(
r"\{% include (.*(md|html)) %}", r'{{< include "\1" >}}', page.content
)
return page
def convert_sample(page: frontmatter.Post) -> frontmatter.Post:
page.content = re.sub(r"\{% include_relative samples_body.*", "", page.content)
return page
def convert_other(page: frontmatter.Post) -> frontmatter.Post:
page.content = re.sub(r"\{:\s*target=(.|\n)*?}", "", page.content)
page.content = re.sub(r"\{%-?\s*include eula(.|\n)*?}", "", page.content)
page.content = re.sub(r"\{%\sraw(.|\n)*?}", "", page.content)
page.content = re.sub(r"\{%\sendraw(.|\n)*?}", "", page.content)
page.content = re.sub(
r"\{:\s*\.(important|warning|tip|experimental|restricted).*?}",
r"{ .\1 }",
page.content,
)
page.content = re.sub(
r"\{:\s*(\.invertible|\.text-center|style=|width=|height=|class=|\.accept-eula).*?}",
"",
page.content,
)
page.content = re.sub(
r"\{% include (.*(md|html)) %}", r'{{< include "\1" >}}', page.content
)
page.content = re.sub(
r"!\[(.*?)]\((.*?)\)\{:\s*.inline\s*}",
r'{{< inline-image src="\2" alt="\1" >}}',
page.content,
)
page.content = re.sub(
r"\[(.*)?]\((.*?)\)\{:\s*\.button.*}",
r'{{< button text="\1" url="\2" >}}',
page.content,
)
page.content = re.sub(
r"\{% include desktop-install\.md (.*) %}",
r"{{< desktop-install \1 >}}",
page.content,
)
page.content = re.sub(
r"\{% include release-date\.html (.*) %}",
r"{{< release-date \1 >}}",
page.content,
)
page.content = re.sub(
r"\{% include (admin-(.*)?)\.md (.*) %}",
r"{{% admin-\2 \3 %}}",
page.content,
)
page.content = re.sub(
r"\{\{\s*site\.(.*?)\s*}}", r'{{% param "\1" %}}', page.content
)
page.content = re.sub(r'\{:\s*id="(.*)" ?}', r"{ #\1 }", page.content)
# handle inline assign
assign_pattern = re.compile(r"{% assign (.*) = (['\"].*) %}\n?")
assign = assign_pattern.search(page.content)
if assign:
key = assign.group(1)
value = assign.group(2)
page[key] = value[1:-1]
page.content = assign_pattern.sub("", page.content)
page.content = re.sub(
rf'{{{{\s*{key}\s*}}}}', rf'{{{{% param "{key}" %}}}}', page.content
)
return page
def write_results(filepath: str, page: frontmatter.Post) -> None:
f = open(filepath, "w")
if "/includes/" in filepath:
# skip front matter for includes
data = page.content
else:
data = frontmatter.dumps(page, sort_keys=False)
f.write(data)
f.close()
if __name__ == "__main__":
parser = argparse.ArgumentParser(
prog="Migrate",
description="Convert content from Jekyll to Hugo",
)
parser.add_argument("-d", type=str, help="Content directory")
parser.add_argument("-f", type=str, help="Single input file")
args = parser.parse_args()
if args.f:
converted_page = convert(args.f)
write_results(args.f, converted_page)
os._exit(os.EX_OK)
content_dir = os.path.join(os.getcwd(), "content")
if args.d:
content_dir = os.path.abspath(args.d)
md_files = get_md_files(content_dir)
for filepath in md_files:
converted_page = convert(filepath)
write_results(filepath, converted_page)
os._exit(os.EX_OK)